]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - tools/regression/priv/main.c
Copy head to stable/8 as part of 8.0 Release cycle.
[FreeBSD/stable/8.git] / tools / regression / priv / main.c
1 /*-
2  * Copyright (c) 2006 nCircle Network Security, Inc.
3  * Copyright (c) 2007 Robert N. M. Watson
4  * All rights reserved.
5  *
6  * This software was developed by Robert N. M. Watson for the TrustedBSD
7  * Project under contract to nCircle Network Security, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22  * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 /*
34  * Privilege test framework.  Each test is encapsulated on a .c file
35  * exporting a function that implements the test.  Each test is run from its
36  * own child process, and they are run in sequence one at a time.
37  */
38
39 #include <sys/param.h>
40 #include <sys/jail.h>
41 #include <sys/stat.h>
42 #include <sys/wait.h>
43
44 #include <netinet/in.h>
45
46 #include <err.h>
47 #include <errno.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52
53 #include "main.h"
54
55 /*
56  * Registration table of privilege tests.  Each test registers a name, a test
57  * function, and a cleanup function to run after the test has completed,
58  * regardless of success/failure.
59  */
60 static struct test tests[] = {
61         { "priv_acct_enable", priv_acct_setup, priv_acct_enable,
62             priv_acct_cleanup },
63
64         { "priv_acct_disable", priv_acct_setup, priv_acct_disable,
65             priv_acct_cleanup },
66
67         { "priv_acct_rotate", priv_acct_setup, priv_acct_rotate,
68             priv_acct_cleanup },
69
70         { "priv_acct_noopdisable", priv_acct_setup, priv_acct_noopdisable,
71             priv_acct_cleanup },
72
73         { "priv_adjtime_set", priv_adjtime_setup, priv_adjtime_set,
74             priv_adjtime_cleanup },
75
76         { "priv_audit_submit", priv_audit_submit_setup, priv_audit_submit,
77             priv_audit_submit_cleanup },
78
79         { "priv_audit_control", priv_audit_control_setup, priv_audit_control,
80             priv_audit_control_cleanup },
81
82         { "priv_audit_getaudit", priv_audit_getaudit_setup,
83             priv_audit_getaudit, priv_audit_getaudit_cleanup },
84
85         { "priv_audit_getaudit_addr", priv_audit_getaudit_setup,
86             priv_audit_getaudit_addr, priv_audit_getaudit_cleanup },
87
88         { "priv_audit_setaudit", priv_audit_setaudit_setup,
89             priv_audit_setaudit, priv_audit_setaudit_cleanup },
90
91         { "priv_audit_setaudit_addr", priv_audit_setaudit_setup,
92             priv_audit_setaudit_addr, priv_audit_setaudit_cleanup },
93
94         { "priv_clock_settime", priv_clock_settime_setup, priv_clock_settime,
95             priv_clock_settime_cleanup },
96
97         { "priv_cred_setuid", priv_cred_setup, priv_cred_setuid,
98             priv_cred_cleanup },
99
100         { "priv_cred_seteuid", priv_cred_setup, priv_cred_seteuid,
101             priv_cred_cleanup },
102
103         { "priv_cred_setgid", priv_cred_setup, priv_cred_setgid,
104             priv_cred_cleanup },
105
106         { "priv_cred_setegid", priv_cred_setup, priv_cred_setegid,
107             priv_cred_cleanup },
108
109         { "priv_cred_setgroups", priv_cred_setup, priv_cred_setgroups,
110             priv_cred_cleanup },
111
112         { "priv_cred_setreuid", priv_cred_setup, priv_cred_setreuid,
113             priv_cred_cleanup },
114
115         { "priv_cred_setregid", priv_cred_setup, priv_cred_setregid,
116             priv_cred_cleanup },
117
118         { "priv_cred_setresuid", priv_cred_setup, priv_cred_setresuid,
119             priv_cred_cleanup },
120
121         { "priv_cred_setresgid", priv_cred_setup, priv_cred_setresgid,
122             priv_cred_cleanup },
123
124         { "priv_io", priv_io_setup, priv_io, priv_io_cleanup },
125
126         { "priv_kenv_set", priv_kenv_set_setup, priv_kenv_set,
127             priv_kenv_set_cleanup },
128
129         { "priv_kenv_unset", priv_kenv_unset_setup, priv_kenv_unset,
130             priv_kenv_unset_cleanup },
131
132         { "priv_msgbuf_privonly", priv_msgbuf_privonly_setup,
133             priv_msgbuf_privonly, priv_msgbuf_cleanup },
134
135         { "priv_msgbuf_unprivok", priv_msgbuf_unprivok_setup,
136            priv_msgbuf_unprivok, priv_msgbuf_cleanup },
137
138         { "priv_netinet_ipsec_pfkey", NULL, priv_netinet_ipsec_pfkey, NULL },
139
140         { "priv_netinet_ipsec_policy4_bypass",
141             priv_netinet_ipsec_policy4_bypass_setup,
142             priv_netinet_ipsec_policy4_bypass,
143             priv_netinet_ipsec_policy_bypass_cleanup },
144
145         { "priv_netinet_ipsec_policy6_bypass",
146             priv_netinet_ipsec_policy6_bypass_setup,
147             priv_netinet_ipsec_policy6_bypass,
148             priv_netinet_ipsec_policy_bypass_cleanup },
149
150         { "priv_netinet_ipsec_policy4_entrust",
151             priv_netinet_ipsec_policy4_entrust_setup,
152             priv_netinet_ipsec_policy4_entrust,
153             priv_netinet_ipsec_policy_entrust_cleanup },
154
155         { "priv_netinet_ipsec_policy6_entrust",
156             priv_netinet_ipsec_policy6_entrust_setup,
157             priv_netinet_ipsec_policy6_entrust,
158             priv_netinet_ipsec_policy_entrust_cleanup },
159
160         { "priv_netinet_raw", priv_netinet_raw_setup, priv_netinet_raw,
161             priv_netinet_raw_cleanup },
162
163         { "priv_proc_setlogin", priv_proc_setlogin_setup, priv_proc_setlogin,
164             priv_proc_setlogin_cleanup },
165
166         { "priv_proc_setrlimit_raisemax", priv_proc_setrlimit_setup,
167             priv_proc_setrlimit_raisemax, priv_proc_setrlimit_cleanup },
168
169         { "priv_proc_setrlimit_raisecur", priv_proc_setrlimit_setup,
170             priv_proc_setrlimit_raisecur, priv_proc_setrlimit_cleanup },
171
172         { "priv_proc_setrlimit_raisecur_nopriv", priv_proc_setrlimit_setup,
173             priv_proc_setrlimit_raisecur_nopriv,
174             priv_proc_setrlimit_cleanup },
175
176         { "priv_sched_rtprio_curproc_normal", priv_sched_rtprio_setup,
177             priv_sched_rtprio_curproc_normal, priv_sched_rtprio_cleanup },
178
179         { "priv_sched_rtprio_curproc_idle", priv_sched_rtprio_setup,
180             priv_sched_rtprio_curproc_idle, priv_sched_rtprio_cleanup },
181
182         { "priv_sched_rtprio_curproc_realtime", priv_sched_rtprio_setup,
183             priv_sched_rtprio_curproc_realtime, priv_sched_rtprio_cleanup },
184
185         { "priv_sched_rtprio_myproc_normal", priv_sched_rtprio_setup,
186             priv_sched_rtprio_myproc_normal, priv_sched_rtprio_cleanup },
187
188         { "priv_sched_rtprio_myproc_idle", priv_sched_rtprio_setup,
189             priv_sched_rtprio_myproc_idle, priv_sched_rtprio_cleanup },
190
191         { "priv_sched_rtprio_myproc_realtime", priv_sched_rtprio_setup,
192             priv_sched_rtprio_myproc_realtime, priv_sched_rtprio_cleanup },
193
194         { "priv_sched_rtprio_aproc_normal", priv_sched_rtprio_setup,
195             priv_sched_rtprio_aproc_normal, priv_sched_rtprio_cleanup },
196
197         { "priv_sched_rtprio_aproc_idle", priv_sched_rtprio_setup,
198             priv_sched_rtprio_aproc_idle, priv_sched_rtprio_cleanup },
199
200         { "priv_sched_rtprio_aproc_realtime", priv_sched_rtprio_setup,
201             priv_sched_rtprio_aproc_realtime, priv_sched_rtprio_cleanup },
202
203         { "priv_sched_setpriority_curproc", priv_sched_setpriority_setup,
204             priv_sched_setpriority_curproc, priv_sched_setpriority_cleanup },
205
206         { "priv_sched_setpriority_myproc", priv_sched_setpriority_setup,
207             priv_sched_setpriority_myproc, priv_sched_setpriority_cleanup },
208
209         { "priv_sched_setpriority_aproc", priv_sched_setpriority_setup,
210             priv_sched_setpriority_aproc, priv_sched_setpriority_cleanup },
211
212         { "priv_settimeofday", priv_settimeofday_setup, priv_settimeofday,
213             priv_settimeofday_cleanup },
214
215         { "priv_sysctl_write", priv_sysctl_write_setup, priv_sysctl_write,
216             priv_sysctl_write_cleanup },
217
218         { "priv_sysctl_writejail", priv_sysctl_write_setup,
219             priv_sysctl_writejail, priv_sysctl_write_cleanup },
220
221         { "priv_vfs_chflags_froot_uflags", priv_vfs_chflags_froot_setup,
222             priv_vfs_chflags_froot_uflags, priv_vfs_chflags_cleanup },
223
224         { "priv_vfs_chflags_froot_sflags", priv_vfs_chflags_froot_setup,
225             priv_vfs_chflags_froot_sflags, priv_vfs_chflags_cleanup },
226
227         { "priv_vfs_chflags_fowner_uflags", priv_vfs_chflags_fowner_setup,
228             priv_vfs_chflags_fowner_uflags, priv_vfs_chflags_cleanup },
229
230         { "priv_vfs_chflags_fowner_sflags", priv_vfs_chflags_fowner_setup,
231             priv_vfs_chflags_fowner_sflags, priv_vfs_chflags_cleanup },
232
233         { "priv_vfs_chflags_fother_uflags", priv_vfs_chflags_fother_setup,
234             priv_vfs_chflags_fother_uflags, priv_vfs_chflags_cleanup },
235
236         { "priv_vfs_chflags_fother_sflags", priv_vfs_chflags_fother_setup,
237             priv_vfs_chflags_fother_sflags, priv_vfs_chflags_cleanup },
238
239         { "priv_vfs_chmod_froot", priv_vfs_chmod_froot_setup,
240              priv_vfs_chmod_froot, priv_vfs_chmod_cleanup },
241
242         { "priv_vfs_chmod_fowner", priv_vfs_chmod_fowner_setup,
243              priv_vfs_chmod_fowner, priv_vfs_chmod_cleanup },
244
245         { "priv_vfs_chmod_fother", priv_vfs_chmod_fother_setup,
246              priv_vfs_chmod_fother, priv_vfs_chmod_cleanup },
247
248         { "priv_vfs_chown_uid", priv_vfs_chown_uid_setup, priv_vfs_chown_uid,
249             priv_vfs_chown_cleanup },
250
251         { "priv_vfs_chown_mygid", priv_vfs_chown_mygid_setup,
252             priv_vfs_chown_mygid, priv_vfs_chown_cleanup },
253
254         { "priv_vfs_chown_othergid", priv_vfs_chown_othergid_setup,
255             priv_vfs_chown_othergid, priv_vfs_chown_cleanup },
256
257         { "priv_vfs_chroot", priv_vfs_chroot_setup, priv_vfs_chroot,
258             priv_vfs_chroot_cleanup },
259
260         { "priv_vfs_clearsugid_chgrp", priv_vfs_clearsugid_setup,
261             priv_vfs_clearsugid_chgrp, priv_vfs_clearsugid_cleanup },
262
263         { "priv_vfs_clearsugid_extattr", priv_vfs_clearsugid_setup,
264             priv_vfs_clearsugid_extattr, priv_vfs_clearsugid_cleanup },
265
266         { "priv_vfs_clearsugid_write", priv_vfs_clearsugid_setup,
267             priv_vfs_clearsugid_write, priv_vfs_clearsugid_cleanup },
268
269         { "priv_vfs_extattr_system", priv_vfs_extattr_system_setup,
270             priv_vfs_extattr_system, priv_vfs_extattr_system_cleanup },
271
272         { "priv_vfs_fhopen", priv_vfs_fhopen_setup, priv_vfs_fhopen,
273             priv_vfs_fhopen_cleanup },
274
275         { "priv_vfs_fhstat", priv_vfs_fhstat_setup, priv_vfs_fhstat,
276             priv_vfs_fhstat_cleanup },
277
278         { "priv_vfs_fhstatfs", priv_vfs_fhstatfs_setup, priv_vfs_fhstatfs,
279             priv_vfs_fhstatfs_cleanup },
280
281         { "priv_vfs_generation", priv_vfs_generation_setup,
282             priv_vfs_generation, priv_vfs_generation_cleanup },
283
284         { "priv_vfs_getfh", priv_vfs_getfh_setup, priv_vfs_getfh,
285             priv_vfs_getfh_cleanup },
286
287         { "priv_vfs_readwrite_fowner", priv_vfs_readwrite_fowner_setup,
288             priv_vfs_readwrite_fowner, priv_vfs_readwrite_cleanup },
289
290         { "priv_vfs_readwrite_fgroup", priv_vfs_readwrite_fgroup_setup,
291             priv_vfs_readwrite_fgroup, priv_vfs_readwrite_cleanup },
292
293         { "priv_vfs_readwrite_fother", priv_vfs_readwrite_fother_setup,
294             priv_vfs_readwrite_fother, priv_vfs_readwrite_cleanup },
295
296         { "priv_vfs_setgid_fowner", priv_vfs_setgid_fowner_setup,
297             priv_vfs_setgid_fowner, priv_vfs_setgid_cleanup },
298
299         { "priv_vfs_setgid_fother", priv_vfs_setgid_fother_setup,
300             priv_vfs_setgid_fother, priv_vfs_setgid_cleanup },
301
302         { "priv_vfs_stickyfile_dir_fowner",
303             priv_vfs_stickyfile_dir_fowner_setup,
304             priv_vfs_stickyfile_dir_fowner,
305             priv_vfs_stickyfile_dir_cleanup },
306
307         { "priv_vfs_stickyfile_dir_fother",
308             priv_vfs_stickyfile_dir_fother_setup,
309             priv_vfs_stickyfile_dir_fother,
310             priv_vfs_stickyfile_dir_cleanup },
311
312         { "priv_vfs_stickyfile_file_fowner",
313             priv_vfs_stickyfile_file_fowner_setup,
314             priv_vfs_stickyfile_file_fowner,
315             priv_vfs_stickyfile_file_cleanup },
316
317         { "priv_vfs_stickyfile_file_fother",
318             priv_vfs_stickyfile_file_fother_setup,
319             priv_vfs_stickyfile_file_fother,
320             priv_vfs_stickyfile_file_cleanup },
321
322         { "priv_vfs_utimes_froot", priv_vfs_utimes_froot_setup,
323             priv_vfs_utimes_froot, priv_vfs_utimes_cleanup },
324
325         { "priv_vfs_utimes_froot_null", priv_vfs_utimes_froot_setup,
326             priv_vfs_utimes_froot_null, priv_vfs_utimes_cleanup },
327
328         { "priv_vfs_utimes_fowner", priv_vfs_utimes_fowner_setup,
329             priv_vfs_utimes_fowner, priv_vfs_utimes_cleanup },
330
331         { "priv_vfs_utimes_fowner_null", priv_vfs_utimes_fowner_setup,
332             priv_vfs_utimes_fowner_null, priv_vfs_utimes_cleanup },
333
334         { "priv_vfs_utimes_fother", priv_vfs_utimes_fother_setup,
335             priv_vfs_utimes_fother, priv_vfs_utimes_cleanup },
336
337         { "priv_vfs_utimes_fother_null", priv_vfs_utimes_fother_setup,
338             priv_vfs_utimes_fother_null, priv_vfs_utimes_cleanup },
339
340         { "priv_vm_madv_protect", priv_vm_madv_protect_setup,
341             priv_vm_madv_protect, priv_vm_madv_protect_cleanup },
342
343         { "priv_vm_mlock", priv_vm_mlock_setup, priv_vm_mlock,
344             priv_vm_mlock_cleanup },
345
346         { "priv_vm_munlock", priv_vm_munlock_setup, priv_vm_munlock,
347             priv_vm_munlock_cleanup },
348
349 };
350 static int tests_count = sizeof(tests) / sizeof(struct test);
351
352 void
353 expect(const char *test, int error, int expected_error, int expected_errno)
354 {
355
356         if (error == 0) {
357                 if (expected_error != 0)
358                         warnx("%s: returned 0", test);
359         } else {
360                 if (expected_error == 0)
361                         warn("%s: returned (%d, %d)", test, error, errno);
362                 else if (expected_errno != errno)
363                         warn("%s: returned (%d, %d)", test, error, errno);
364         }
365 }
366
367 void
368 setup_dir(const char *test, char *dpathp, uid_t uid, gid_t gid, mode_t mode)
369 {
370
371         strcpy(dpathp, "/tmp/priv.XXXXXXXXXXX");
372         if (mkdtemp(dpathp) == NULL)
373                 err(-1, "test %s: mkdtemp", test);
374
375         if (chown(dpathp, uid, gid) < 0)
376                 err(-1, "test %s: chown(%s, %d, %d)", test, dpathp, uid,
377                     gid);
378
379         if (chmod(dpathp, mode) < 0)
380                 err(-1, "test %s: chmod(%s, 0%o)", test, dpathp, mode);
381 }
382
383 void
384 setup_file(const char *test, char *fpathp, uid_t uid, gid_t gid, mode_t mode)
385 {
386         int fd;
387
388         strcpy(fpathp, "/tmp/priv.XXXXXXXXXXX");
389         fd = mkstemp(fpathp);
390         if (fd < 0)
391                 err(-1, "test %s: mkstemp", test);
392
393         if (fchown(fd, uid, gid) < 0)
394                 err(-1, "test %s: fchown(%s, %d, %d)", test, fpathp, uid,
395                     gid);
396
397         if (fchmod(fd, mode) < 0)
398                 err(-1, "test %s: chmod(%s, 0%o)", test, fpathp, mode);
399
400         close(fd);
401 }
402
403 /*
404  * Irrevocably set credentials to specific uid and gid.
405  */
406 static void
407 set_creds(const char *test, uid_t uid, gid_t gid)
408 {
409         gid_t gids[1] = { gid };
410
411         if (setgid(gid) < 0)
412                 err(-1, "test %s: setegid(%d)", test, gid);
413         if (setgroups(sizeof(gids)/sizeof(gid_t), gids) < 0)
414                 err(-1, "test %s: setgroups(%d)", test, gid);
415         if (setuid(uid) < 0)
416                 err(-1, "test %s: seteuid(%d)", test, uid);
417 }
418
419 static void
420 enter_jail(const char *test)
421 {
422         struct jail j;
423
424         bzero(&j, sizeof(j));
425         j.version = 0;
426         j.path = "/";
427         j.hostname = "test";
428         j.ip_number = htonl(INADDR_LOOPBACK);
429         if (jail(&j) < 0)
430                 err(-1, "test %s: jail", test);
431 }
432
433 static void
434 run_child(struct test *test, int asroot, int injail)
435 {
436
437         setprogname(test->t_name);
438         if (injail)
439                 enter_jail(test->t_name);
440         if (!asroot)
441                 set_creds(test->t_name, UID_OWNER, GID_OWNER);
442         test->t_test_func(asroot, injail, test);
443 }
444
445 /*
446  * Run a test in a particular credential context -- always call the setup and
447  * cleanup routines; if setup succeeds, also run the test.  Test cleanup must
448  * handle cases where the setup has failed, so may need to maintain their own
449  * state in order to know what needs cleaning up (such as whether temporary
450  * files were created).
451  */
452 static void
453 run(struct test *test, int asroot, int injail)
454 {
455         pid_t childpid, pid;
456
457         if (test->t_setup_func != NULL) {
458                 if ((test->t_setup_func)(asroot, injail, test) != 0) {
459                         warnx("run(%s, %d, %d) setup failed", test->t_name,
460                             asroot, injail);
461                         goto cleanup;
462                 }
463         }
464         fflush(stdout);
465         fflush(stderr);
466         childpid = fork();
467         if (childpid == -1) {
468                 warn("run(%s, %d, %d) fork failed", test->t_name, asroot,
469                     injail);
470                 goto cleanup;
471         }
472         if (childpid == 0) {
473                 run_child(test, asroot, injail);
474                 fflush(stdout);
475                 fflush(stderr);
476                 exit(0);
477         } else {
478                 while (1) {
479                         pid = waitpid(childpid, NULL, 0);
480                         if (pid == -1)
481                                 warn("test: waitpid %s", test->t_name);
482                         if (pid == childpid)
483                                 break;
484                 }
485         }
486         fflush(stdout);
487         fflush(stderr);
488 cleanup:
489         if (test->t_cleanup_func != NULL)
490                 test->t_cleanup_func(asroot, injail, test);
491 }
492
493 int
494 main(int argc, char *argv[])
495 {
496         int i;
497
498         /*
499          * This test suite will need to become quite a bit more enlightened
500          * if the notion of privilege is truly separated from root, as tests
501          * make assumptions about when privilege will be present.  In
502          * particular, VFS-related tests need to manage uids in order to
503          * force the use of privilege, and will likely need checking.
504          */
505         if (getuid() != 0 && geteuid() != 0)
506                 errx(-1, "priv: must be run as root");
507
508         /*
509          * Run each test four times, varying whether the process is running
510          * as root and in jail in order to test all possible combinations.
511          */
512         for (i = 0; i < tests_count; i++) {
513                 run(&tests[i], 0, 0);
514                 run(&tests[i], 0, 1);
515                 run(&tests[i], 1, 0);
516                 run(&tests[i], 1, 1);
517         }
518         return (0);
519 }