Deleted Added
sdiff udiff text old ( 221431 ) new ( 224651 )
full compact
1/*-
2 * Copyright (c) 2008-2009 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/tools/regression/security/cap_test/cap_test_capmode.c 221431 2011-05-04 12:44:46Z jonathan $
27 */
28
29/*
30 * Test routines to make sure a variety of system calls are or are not
31 * available in capability mode. The goal is not to see if they work, just
32 * whether or not they return the expected ECAPMODE.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/tools/regression/security/cap_test/cap_test_capmode.c 221431 2011-05-04 12:44:46Z jonathan $");
37
38#include <sys/param.h>
39#include <sys/capability.h>
40#include <sys/mman.h>
41#include <sys/mount.h>
42#include <sys/poll.h>
43#include <sys/socket.h>
44#include <sys/stat.h>
45#include <sys/wait.h>
46
47#include <machine/sysarch.h>
48#include <netinet/in.h>
49
50#include <err.h>
51#include <errno.h>
52#include <fcntl.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56
57/* Need to check machine-dependent sysarch(). */
58#define ARCH_IS(s) (!strncmp(s, MACHINE, sizeof(s) + 1))
59
60#include "cap_test.h"
61
62void
63test_capmode(void)
64{
65 struct sockaddr_in sin;
66 struct statfs statfs;
67 struct stat sb;
68 ssize_t len;
69 long sysarch_arg = 0;
70 int fd, fd_close, fd_dir, fd_file, fd_socket, fd2[2], ret;
71 pid_t pid, wpid;
72 char ch;
73
74 fd_file = open("/tmp/cap_test_syscalls", O_RDWR|O_CREAT, 0644);
75 if (fd_file < 0)
76 err(-1, "test_syscalls:prep: open cap_test_syscalls");
77
78 fd_close = open("/dev/null", O_RDWR);
79 if (fd_close < 0)
80 err(-1, "test_syscalls:prep: open /dev/null");
81
82 fd_dir = open("/tmp", O_RDONLY);
83 if (fd_dir < 0)
84 err(-1, "test_syscalls:prep: open /tmp");
85
86 fd_socket = socket(PF_INET, SOCK_DGRAM, 0);
87 if (fd_socket < 0)
88 err(-1, "test_syscalls:prep: socket");
89
90 if (cap_enter() < 0)
91 err(-1, "test_syscalls:prep: cap_enter");
92
93
94 bzero(&sin, sizeof(sin));
95 sin.sin_len = sizeof(sin);
96 sin.sin_family = AF_INET;
97
98 /*
99 * Here begin the tests, sorted roughly alphabetically by system call
100 * name.
101 */
102 fd = accept(fd_socket, NULL, NULL);
103 if (fd < 0) {
104 if (errno == ECAPMODE)
105 warnx("test_syscalls:accept");
106 } else {
107 warnx("test_syscalls:accept succeeded");
108 close(fd);
109 }
110
111 if (access("/tmp/cap_test_syscalls_access", F_OK) < 0) {
112 if (errno != ECAPMODE)
113 warn("test_syscalls:access");
114 } else
115 warnx("test_syscalls:access succeeded");
116
117 if (acct("/tmp/cap_test_syscalls_acct") < 0) {
118 if (errno != ECAPMODE)
119 warn("test_syscalls:acct");
120 } else
121 warnx("test_syscalls:acct succeeded");
122
123 if (bind(PF_INET, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
124 if (errno != ECAPMODE)
125 warn("test_syscall:bind");
126 } else
127 warnx("test_syscall:bind succeeded");
128
129 if (chdir("/tmp/cap_test_syscalls_chdir") < 0) {
130 if (errno != ECAPMODE)
131 warn("test_syscalls:chdir");
132 } else
133 warnx("test_syscalls:chdir succeeded");
134
135 if (chflags("/tmp/cap_test_syscalls_chflags", UF_NODUMP) < 0) {
136 if (errno != ECAPMODE)
137 warn("test_syscalls:chflags");
138 } else
139 warnx("test_syscalls:chflags succeeded");
140
141 if (chmod("/tmp/cap_test_syscalls_chmod", 0644) < 0) {
142 if (errno != ECAPMODE)
143 warn("test_syscalls:chmod");
144 } else
145 warnx("test_syscalls:chmod succeeded");
146
147 if (chown("/tmp/cap_test_syscalls_chown", -1, -1) < 0) {
148 if (errno != ECAPMODE)
149 warn("test_syscalls:chown");
150 } else
151 warnx("test_syscalls:chown succeeded");
152
153 if (chroot("/tmp/cap_test_syscalls_chroot") < 0) {
154 if (errno != ECAPMODE)
155 warn("test_syscalls:chroot");
156 } else
157 warnx("test_syscalls:chroot succeeded");
158
159 if (close(fd_close)) {
160 if (errno == ECAPMODE)
161 warnx("test_syscalls:close");
162 else
163 warn("test_syscalls:close");
164 }
165
166 if (connect(PF_INET, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
167 if (errno != ECAPMODE)
168 warn("test_syscall:connect");
169 } else
170 warnx("test_syscall:connect succeeded");
171
172 fd = creat("/tmp/cap_test_syscalls_creat", 0644);
173 if (fd >= 0) {
174 warnx("test_syscalls:creat succeeded");
175 close(fd);
176 } else if (errno != ECAPMODE)
177 warn("test_syscalls:creat");
178
179 fd = dup(fd_file);
180 if (fd < 0) {
181 if (errno == ECAPMODE)
182 warnx("test_syscalls:dup");
183 } else
184 close(fd);
185
186 if (fchdir(fd_dir) < 0) {
187 if (errno != ECAPMODE)
188 warn("test_syscall:fchdir");
189 } else
190 warnx("test_syscalls:fchdir succeeded");
191
192 if (fchflags(fd_file, UF_NODUMP) < 0) {
193 if (errno == ECAPMODE)
194 warnx("test_syscall:fchflags");
195 }
196
197 pid = fork();
198 if (pid >= 0) {
199 if (pid == 0) {
200 exit(0);
201 } else if (pid > 0) {
202 wpid = waitpid(pid, NULL, 0);
203 if (wpid < 0) {
204 if (errno != ECAPMODE)
205 warn("test_syscalls:waitpid");
206 } else
207 warnx("test_syscalls:waitpid succeeded");
208 }
209 } else
210 warn("test_syscalls:fork");
211
212 if (fstat(fd_file, &sb) < 0) {
213 if (errno == ECAPMODE)
214 warnx("test_syscalls:fstat");
215 }
216
217 /*
218 * getegid() can't return an error but check for it anyway.
219 */
220 errno = 0;
221 (void)getegid();
222 if (errno == ECAPMODE)
223 warnx("test_syscalls:getegid");
224
225 /*
226 * geteuid() can't return an error but check for it anyway.
227 */
228 errno = 0;
229 geteuid();
230 if (errno == ECAPMODE)
231 warnx("test_syscalls:geteuid");
232
233 if (getfsstat(&statfs, sizeof(statfs), MNT_NOWAIT) < 0) {
234 if (errno != ECAPMODE)
235 warn("test_syscalls:getfsstat");
236 } else
237 warnx("test_syscalls:getfsstat succeeded");
238
239 /*
240 * getgid() can't return an error but check for it anyway.
241 */
242 errno = 0;
243 getgid();
244 if (errno == ECAPMODE)
245 warnx("test_syscalls:getgid");
246
247 if (getpeername(fd_socket, NULL, NULL) < 0) {
248 if (errno == ECAPMODE)
249 warnx("test_syscalls:getpeername");
250 }
251
252 if (getlogin() == NULL)
253 warn("test_sycalls:getlogin %d", errno);
254
255 /*
256 * getpid() can't return an error but check for it anyway.
257 */
258 errno = 0;
259 (void)getpid();
260 if (errno == ECAPMODE)
261 warnx("test_syscalls:getpid");
262
263 /*
264 * getppid() can't return an error but check for it anyway.
265 */
266 errno = 0;
267 (void)getppid();
268 if (errno == ECAPMODE)
269 warnx("test_syscalls:getppid");
270
271 if (getsockname(fd_socket, NULL, NULL) < 0) {
272 if (errno == ECAPMODE)
273 warnx("test_syscalls:getsockname");
274 }
275
276 /*
277 * getuid() can't return an error but check for it anyway.
278 */
279 errno = 0;
280 (void)getuid();
281 if (errno == ECAPMODE)
282 warnx("test_syscalls:getuid");
283
284 /* XXXRW: ktrace */
285
286 if (link("/tmp/foo", "/tmp/bar") < 0) {
287 if (errno != ECAPMODE)
288 warn("test_syscalls:link");
289 } else
290 warnx("test_syscalls:link succeeded");
291
292 ret = lseek(fd_file, SEEK_SET, 0);
293 if (ret < 0) {
294 if (errno == ECAPMODE)
295 warnx("test_syscalls:lseek");
296 else
297 warn("test_syscalls:lseek");
298 }
299
300 if (lstat("/tmp/cap_test_syscalls_lstat", &sb) < 0) {
301 if (errno != ECAPMODE)
302 warn("test_syscalls:lstat");
303 } else
304 warnx("test_syscalls:lstat succeeded");
305
306 if (mknod("/tmp/test_syscalls_mknod", 06440, 0) < 0) {
307 if (errno != ECAPMODE)
308 warn("test_syscalls:mknod");
309 } else
310 warnx("test_syscalls:mknod succeeded");
311
312 /*
313 * mount() is a bit tricky but do our best.
314 */
315 if (mount("procfs", "/not_mounted", 0, NULL) < 0) {
316 if (errno != ECAPMODE)
317 warn("test_syscalls:mount");
318 } else
319 warnx("test_syscalls:mount succeeded");
320
321 if (msync(&fd_file, 8192, MS_ASYNC) < 0) {
322 if (errno == ECAPMODE)
323 warnx("test_syscalls:msync");
324 }
325
326 fd = open("/dev/null", O_RDWR);
327 if (fd >= 0) {
328 warnx("test_syscalls:open succeeded");
329 close(fd);
330 }
331
332 if (pipe(fd2) == 0) {
333 close(fd2[0]);
334 close(fd2[1]);
335 } else if (errno == ECAPMODE)
336 warnx("test_syscalls:pipe");
337
338 if (profil(NULL, 0, 0, 0) < 0) {
339 if (errno == ECAPMODE)
340 warnx("test_syscalls:profile");
341 }
342
343 /* XXXRW: ptrace. */
344
345 len = read(fd_file, &ch, sizeof(ch));
346 if (len < 0 && errno == ECAPMODE)
347 warnx("test_syscalls:read");
348
349 if (readlink("/tmp/cap_test_syscalls_readlink", NULL, 0) < 0) {
350 if (errno != ECAPMODE)
351 warn("test_syscalls:readlink");
352 } else
353 warnx("test_syscalls:readlink succeeded");
354
355 len = recvfrom(fd_socket, NULL, 0, 0, NULL, NULL);
356 if (len < 0 && errno == ECAPMODE)
357 warnx("test_syscalls:recvfrom");
358
359 len = recvmsg(fd_socket, NULL, 0);
360 if (len < 0 && errno == ECAPMODE)
361 warnx("test_syscalls:recvmsg");
362
363 if (revoke("/tmp/cap_test_syscalls_revoke") < 0) {
364 if (errno != ECAPMODE)
365 warn("test_syscalls:revoke");
366 } else
367 warnx("test_syscalls:revoke succeeded");
368
369 len = sendmsg(fd_socket, NULL, 0);
370 if (len < 0 && errno == ECAPMODE)
371 warnx("test_syscalls:sendmsg");
372
373 len = sendto(fd_socket, NULL, 0, 0, NULL, 0);
374 if (len < 0 && errno == ECAPMODE)
375 warn("test_syscalls:sendto(NULL)");
376
377 if (setuid(getuid()) < 0) {
378 if (errno == ECAPMODE)
379 warnx("test_syscalls:setuid");
380 }
381
382 if (stat("/tmp/cap_test_syscalls_stat", &sb) < 0) {
383 if (errno != ECAPMODE)
384 warn("test_syscalls:stat");
385 } else
386 warnx("test_syscalls:stat succeeded");
387
388 if (symlink("/tmp/cap_test_syscalls_symlink_from",
389 "/tmp/cap_test_syscalls_symlink_to") < 0) {
390 if (errno != ECAPMODE)
391 warn("test_syscalls:symlink");
392 } else
393 warnx("test_syscalls:symlink succeeded");
394
395 /* sysarch() is, by definition, architecture-dependent */
396 if (ARCH_IS("i386") || ARCH_IS("amd64")) {
397 if (sysarch(I386_SET_IOPERM, &sysarch_arg) != -1)
398 warnx("test_syscalls:sysarch succeeded");
399 else if (errno != ECAPMODE)
400 warn("test_syscalls:sysarch errno != ECAPMODE");
401
402 /* XXXJA: write a test for arm */
403 } else {
404 warnx("test_syscalls:no sysarch() test for architecture '%s'", MACHINE);
405 }
406
407 /* XXXRW: No error return from sync(2) to test. */
408
409 if (unlink("/tmp/cap_test_syscalls_unlink") < 0) {
410 if (errno != ECAPMODE)
411 warn("test_syscalls:unlink");
412 } else
413 warnx("test_syscalls:unlink succeeded");
414
415 if (unmount("/not_mounted", 0) < 0) {
416 if (errno != ECAPMODE)
417 warn("test_syscalls:unmount");
418 } else
419 warnx("test_syscalls:unmount succeeded");
420
421 len = write(fd_file, &ch, sizeof(ch));
422 if (len < 0 && errno == ECAPMODE)
423 warnx("test_syscalls:write");
424
425 exit(0);
426}