1 #include <sys/types.h>
2 #include <sys/wait.h>
3 #include <stdio.h>
4 #include <unistd.h>
5
6 int max_error = 5;
7 #include "common.h"
8
9
10 int subtest = -1;
11
12 void test_self(void);
13 void test_setnone(void);
14 void test_setuid(void);
15 void test_setgid(void);
16 void test_effugid(void);
17 int execute(const char *prog, const char *arg);
18
execute(const char * prog,const char * arg)19 int execute(const char *prog, const char *arg)
20 {
21 pid_t childpid;
22 int status;
23 char cmd[30];
24
25 snprintf(cmd, sizeof(cmd), "./%s", prog);
26
27 childpid = fork();
28 if (childpid == (pid_t) -1) {
29 return(-2);
30 } else if (childpid == 0) {
31 if (execl(cmd, prog, arg, NULL) == -1) {
32 exit(-2);
33 }
34 return(-2); /* Never reached */
35 } else {
36 wait(&status);
37 }
38
39 return(WEXITSTATUS(status));
40 }
41
test_setgid(void)42 void test_setgid(void)
43 {
44 /* Execve a new process that has setgid bits set */
45 subtest = 3;
46
47 /* When we exec a new process which has setgid set, that process should
48 * be tainted.
49 */
50 system("chmod 2755 setgid");
51 if (execute("setgid", "0000") != 1) e(2);
52
53 /* When we exec a new process which has setgid set, but unsets that bit
54 * before calling issetugid() should still be tainted
55 */
56 system("chmod 2755 setgid");
57 if (execute("setgid", "0755") != 1) e(3);
58
59 /* When we exec a new process which has setgid set, and then also sets
60 * setuid before calling issetugid() should still be tainted
61 */
62 system("chmod 2755 setgid");
63 if (execute("setgid", "06755") != 1) e(4);
64
65 /* When we exec a new process that has setgid set, and which upon
66 * execution forks, the forked child should also be tainted */
67 system("chmod 2755 setgidfork");
68 if (execute("setgidfork", "0000") != 1) e(5);
69 }
70
test_setuid(void)71 void test_setuid(void)
72 {
73 /* Execve a new process that has setuid bits set */
74 subtest = 4;
75
76 /* When we exec a new process which has setuid set, that process should
77 * be tainted.
78 */
79 system("chmod 4755 setuid");
80 if (execute("setuid", "0000") != 1) e(1);
81
82 /* When we exec a new process which has setuid set, but unsets that bit
83 * before calling issetugid() should still be tainted
84 */
85 system("chmod 4755 setuid");
86 if (execute("setuid", "0755") != 1) e(2);
87
88 /* When we exec a new process which has setuid set, and then also sets
89 * setgid before calling issetugid() should still be tainted
90 */
91 system("chmod 4755 setuid");
92 if (execute("setuid", "06755") != 1) e(3);
93
94 /* When we exec a new process that has setgid set, and which upon
95 * execution forks, the forked child should also be tainted */
96 system("chmod 4755 setuidfork");
97 if (execute("setuidfork", "0000") != 1) e(4);
98
99 }
100
test_setugid(void)101 static void test_setugid(void)
102 {
103 /* Execve a new process that has setuid and setgid bits set */
104 subtest = 5;
105
106 /* When we exec a new process which has setugid set, that
107 * process should be tainted.
108 */
109 system("chmod 6755 setugid");
110 if (execute("setugid", "0000") != 1) e(1);
111
112 /* When we exec a new process which has setugid set, but unsets those bits
113 * before calling issetugid() should still be tainted
114 */
115 system("chmod 6755 setugid");
116 if (execute("setugid", "0755") != 1) e(2);
117
118 /* When we exec a new process that has setugid set, and which upon
119 * execution forks, the forked child should also be tainted */
120 system("chmod 6755 setugidfork");
121 if (execute("setugidfork", "0000") != 1) e(4);
122
123 }
124
test_effugid(void)125 void test_effugid(void)
126 {
127 /* Test taint status with different effective uid and gid */
128 pid_t childpid;
129 int status;
130
131 subtest = 6;
132
133 /* Start with effective uid */
134 childpid = fork();
135 if (childpid == (pid_t) -1) e(1);
136 else if (childpid == 0) {
137 /* We're the child */
138
139 /* We should be tainted */
140 if (issetugid() != 1) e(2);
141
142 /* Now execute a program without set{u,g}id; should not be tainted */
143 system("chmod 755 nobits");
144 if (execute("nobits", "0000") != 0) e(3);
145
146 /* Change effective uid into current+42 and try nobits again. This time
147 * it should be tainted */
148 if (seteuid(geteuid() + 42) != 0) e(4);
149 if (execute("nobits", "0000") != 1) e(5);
150 exit(EXIT_SUCCESS);
151 } else {
152 /* We're the parent, wait for the child to finish */
153 wait(&status);
154 }
155
156 /* Now test effective gid */
157 childpid = fork();
158 if (childpid == (pid_t) -1) e(1);
159 else if (childpid == 0) {
160 /* We're the child */
161
162 /* We should be tainted */
163 if (issetugid() != 1) e(2);
164
165 /* Now execute a program without set{u,g}id; should not be tainted */
166 system("chmod 755 nobits");
167 if (execute("nobits", "0000") != 0) e(3);
168
169 /* Change effective gid into current+42 and try nobits again. This time
170 * it should be tainted */
171 if (seteuid(getegid() + 42) != 0) e(4);
172 if (execute("nobits", "0000") != 1) e(5);
173 exit(EXIT_SUCCESS);
174 } else {
175 /* We're the parent, wait for the child to finish */
176 wait(&status);
177 }
178 }
179
test_setnone(void)180 void test_setnone(void)
181 {
182 /* Execve a new process that does not have setuid or setgid bits set */
183 subtest = 2;
184
185 /* When we exec a new process which doesn't have set{u,g}id set, that
186 * process should not be tainted */
187 system("chmod 755 nobits");
188 if (execute("nobits", "0000") != 0) e(2);
189
190 /* When we exec a new process which doesn't have set{u,g}id set, but
191 * sets them after execution, the process should still not be tainted
192 */
193 system("chmod 755 nobits");
194 if (execute("nobits", "02755") != 0) e(4);
195 system("chmod 755 nobits");
196 if (execute("nobits", "04755") != 0) e(3);
197 system("chmod 755 nobits");
198 if (execute("nobits", "06755") != 0) e(5);
199
200 /* When we exec a new process that doesn't have setugid set, and which upon
201 * execution forks, the forked child should not be tainted either */
202 system("chmod 755 nobitsfork");
203 if (execute("nobitsfork", "0000") != 0) e(6);
204 }
205
test_self(void)206 void test_self(void)
207 {
208 /* We're supposed to be setuid. Verify. */
209
210 int status;
211 pid_t childpid;
212
213 subtest = 1;
214
215 if (issetugid() != 1) e(1);
216 childpid = fork();
217 if (childpid == -1) e(2);
218 else if (childpid == 0) {
219 /* We're the child and should inherit the tainted status of the parent
220 */
221 if (issetugid() != 1) e(3);
222
223 /* Let's change to the bin user */
224 if (setuid((uid_t) 2) != 0) e(4);
225 if (getuid() != (uid_t) 2) e(5);
226
227 /* At this point, taint status should not have changed. */
228 if (issetugid() != 1) e(6);
229
230 exit(EXIT_SUCCESS);
231 } else {
232 /* We're the parent. Wait for the child to finish */
233 wait(&status);
234 }
235 }
236
switch_to_su(void)237 static void switch_to_su(void)
238 {
239 subtest = 0;
240 if (setuid(0) != 0) e(1);
241 }
242
main(int argc,char ** argv)243 int main(int argc, char **argv)
244 {
245 start(60);
246 system("cp ../t60a nobits");
247 system("cp ../t60a setgid");
248 system("cp ../t60a setuid");
249 system("cp ../t60a setugid");
250 system("cp ../t60b nobitsfork");
251 system("cp ../t60b setuidfork");
252 system("cp ../t60b setgidfork");
253 system("cp ../t60b setugidfork");
254
255 switch_to_su(); /* We have to be root to perform this test */
256 test_self();
257 test_setnone();
258 test_setuid();
259 test_setgid();
260 test_setugid();
261 test_effugid();
262
263 quit();
264
265 return(-1); /* Never reached */
266 }
267