C - 程序仅在与GDB一起运行时才能获取文件描述符

jay*_*ren 5 c linux

我不是专业的C程序员.我在使用GDB调试程序时遇到问题.(我试图修复的错误与我在这里询问的问题无关.)我的问题是程序在我直接从shell运行二进制文件时运行正常,但是当我使用GDB运行它时程序崩溃了.

以下是一些可能有用的程序信息:它是一个20多年历史的数据库软件,最初是为Solaris编写的(我认为)但是从移植到Linux,这是setuid(但不是root,感谢上帝) .

尝试打开文件进行写入时,程序在GDB中崩溃.使用GDB,我能够确定发生崩溃,因为以下系统调用失败:

fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
Run Code Online (Sandbox Code Playgroud)

为了澄清:path存在的锁文件的路径.如果存在锁定文件,则程序在进入此系统调用之前会干净地关闭.

我不明白为什么这个系统调用会失败,因为1)该程序运行的用户在包含的目录上运行rwx权限path(我通过检查存储的变量的值验证了这一点path),以及2)程序成功打开我不使用GDB进行调试时写入的文件.

有什么理由我不能

tor*_*rek 8

关键是这一点:

...是setuid(但不是root,感谢上帝).

当您在(任何)调试器下运行程序(使用任何stop-and-inspect/modify程序工具)时,内核会禁用setuid-ness,即使对于非root setuid也是如此.

如果你考虑一下这有点意义.考虑一个保持"高分"文件的游戏,并使用"setuid游戏"来执行此操作,其中:

fd = open(GAME_SCORE_FILE, open_mode, file_mode);
score_data = read_scores(fd);
/* set breakpoint here or so */
if (check_for_new_high_score(current_score, score_data)) {
    printf("congratulations, you've entered the High Scores records!\n");
    save_scores(fd, score_data);
}
close(fd);
Run Code Online (Sandbox Code Playgroud)

对"高分"文件的访问受文件权限的保护:只有"游戏"用户才能写入.

但是,如果您在调试器下运行游戏,则可以在标记的行处设置断点,并将current_score数据设置为某个超高值,然后恢复该程序.

为了避免允许调试器破坏setuid程序的内部数据,内核只在运行启用了调试工具的代码时禁用setuid-ness.如果您可以su(或者sudo其他)向用户表明您无论是否进行任何调试都拥有权限,那么您可以以该用户身份运行gdb本身,以便该程序以其"已经"设置的用户身份运行.