xref: /freebsd/sys/kern/sys_capability.c (revision ddd5b8e9b4d8957fce018c520657cdfa4ecffad3)
1 /*-
2  * Copyright (c) 2008-2011 Robert N. M. Watson
3  * Copyright (c) 2010-2011 Jonathan Anderson
4  * Copyright (c) 2012 FreeBSD Foundation
5  * All rights reserved.
6  *
7  * This software was developed at the University of Cambridge Computer
8  * Laboratory with support from a grant from Google, Inc.
9  *
10  * Portions of this software were developed by Pawel Jakub Dawidek under
11  * sponsorship from the FreeBSD Foundation.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  * FreeBSD kernel capability facility.
37  *
38  * Two kernel features are implemented here: capability mode, a sandboxed mode
39  * of execution for processes, and capabilities, a refinement on file
40  * descriptors that allows fine-grained control over operations on the file
41  * descriptor.  Collectively, these allow processes to run in the style of a
42  * historic "capability system" in which they can use only resources
43  * explicitly delegated to them.  This model is enforced by restricting access
44  * to global namespaces in capability mode.
45  *
46  * Capabilities wrap other file descriptor types, binding them to a constant
47  * rights mask set when the capability is created.  New capabilities may be
48  * derived from existing capabilities, but only if they have the same or a
49  * strict subset of the rights on the original capability.
50  *
51  * System calls permitted in capability mode are defined in capabilities.conf;
52  * calls must be carefully audited for safety to ensure that they don't allow
53  * escape from a sandbox.  Some calls permit only a subset of operations in
54  * capability mode -- for example, shm_open(2) is limited to creating
55  * anonymous, rather than named, POSIX shared memory objects.
56  */
57 
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
60 
61 #include "opt_capsicum.h"
62 #include "opt_ktrace.h"
63 
64 #include <sys/param.h>
65 #include <sys/capability.h>
66 #include <sys/file.h>
67 #include <sys/filedesc.h>
68 #include <sys/kernel.h>
69 #include <sys/limits.h>
70 #include <sys/lock.h>
71 #include <sys/mutex.h>
72 #include <sys/proc.h>
73 #include <sys/sysproto.h>
74 #include <sys/sysctl.h>
75 #include <sys/systm.h>
76 #include <sys/ucred.h>
77 #include <sys/uio.h>
78 #include <sys/ktrace.h>
79 
80 #include <security/audit/audit.h>
81 
82 #include <vm/uma.h>
83 #include <vm/vm.h>
84 
85 #ifdef CAPABILITY_MODE
86 
87 FEATURE(security_capability_mode, "Capsicum Capability Mode");
88 
89 /*
90  * System call to enter capability mode for the process.
91  */
92 int
93 sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
94 {
95 	struct ucred *newcred, *oldcred;
96 	struct proc *p;
97 
98 	if (IN_CAPABILITY_MODE(td))
99 		return (0);
100 
101 	newcred = crget();
102 	p = td->td_proc;
103 	PROC_LOCK(p);
104 	oldcred = p->p_ucred;
105 	crcopy(newcred, oldcred);
106 	newcred->cr_flags |= CRED_FLAG_CAPMODE;
107 	p->p_ucred = newcred;
108 	PROC_UNLOCK(p);
109 	crfree(oldcred);
110 	return (0);
111 }
112 
113 /*
114  * System call to query whether the process is in capability mode.
115  */
116 int
117 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
118 {
119 	u_int i;
120 
121 	i = IN_CAPABILITY_MODE(td) ? 1 : 0;
122 	return (copyout(&i, uap->modep, sizeof(i)));
123 }
124 
125 #else /* !CAPABILITY_MODE */
126 
127 int
128 sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
129 {
130 
131 	return (ENOSYS);
132 }
133 
134 int
135 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
136 {
137 
138 	return (ENOSYS);
139 }
140 
141 #endif /* CAPABILITY_MODE */
142 
143 #ifdef CAPABILITIES
144 
145 FEATURE(security_capabilities, "Capsicum Capabilities");
146 
147 static inline int
148 _cap_check(cap_rights_t have, cap_rights_t need, enum ktr_cap_fail_type type)
149 {
150 
151 
152 	if ((need & ~have) != 0) {
153 #ifdef KTRACE
154 		if (KTRPOINT(curthread, KTR_CAPFAIL))
155 			ktrcapfail(type, need, have);
156 #endif
157 		return (ENOTCAPABLE);
158 	}
159 	return (0);
160 }
161 
162 /*
163  * Test whether a capability grants the requested rights.
164  */
165 int
166 cap_check(cap_rights_t have, cap_rights_t need)
167 {
168 
169 	return (_cap_check(have, need, CAPFAIL_NOTCAPABLE));
170 }
171 
172 /*
173  * Convert capability rights into VM access flags.
174  */
175 u_char
176 cap_rights_to_vmprot(cap_rights_t have)
177 {
178 	u_char maxprot;
179 
180 	maxprot = VM_PROT_NONE;
181 	if (have & CAP_MMAP_R)
182 		maxprot |= VM_PROT_READ;
183 	if (have & CAP_MMAP_W)
184 		maxprot |= VM_PROT_WRITE;
185 	if (have & CAP_MMAP_X)
186 		maxprot |= VM_PROT_EXECUTE;
187 
188 	return (maxprot);
189 }
190 
191 /*
192  * Extract rights from a capability for monitoring purposes -- not for use in
193  * any other way, as we want to keep all capability permission evaluation in
194  * this one file.
195  */
196 cap_rights_t
197 cap_rights(struct filedesc *fdp, int fd)
198 {
199 
200 	return (fdp->fd_ofiles[fd].fde_rights);
201 }
202 
203 /*
204  * System call to limit rights of the given capability.
205  */
206 int
207 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
208 {
209 	struct filedesc *fdp;
210 	cap_rights_t rights;
211 	int error, fd;
212 
213 	fd = uap->fd;
214 	rights = uap->rights;
215 
216 	AUDIT_ARG_FD(fd);
217 	AUDIT_ARG_RIGHTS(rights);
218 
219 	if ((rights & ~CAP_ALL) != 0)
220 		return (EINVAL);
221 
222 	fdp = td->td_proc->p_fd;
223 	FILEDESC_XLOCK(fdp);
224 	if (fget_locked(fdp, fd) == NULL) {
225 		FILEDESC_XUNLOCK(fdp);
226 		return (EBADF);
227 	}
228 	error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
229 	if (error == 0) {
230 		fdp->fd_ofiles[fd].fde_rights = rights;
231 		if ((rights & CAP_IOCTL) == 0) {
232 			free(fdp->fd_ofiles[fd].fde_ioctls, M_TEMP);
233 			fdp->fd_ofiles[fd].fde_ioctls = NULL;
234 			fdp->fd_ofiles[fd].fde_nioctls = 0;
235 		}
236 		if ((rights & CAP_FCNTL) == 0)
237 			fdp->fd_ofiles[fd].fde_fcntls = 0;
238 	}
239 	FILEDESC_XUNLOCK(fdp);
240 	return (error);
241 }
242 
243 /*
244  * System call to query the rights mask associated with a capability.
245  */
246 int
247 sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
248 {
249 	struct filedesc *fdp;
250 	cap_rights_t rights;
251 	int fd;
252 
253 	fd = uap->fd;
254 
255 	AUDIT_ARG_FD(fd);
256 
257 	fdp = td->td_proc->p_fd;
258 	FILEDESC_SLOCK(fdp);
259 	if (fget_locked(fdp, fd) == NULL) {
260 		FILEDESC_SUNLOCK(fdp);
261 		return (EBADF);
262 	}
263 	rights = cap_rights(fdp, fd);
264 	FILEDESC_SUNLOCK(fdp);
265 	return (copyout(&rights, uap->rightsp, sizeof(*uap->rightsp)));
266 }
267 
268 /*
269  * Test whether a capability grants the given ioctl command.
270  * If descriptor doesn't have CAP_IOCTL, then ioctls list is empty and
271  * ENOTCAPABLE will be returned.
272  */
273 int
274 cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
275 {
276 	u_long *cmds;
277 	ssize_t ncmds;
278 	long i;
279 
280 	FILEDESC_LOCK_ASSERT(fdp);
281 	KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
282 	    ("%s: invalid fd=%d", __func__, fd));
283 
284 	ncmds = fdp->fd_ofiles[fd].fde_nioctls;
285 	if (ncmds == -1)
286 		return (0);
287 
288 	cmds = fdp->fd_ofiles[fd].fde_ioctls;
289 	for (i = 0; i < ncmds; i++) {
290 		if (cmds[i] == cmd)
291 			return (0);
292 	}
293 
294 	return (ENOTCAPABLE);
295 }
296 
297 /*
298  * Check if the current ioctls list can be replaced by the new one.
299  */
300 static int
301 cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds,
302     size_t ncmds)
303 {
304 	u_long *ocmds;
305 	ssize_t oncmds;
306 	u_long i;
307 	long j;
308 
309 	oncmds = fdp->fd_ofiles[fd].fde_nioctls;
310 	if (oncmds == -1)
311 		return (0);
312 	if (oncmds < (ssize_t)ncmds)
313 		return (ENOTCAPABLE);
314 
315 	ocmds = fdp->fd_ofiles[fd].fde_ioctls;
316 	for (i = 0; i < ncmds; i++) {
317 		for (j = 0; j < oncmds; j++) {
318 			if (cmds[i] == ocmds[j])
319 				break;
320 		}
321 		if (j == oncmds)
322 			return (ENOTCAPABLE);
323 	}
324 
325 	return (0);
326 }
327 
328 int
329 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
330 {
331 	struct filedesc *fdp;
332 	u_long *cmds, *ocmds;
333 	size_t ncmds;
334 	int error, fd;
335 
336 	fd = uap->fd;
337 	ncmds = uap->ncmds;
338 
339 	AUDIT_ARG_FD(fd);
340 
341 	if (ncmds > 256)	/* XXX: Is 256 sane? */
342 		return (EINVAL);
343 
344 	if (ncmds == 0) {
345 		cmds = NULL;
346 	} else {
347 		cmds = malloc(sizeof(cmds[0]) * ncmds, M_TEMP, M_WAITOK);
348 		error = copyin(uap->cmds, cmds, sizeof(cmds[0]) * ncmds);
349 		if (error != 0) {
350 			free(cmds, M_TEMP);
351 			return (error);
352 		}
353 	}
354 
355 	fdp = td->td_proc->p_fd;
356 	FILEDESC_XLOCK(fdp);
357 
358 	if (fget_locked(fdp, fd) == NULL) {
359 		error = EBADF;
360 		goto out;
361 	}
362 
363 	error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds);
364 	if (error != 0)
365 		goto out;
366 
367 	ocmds = fdp->fd_ofiles[fd].fde_ioctls;
368 	fdp->fd_ofiles[fd].fde_ioctls = cmds;
369 	fdp->fd_ofiles[fd].fde_nioctls = ncmds;
370 
371 	cmds = ocmds;
372 	error = 0;
373 out:
374 	FILEDESC_XUNLOCK(fdp);
375 	free(cmds, M_TEMP);
376 	return (error);
377 }
378 
379 int
380 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
381 {
382 	struct filedesc *fdp;
383 	struct filedescent *fdep;
384 	u_long *cmds;
385 	size_t maxcmds;
386 	int error, fd;
387 
388 	fd = uap->fd;
389 	cmds = uap->cmds;
390 	maxcmds = uap->maxcmds;
391 
392 	AUDIT_ARG_FD(fd);
393 
394 	fdp = td->td_proc->p_fd;
395 	FILEDESC_SLOCK(fdp);
396 
397 	if (fget_locked(fdp, fd) == NULL) {
398 		error = EBADF;
399 		goto out;
400 	}
401 
402 	/*
403 	 * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL)
404 	 * the only sane thing we can do is to not populate the given array and
405 	 * return CAP_IOCTLS_ALL.
406 	 */
407 
408 	fdep = &fdp->fd_ofiles[fd];
409 	if (cmds != NULL && fdep->fde_ioctls != NULL) {
410 		error = copyout(fdep->fde_ioctls, cmds,
411 		    sizeof(cmds[0]) * MIN(fdep->fde_nioctls, maxcmds));
412 		if (error != 0)
413 			goto out;
414 	}
415 	if (fdep->fde_nioctls == -1)
416 		td->td_retval[0] = CAP_IOCTLS_ALL;
417 	else
418 		td->td_retval[0] = fdep->fde_nioctls;
419 
420 	error = 0;
421 out:
422 	FILEDESC_SUNLOCK(fdp);
423 	return (error);
424 }
425 
426 /*
427  * Test whether a capability grants the given fcntl command.
428  */
429 int
430 cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
431 {
432 	uint32_t fcntlcap;
433 
434 	KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
435 	    ("%s: invalid fd=%d", __func__, fd));
436 
437 	fcntlcap = (1 << cmd);
438 	KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
439 	    ("Unsupported fcntl=%d.", cmd));
440 
441 	if ((fdp->fd_ofiles[fd].fde_fcntls & fcntlcap) != 0)
442 		return (0);
443 
444 	return (ENOTCAPABLE);
445 }
446 
447 int
448 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
449 {
450 	struct filedesc *fdp;
451 	uint32_t fcntlrights;
452 	int fd;
453 
454 	fd = uap->fd;
455 	fcntlrights = uap->fcntlrights;
456 
457 	AUDIT_ARG_FD(fd);
458 	AUDIT_ARG_FCNTL_RIGHTS(fcntlrights);
459 
460 	if ((fcntlrights & ~CAP_FCNTL_ALL) != 0)
461 		return (EINVAL);
462 
463 	fdp = td->td_proc->p_fd;
464 	FILEDESC_XLOCK(fdp);
465 
466 	if (fget_locked(fdp, fd) == NULL) {
467 		FILEDESC_XUNLOCK(fdp);
468 		return (EBADF);
469 	}
470 
471 	if ((fcntlrights & ~fdp->fd_ofiles[fd].fde_fcntls) != 0) {
472 		FILEDESC_XUNLOCK(fdp);
473 		return (ENOTCAPABLE);
474 	}
475 
476 	fdp->fd_ofiles[fd].fde_fcntls = fcntlrights;
477 	FILEDESC_XUNLOCK(fdp);
478 
479 	return (0);
480 }
481 
482 int
483 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
484 {
485 	struct filedesc *fdp;
486 	uint32_t rights;
487 	int fd;
488 
489 	fd = uap->fd;
490 
491 	AUDIT_ARG_FD(fd);
492 
493 	fdp = td->td_proc->p_fd;
494 	FILEDESC_SLOCK(fdp);
495 	if (fget_locked(fdp, fd) == NULL) {
496 		FILEDESC_SUNLOCK(fdp);
497 		return (EBADF);
498 	}
499 	rights = fdp->fd_ofiles[fd].fde_fcntls;
500 	FILEDESC_SUNLOCK(fdp);
501 
502 	return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));
503 }
504 
505 /*
506  * For backward compatibility.
507  */
508 int
509 sys_cap_new(struct thread *td, struct cap_new_args *uap)
510 {
511 	struct filedesc *fdp;
512 	cap_rights_t rights;
513 	register_t newfd;
514 	int error, fd;
515 
516 	fd = uap->fd;
517 	rights = uap->rights;
518 
519 	AUDIT_ARG_FD(fd);
520 	AUDIT_ARG_RIGHTS(rights);
521 
522 	if ((rights & ~CAP_ALL) != 0)
523 		return (EINVAL);
524 
525 	fdp = td->td_proc->p_fd;
526 	FILEDESC_SLOCK(fdp);
527 	if (fget_locked(fdp, fd) == NULL) {
528 		FILEDESC_SUNLOCK(fdp);
529 		return (EBADF);
530 	}
531 	error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
532 	FILEDESC_SUNLOCK(fdp);
533 	if (error != 0)
534 		return (error);
535 
536 	error = do_dup(td, 0, fd, 0, &newfd);
537 	if (error != 0)
538 		return (error);
539 
540 	FILEDESC_XLOCK(fdp);
541 	/*
542 	 * We don't really care about the race between checking capability
543 	 * rights for the source descriptor and now. If capability rights
544 	 * were ok at that earlier point, the process had this descriptor
545 	 * with those rights, so we don't increase them in security sense,
546 	 * the process might have done the cap_new(2) a bit earlier to get
547 	 * the same effect.
548 	 */
549 	fdp->fd_ofiles[newfd].fde_rights = rights;
550 	if ((rights & CAP_IOCTL) == 0) {
551 		free(fdp->fd_ofiles[newfd].fde_ioctls, M_TEMP);
552 		fdp->fd_ofiles[newfd].fde_ioctls = NULL;
553 		fdp->fd_ofiles[newfd].fde_nioctls = 0;
554 	}
555 	if ((rights & CAP_FCNTL) == 0)
556 		fdp->fd_ofiles[newfd].fde_fcntls = 0;
557 	FILEDESC_XUNLOCK(fdp);
558 
559 	td->td_retval[0] = newfd;
560 
561 	return (0);
562 }
563 
564 #else /* !CAPABILITIES */
565 
566 /*
567  * Stub Capability functions for when options CAPABILITIES isn't compiled
568  * into the kernel.
569  */
570 
571 int
572 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
573 {
574 
575 	return (ENOSYS);
576 }
577 
578 int
579 sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
580 {
581 
582 	return (ENOSYS);
583 }
584 
585 int
586 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
587 {
588 
589 	return (ENOSYS);
590 }
591 
592 int
593 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
594 {
595 
596 	return (ENOSYS);
597 }
598 
599 int
600 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
601 {
602 
603 	return (ENOSYS);
604 }
605 
606 int
607 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
608 {
609 
610 	return (ENOSYS);
611 }
612 
613 int
614 sys_cap_new(struct thread *td, struct cap_new_args *uap)
615 {
616 
617 	return (ENOSYS);
618 }
619 
620 #endif /* CAPABILITIES */
621