我的Linux守护程序有问题。它从root特权开始,进行一些配置,然后通过切换到某些用户和组永久放弃特权并继续工作。切换到非特权用户的操作如下:
void switch_to_user_group(std::string const& username, std::string const& groupname)
{
// Switch to user/group
gid_t gid = getgid();
if (!groupname.empty())
{
gid = get_group_id(groupname);
if (0 != setgid(gid))
{
std::cout << "Failed to switch to group " << gid << std::endl;
std::abort();
}
}
if (!username.empty())
{
uid_t uid = get_user_id(username);
if (initgroups(username.c_str(), gid) != 0)
{
std::cout << "initgroups failed" << std::endl;
std::abort();
}
if (0 != setuid(uid))
{
std::cout << "Failed to switch to user " << uid << std::endl;
std::abort();
}
}
}
切换正常执行,我可以在用户下看到ps进程和top运行。问题是即使删除了特权,我也无法从gdb附加到该进程。输出为:
Attaching to process 15716
Could not attach to process. If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.
我在进程切换到的同一用户下运行gdb,并且能够附加到最初在该用户下启动的其他进程。我在Kubuntu 13.10(禁用YAMA),Debian 6和7上尝试了相同的结果。
所以我的问题是:
为什么ptrace无法附加到具有与gdb相同的有效UID的进程?
是否可以某种方式放弃程序的特权,以便可以从无特权的gdb附加到它?怎么样?
谢谢。
最佳答案
我自己找到了解决方案。
内核中的每个进程都有一个“ dumpable”标志。当进程执行setuid或setgid时(至少在我来说,当进程放弃特权时),此标志将被清除,普通用户无法使用调试器附加到该进程,并且该进程崩溃也不会产生崩溃转储。出于安全考虑,这样做是为了保护进程内存中以提升的特权获得的任何敏感数据。
为了解决该问题,该过程可以通过将“ dumpable”标志设置为1来明确允许调试。
prctl(PR_SET_DUMPABLE, 1);
这必须在setgid / setuid调用之后完成。
关于ptrace - 为什么在setuid之后ptrace不附加到进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21337923/