1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
4 * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
5 *
6 * Test PR_GET_NO_NEW_PRIVS and PR_SET_NO_NEW_PRIVS of prctl(2).
7 *
8 * 1)Return the value of the no_new_privs bit for the calling thread.
9 * A value of 0 indicates the regular execve(2) behavior. A value of
10 * 1 indicates execve(2) will operate in the privilege-restricting mode.
11 * 2)With no_new_privs set to 1, diables privilege granting operations
12 * at execve-time. For example, a process will not be able to execute a
13 * setuid binary to change their uid or gid if this bit is set. The same
14 * is true for file capabilities.
15 * 3)The setting of this bit is inherited by children created by fork(2),
16 * and preserved across execve(2). We also check NoNewPrivs field in
17 * /proc/self/status if it supports.
18 */
19
20 #include "prctl06.h"
21
22 static uid_t nobody_uid;
23 static gid_t nobody_gid;
24 static int proc_flag = 1;
25 static char *proc_sup = "Yes";
26
do_prctl(void)27 static void do_prctl(void)
28 {
29 char ipc_env_var[1024];
30 char *const argv[] = {BIN_PATH, "After execve, parent process", proc_sup, NULL};
31 char *const childargv[] = {BIN_PATH, "After execve, child process", proc_sup, NULL};
32 char *const envp[] = {ipc_env_var, NULL };
33 int childpid;
34
35 check_no_new_privs(0, "parent", proc_flag);
36
37 TEST(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
38 if (TST_RET == -1) {
39 tst_res(TFAIL | TTERRNO, "prctl(PR_SET_NO_NEW_PRIVS) failed");
40 return;
41 }
42 tst_res(TPASS, "prctl(PR_SET_NO_NEW_PRIVS) succeeded");
43
44 SAFE_SETGID(nobody_gid);
45 SAFE_SETUID(nobody_uid);
46
47 sprintf(ipc_env_var, IPC_ENV_VAR "=%s", getenv(IPC_ENV_VAR));
48
49 childpid = SAFE_FORK();
50 if (childpid == 0) {
51 check_no_new_privs(1, "After fork, child process", proc_flag);
52 execve(BIN_PATH, childargv, envp);
53 tst_brk(TFAIL | TTERRNO,
54 "child process failed to execute prctl_execve");
55
56 } else {
57 tst_reap_children();
58 check_no_new_privs(1, "parent process", proc_flag);
59 execve(BIN_PATH, argv, envp);
60 tst_brk(TFAIL | TTERRNO,
61 "parent process failed to execute prctl_execve");
62 }
63 }
64
verify_prctl(void)65 static void verify_prctl(void)
66 {
67 int pid;
68
69 pid = SAFE_FORK();
70 if (pid == 0) {
71 do_prctl();
72 exit(0);
73 }
74 }
75
setup(void)76 static void setup(void)
77 {
78 struct passwd *pw;
79 int field;
80
81 pw = SAFE_GETPWNAM("nobody");
82 nobody_uid = pw->pw_uid;
83 nobody_gid = pw->pw_gid;
84
85 SAFE_CP(TESTBIN, TEST_REL_BIN_DIR);
86
87 SAFE_CHOWN(BIN_PATH, 0, 0);
88 SAFE_CHMOD(BIN_PATH, SUID_MODE);
89
90 if (FILE_LINES_SCANF(PROC_STATUS, "NoNewPrivs:%d", &field)) {
91 tst_res(TCONF, "%s doesn't support NoNewPrivs field", PROC_STATUS);
92 proc_flag = 0;
93 proc_sup = "No";
94 }
95
96 TEST(prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));
97 if (TST_RET == 0) {
98 tst_res(TINFO, "kernel supports PR_GET/SET_NO_NEW_PRIVS");
99 return;
100 }
101
102 if (TST_ERR == EINVAL)
103 tst_brk(TCONF,
104 "kernel doesn't support PR_GET/SET_NO_NEW_PRIVS");
105
106 tst_brk(TBROK | TTERRNO,
107 "current environment doesn't permit PR_GET/SET_NO_NEW_PRIVS");
108 }
109
110 static const char *const resfile[] = {
111 TESTBIN,
112 NULL,
113 };
114
115 static struct tst_test test = {
116 .resource_files = resfile,
117 .setup = setup,
118 .test_all = verify_prctl,
119 .forks_child = 1,
120 .needs_root = 1,
121 .mount_device = 1,
122 .mntpoint = MNTPOINT,
123 .child_needs_reinit = 1,
124 };
125