GDB调试GameOfChance程序遇权限问题及UID相关疑问
首先,我们来拆解你遇到的核心矛盾:SUID权限的程序在普通Bash中能正常运行,但直接在GDB中启动就会出现权限不足,这本质是GDB的安全机制在起作用。
为什么Bash中普通用户能正常运行?
你的GameOfChance可执行文件权限是-rwsrwxr-x 1 root root,其中的s位表示这是一个SUID(Set User ID)程序。当普通用户(masterdungeon,UID1000)运行它时,程序的有效UID会切换为文件所有者的UID(也就是root的UID 0)——这就是SUID的核心作用:让普通用户以root权限执行特定程序。
而/var/gameofchance.data的权限是-rw------- 1 root masterdungeon,root用户拥有完全读写权限,所以程序以有效UID root运行时,自然能正常打开并写入这个文件。
为什么GDB中直接运行会失败?
GDB默认有一个安全设置:启动程序时会自动清除SUID/SGID权限位,也就是程序运行时的有效UID会保持为当前用户的UID(1000),而不是切换为root。这时候,普通用户masterdungeon没有权限写入root所有的/var/gameofchance.data,所以会触发Permission denied错误。
你在断点处看到的uid=1000是getuid()返回的真实UID(也就是你登录的用户ID),而不是有效UID(程序实际拥有的权限ID)。如果在GDB中未开启SUID支持时查看有效UID(调用geteuid()),会发现它也是1000,而不是0。
解决方法:让GDB保留SUID权限运行程序
有两种可靠的方式解决这个问题:
方法1:在GDB中启用SUID支持
这是最推荐的方式,不需要修改文件权限:
- 启动GDB:
gdb ./GameOfChance - 在GDB提示符下输入命令,开启SUID权限保留:
set suid on - 然后执行
run,程序就会像在Bash中一样,以有效UID root运行,顺利完成玩家注册。
你也可以在启动GDB时直接带上这个设置,一步到位:
gdb -ex 'set suid on' ./GameOfChance
方法2:临时修改数据文件权限(不推荐,调试后需复原)
如果你只是临时调试,也可以给数据文件添加普通用户写权限:
sudo chmod o+w /var/gameofchance.data
调试完成后,记得改回原来的安全权限:
sudo chmod o-w /var/gameofchance.data
这种方法会降低系统安全性,只适合临时测试用。
验证思路
你可以在register_player函数的open调用前加一个断点,然后在GDB中分别查看开启/关闭SUID时的有效UID:
break register_player run # 查看有效UID call geteuid()
开启set suid on后,这个值会返回0(root的UID),关闭时返回1000(masterdungeon的UID),这就能直观验证权限切换的差异。
内容的提问来源于stack exchange,提问作者sweetpoision

