调试一个setuid程序/使用setuid时出现“权限被拒绝”错误

4

这实际上是一个三部分问题,我将在下面解释,但问题是:

  • 如何使用gdb,以root权限运行程序的一部分,其余部分以普通方式运行?
  • 为什么我在使用mkstemp在setuid(到root)程序中创建/tmp中的文件时会收到“permission denied”错误消息?
  • 为什么“sudo program_name”与具有setuid到root的“./program_name”相比会有任何不同表现?

我在Linux上运行一个C程序(多个发行版),通常由具有普通权限的用户运行,但程序的某些部分必须以root权限运行。为此,我使用了set-UID标志,这在功能上已经可以正常工作。

然而,现在我想使用普通用户权限调试程序,但我遇到了一个困境。我刚刚添加了一个用于创建临时文件(/tmp/my_name-XXXXXX)的函数,并且该函数从程序的许多点调用。由于某种原因,当运行该函数时,它会发出以下消息:

sh: /tmp/my_name-hhnNuM: Permission denied

(当然,实际名称可能会有所不同。)然而,该程序能够执行我绝对知道普通用户无法执行的原始套接字函数。 (如果我删除setuid标志,程序将彻底失败。)
如果我在没有sudo权限的情况下通过gdb运行此程序,则该程序会在原始套接字部分崩溃(因为gdb似乎不能-或者可能不能-尊重程序上的setuid标志)。 如果我在“sudo gdb”下运行它,则一切正常。 如果我将其作为“sudo ./my_name”运行,则一切正常。
这是该程序的ls -l输出:
-rwsr-xr-x 1 root root 48222 Jun 23 08:14 my_name

以下是我的问题,没有特定的顺序:

  • 在gdb下,(如何)可以运行程序的不同部分以不同有效UID的方式运行?
  • 当./program设置为root的set-uid时,“sudo ./program”和“./program”有什么不同?
  • 为什么在由普通用户调用的setuid(到root)程序中调用mkstemp会失败?
1个回答

5

1在gdb下正确调试setuid应用程序的唯一方法是以root身份运行gdb。对于setuid应用程序,最明智的做法是在应用程序启动后附加到应用程序。一个快速的技巧是在setuid应用程序中添加一行:

kill(getpid(), SIGSTOP);

这会导致程序在此处停止,然后您可以使用以下命令附加gdb:

sudo gdb <application> <pid>

然后您将附加到应用程序并可以像正常调试一样进行调试。

2 sudo更改规则,因为它允许从当前用户环境中导出各种项目到根用户环境。这完全取决于当前sudo配置,并且可能会使您拥有与setuid应用程序完全不同的环境,这就是为什么您需要依靠诸如停止应用程序,然后在运行时附加到它之类的技巧。

此外,应用程序中可能存在逻辑来检测是否在setuid环境下运行,而在sudo下运行时实际上并非如此-请记住,sudo设置所有进程的ID字段(实际UID,有效UID和保存UID)为相同的值,而setuid则不会(真实UID仍然是原始调用者的UID)。您可以使用getresuid()调用来确定三个变量的状态。

3 问题在于“Permission Denied”消息具有“sh:”前缀;这似乎意味着正在执行另一个子进程,该进程正在尝试访问该文件。在调用mkstemp之后,您可能希望放宽读取文件的权限,以便子进程能够读取该文件。


太好了!mkstemp()被用来创建电子邮件消息,然后sendmail将读取文件并发送它。我没有想到,当然,sendmail进程没有采用其父进程的权限。(在我通常编程的平台上:AS/400 / iSeries / System i,这种采用是自然的。这就是我的借口,我会坚持不懈的!)谢谢!也感谢您提醒如何调试运行中的进程! - Dennis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接