Den*_*is 4 c permissions gdb setuid
这实际上是一个由三部分组成的问题,我将在下面解释,但问题是:
我有一个在 Linux(多个发行版)上运行的 C 程序,通常由具有普通权限的用户运行,但程序的某些部分必须以 root 权限运行。为此,我使用了 set-UID 标志,就目前而言,效果很好。
然而,现在我想用普通用户权限调试程序,我发现我有一个catch-22。我刚刚添加了一个函数来创建临时文件 (/tmp/my_name-XXXXXX),并且该函数是从程序内的许多点调用的。无论出于何种原因,该函数在运行时都会发出以下消息:
sh: /tmp/my_name-hhnNuM: Permission denied
Run Code Online (Sandbox Code Playgroud)
(当然,实际名称有所不同。)然而,该程序能够执行原始套接字函数,我绝对知道除 root 之外的用户无法执行该函数。(如果我删除 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
Run Code Online (Sandbox Code Playgroud)
所以我的问题(排名不分先后):
1 在 gdb 下正确调试 setuid 应用程序的唯一方法是以 root 身份运行 gdb。对于 setuid 应用程序执行此操作的最明智方法是在应用程序启动后附加到该应用程序。执行此操作的一个快速技巧是在 setuid 应用程序中添加一行:
kill(getpid(), SIGSTOP);
Run Code Online (Sandbox Code Playgroud)
这会导致它在此时停止,然后使用以下命令附加 gdb:
sudo gdb <application> <pid>
Run Code Online (Sandbox Code Playgroud)
然后您将连接到该应用程序并可以正常调试它。
2 sudo 更改了规则,因为它允许将当前用户环境中的各种项目导出到 root 用户环境中。这完全取决于当前的 sudo 配置,并且可能会给您带来与 setuid 应用程序截然不同的环境,这就是为什么您需要依赖诸如停止应用程序然后在运行时附加到它之类的技巧。
此外,应用程序中可能有逻辑来检测它是否在 setuid 环境中运行,而在 sudo 下运行时实际情况并非如此 - 请记住 sudo 将所有进程的 id 字段(真实 uid、有效 uid 和保存的 uid)设置为相同value,而 setuid 没有(真正的 uid 仍然是原始调用者的 uid)。您可以使用getresuid()调用来确定三个变量的状态。
3问题是该Permission Denied
消息有一个前缀sh:
; 这似乎意味着正在执行另一个试图访问该文件的子进程。调用 mkstemp 后,您可能需要放宽读取文件的权限,以便子进程能够读取该文件。