1 /*-
2  * Copyright (c) 2012 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/types.h>
31 #include <sys/capsicum.h>
32 #include <sys/procdesc.h>
33 #include <sys/wait.h>
34 
35 #include <err.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 
41 #include "misc.h"
42 
43 int
44 main(void)
45 {
46 	unsigned int mode;
47 	pid_t pid;
48 	int pfd;
49 
50 	printf("1..27\n");
51 
52 	mode = 666;
53 	CHECK(cap_getmode(&mode) == 0);
54 	/* If cap_getmode() succeeded mode should be modified. */
55 	CHECK(mode != 666);
56 	/* We are not in capability mode. */
57 	CHECK(mode == 0);
58 
59 	/* Expect EFAULT. */
60 	errno = 0;
61 	CHECK(cap_getmode(NULL) == -1);
62 	CHECK(errno == EFAULT);
63 	errno = 0;
64 	CHECK(cap_getmode((void *)(uintptr_t)0xdeadc0de) == -1);
65 	CHECK(errno == EFAULT);
66 
67 	/* If parent is not in capability mode, child after fork() also won't be. */
68 	pid = fork();
69 	switch (pid) {
70 	case -1:
71 		err(1, "fork() failed");
72 	case 0:
73 		mode = 666;
74 		CHECK(cap_getmode(&mode) == 0);
75 		/* If cap_getmode() succeeded mode should be modified. */
76 		CHECK(mode != 666);
77 		/* We are not in capability mode. */
78 		CHECK(mode == 0);
79 		exit(0);
80 	default:
81 		if (waitpid(pid, NULL, 0) == -1)
82 			err(1, "waitpid() failed");
83 	}
84 
85 	/* If parent is not in capability mode, child after pdfork() also won't be. */
86 	pid = pdfork(&pfd, 0);
87 	switch (pid) {
88 	case -1:
89 		err(1, "pdfork() failed");
90 	case 0:
91 		mode = 666;
92 		CHECK(cap_getmode(&mode) == 0);
93 		/* If cap_getmode() succeeded mode should be modified. */
94 		CHECK(mode != 666);
95 		/* We are not in capability mode. */
96 		CHECK(mode == 0);
97 		exit(0);
98 	default:
99 		if (pdwait(pfd) == -1)
100 			err(1, "pdwait() failed");
101 		close(pfd);
102 	}
103 
104 	/* In capability mode... */
105 
106 	CHECK(cap_enter() == 0);
107 
108 	mode = 666;
109 	CHECK(cap_getmode(&mode) == 0);
110 	/* If cap_getmode() succeeded mode should be modified. */
111 	CHECK(mode != 666);
112 	/* We are in capability mode. */
113 	CHECK(mode == 1);
114 
115 	/* Expect EFAULT. */
116 	errno = 0;
117 	CHECK(cap_getmode(NULL) == -1);
118 	CHECK(errno == EFAULT);
119 	errno = 0;
120 	CHECK(cap_getmode((void *)(uintptr_t)0xdeadc0de) == -1);
121 	CHECK(errno == EFAULT);
122 
123 	/* If parent is in capability mode, child after fork() also will be. */
124 	pid = fork();
125 	switch (pid) {
126 	case -1:
127 		err(1, "fork() failed");
128 	case 0:
129 		mode = 666;
130 		CHECK(cap_getmode(&mode) == 0);
131 		/* If cap_getmode() succeeded mode should be modified. */
132 		CHECK(mode != 666);
133 		/* We are in capability mode. */
134 		CHECK(mode == 1);
135 		exit(0);
136 	default:
137 		/*
138 		 * wait(2) and friends are not permitted in the capability mode,
139 		 * so we can only just wait for a while.
140 		 */
141 		sleep(1);
142 	}
143 
144 	/* If parent is in capability mode, child after pdfork() also will be. */
145 	pid = pdfork(&pfd, 0);
146 	switch (pid) {
147 	case -1:
148 		err(1, "pdfork() failed");
149 	case 0:
150 		mode = 666;
151 		CHECK(cap_getmode(&mode) == 0);
152 		/* If cap_getmode() succeeded mode should be modified. */
153 		CHECK(mode != 666);
154 		/* We are in capability mode. */
155 		CHECK(mode == 1);
156 		exit(0);
157 	default:
158 		if (pdwait(pfd) == -1)
159 			err(1, "pdwait() failed");
160 		close(pfd);
161 	}
162 
163 	exit(0);
164 }
165