uid/gid变更导致无法生成coredump的问题
项目中遇到一个问题,某个进程已经通过prctl(PR_SET_DUMPABLE, 1)
将其设置为dumpable,但还是无法生成coredump,其他进程能生成,说明系统配置没问题。最终查下来发现,是因为该进程变更uid/gid导致的。
下面用一个简化后的例子说明这个问题:
- 在系统中创建一个新用户
test
:1
sudo adduser test
- 执行命令
cat /etc/passwd
查看用户test
的uid
, 我的是10021
test:x:1002:1002:,,,:/home/test:/bin/bash
简化后的示例程序如下,注意用实际的
uid
替换宏TEST_UID的值:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#include <stdio.h> #include <sys/prctl.h> #include <unistd.h> #define TEST_UID (1002) int main() { // 强制设置允许coredump prctl(PR_SET_DUMPABLE, 1); // 获取并打印当前dumpable状态 int dumpable = prctl(PR_GET_DUMPABLE); printf("Before change uid, dumpable state of process %u is %d\n", getpid(), dumpable); // 在此之前通过 kill -11 pid 可以生成coredump getchar(); // 改变进程的用户ID setuid(TEST_UID); // 获取并打印当前dumpable状态 // dumpable的值被重置为用户1002的配置/proc/sys/fs/suid_dumpable dumpable = prctl(PR_GET_DUMPABLE); printf("After change uid, dumpable state of process %u is %d\n", getpid(), dumpable); // 现在还能不能生成coredump取决于用户test的配置/proc/sys/fs/suid_dumpable getchar(); return 0; }
- 编译运行,注意用root权限执行,因为上面代码中调用了
setuid
,普通用户是没这个权限的:1 2
gcc gen_coredump.c sudo ./a.out
输出如下,可以看到dumpable的值在setuid后确实变了:
1 2 3
Before change uid, dumpable state of process 1191147 is 1 After change uid, dumpable state of process 1191147 is 0
上述程序通过getchar设置了两个暂停点,感兴趣的同学可以试下,是不是前半段能生成coredump,后半段就无法生成了。
- 这是因为setuid后,
dumpable
被设置成新用户test
中/proc/sys/fs/suid_dumpable
的值,参考ptrace(2):
- 通过下面的命令可以查看用户
test
中/proc/sys/fs/suid_dumpable
的值,我的设备上确实是0(不同系统可能有差异)1 2
su test cat /proc/sys/fs/suid_dumpable
- 系统的这种行为,主要是出于安全考虑:
- 一般执行setuid/setgid的程序,都是先运行在特权模式(比如以root运行),执行一些只有特权用户才能执行的任务,然后修改uid/gid降权,运行在普通模式。
- 特权模式下执行的代码,可能在内存中留下了痕迹(比如将密码读取到了内存),如果生成了coredump,或者允许gdb attach上去,可能会造成信息泄露。
- 所以系统在uid/gid变更后,默认禁止生成coredump,也不能通过gdb attach进行debug。
- 比较典型的例子是Android系统中zygote进程fork应用进程的场景:
- zygote进程刚fork出来的应用进程是root权限,此时它可以执行普通用户无法执行的任务,比如给应用挂载数据目录等。
- 执行完这些任务,在进入用户代码之前就降权,降权之后无法再提权,从而避免用户代码干坏事。
This post is licensed under CC BY 4.0 by the author.