5

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

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

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

fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);

为了澄清:path不应该存在的锁定文件的路径。如果锁文件存在,那么程序在到达这个系统调用之前就彻底关闭了。

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

有什么理由我不能

4

1 回答 1

8

关键是这个位:

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

当您在(任何)调试器下(使用任何停止和检查/修改程序工具)运行程序时,内核禁用 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);

对“高分”文件的访问受到文件权限的保护:只有“游戏”用户可以对其进行写入。

但是,如果您在调试器下运行游戏,则可以在标记行设置断点,并将 current_score 数据设置为某个超高值,然后继续执行程序。

为了避免调试器破坏 setuid 程序的内部数据,内核在启用调试工具的情况下运行代码时简单地禁用 setuid-ness。如果您可以su(或sudo其他任何方式)向用户表明无论任何调试如何您都具有权限,那么您可以以该用户身份运行 gdb 本身,以便程序以它“将拥有”setuid 的用户身份运行。

于 2013-11-05T00:05:50.073 回答