写在前面
在阅读 seccomp manual 的时候了解到进程的 no_new_privs 属性,man 了一下 prctl 发现帮助文档中的描述很难理解,于是通过一些例子研究了下,摸着些头脑,在本文中记录一下。
no_new_privs 的使用示例
将如下代码保存为 test.c,并编译生成 a.out 文件。
#include <errno.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
if (argc < 2) {
printf("%s argument\n", argv[0]);
exit(-1);
}
if (argc == 3) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("prctl(NO_NEW_PRIVS)");
return 1;
}
}
return system(argv[1]);
}
测试示例
no_new_privs 是否设置对 sudo 程序执行的影响
sudo 命令的权限:
[longyu@debian:09:13:05] tmp $ ls -lh /usr/bin/sudo
-rwsr-xr-x 1 root root 179K Feb 27 2021 /usr/bin/sudo
sudo 命令具有 suid root 权限。
1. 设置 no_new_privs 时运行 sudo
[longyu@debian:09:06:51] tmp $ ./a.out sudo 1
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
无法运行!
2. 未设置 no_new_privs 时运行 sudo
[longyu@debian:09:07:29] tmp $ ./a.out 'sudo su'
[sudo] password for longyu:
root@debian:/tmp#
正常运行!
no_new_privs 是否设置对 ping 程序执行的影响
ping 程序的权限:
[longyu@debian:09:11:09] tmp $ ls -lh /usr/bin/ping
-rwxr-xr-x 1 root root 76K Feb 3 2021 /usr/bin/ping
[longyu@debian:09:11:55] tmp $ sudo getcap /usr/bin/ping
/usr/bin/ping cap_net_raw=ep
ping 没有 suid root 权限,有 cap_net_raw 权限。
1 . 设置 no_new_privs 时运行 ping
[longyu@debian:09:09:42] tmp $ ./a.out 'ping www.baidu.com' 1
ping: socket: Operation not permitted
无法运行!
2. 未设置 no_new_privs 时运行 ping
[longyu@debian:09:09:35] tmp $ ./a.out 'ping www.baidu.com'
PING www.baidu.com (39.156.66.18) 56(84) bytes of data.
64 bytes from 39.156.26.18 (39.156.63.18): icmp_seq=1 ttl=52 time=38.7 ms
正常运行!
单个进程设置 no_new_privs 权限后尝试关闭
将如下代码保存为 test-new.c 并编译生成 a.out 文件:
#include <errno.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
if (argc < 2) {
printf("%s argument\n", argv[0]);
exit(-1);
}
if (argc == 3) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("prctl(NO_NEW_PRIVS)");
return 1;
}
if (prctl(PR_SET_NO_NEW_PRIVS, 0, 0, 0, 0)) {
perror("prctl(NO_NEW_PRIVS)");
return 1;
}
}
return system(argv[1]);
}
测试记录如下:
longyu@debian:/tmp$ ./a.out sudo 1
prctl(NO_NEW_PRIVS): Invalid argument
strace 跟踪得到的关键信息:
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0
prctl(PR_SET_NO_NEW_PRIVS, 0, 0, 0, 0) = -1 EINVAL (Invalid argument)
当进程设置了 no_new_privs 后无法关闭!
子进程中尝试关闭 no_new_privs 配置
将如下代码保存为 test1.c 文件后编译生成 test1。
#include <errno.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
if (prctl(PR_SET_NO_NEW_PRIVS, 0, 0, 0, 0)) {
perror("set failed");
return 1;
}
return 0;
}
使用第一个示例中的程序运行此程序,测试结果如下:
longyu@debian:/tmp$ ./a.out ./test1 1
set failed: Invalid argument
当父进程设置了 no_new_privs 的权限后,子进程无法关闭。
manual 中的描述信息
man prctl 中得到如下信息:
PR_SET_NO_NEW_PRIVS (since Linux 3.5)
Set the calling thread's no_new_privs attribute to the value in arg2. With no_new_privs set to 1, execve(2) prom‐
ises not to grant privileges to do anything that could not have been done without the execve(2) call (for example,
rendering the set-user-ID and set-group-ID mode bits, and file capabilities non-functional). Once set, the
no_new_privs attribute cannot be unset. The setting of this attribute is inherited by children created by fork(2)
and clone(2), and preserved across execve(2).
Since Linux 4.10, the value of a thread's no_new_privs attribute can be viewed via the NoNewPrivs field in the
/proc/[pid]/status file.
For more information, see the kernel source file Documentation/userspace-api/no_new_privs.rst (or Documenta‐
tion/prctl/no_new_privs.txt before Linux 4.13). See also seccomp(2).
上述信息表明当设置了 no_new_privs 标志后,execve 会保证不会赋予运行进程新的权限, suid、sgid 权限会失效并且文件特殊权限也会失效,这意味着 execve 运行的新程序不会拥有比原进程更高的权限。
no_new_privs 标志一旦设置就不能撤销,使用 fork 与 clone 创建的子进程会继承父进程的此标志,且在 execve 的时候也会保留。
这里需要理解的点在于 execve 那些设置了 suid、sgid bit、Linux capabilities 的可执行文件时,未设置 no_new_privs 属性时,进程将会拥有比原进程更高的权限,no_new_privs 可以理解为是对 execve 提权操作的限制,在一些场景中能够增强系统的安全性。
参考链接
https://segmentfault.com/a/1190000041968184?utm_source=sf-similar-article