2 * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5 * Copyright (c) 2005-2006 SPARTA, Inc.
6 * Copyright (c) 2008 Apple Inc.
9 * This software was developed by Robert Watson and Ilmar Habibulin for the
12 * This software was developed for the FreeBSD Project in part by Network
13 * Associates Laboratories, the Security Research Division of Network
14 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
15 * as part of the DARPA CHATS research program.
17 * This software was enhanced by SPARTA ISSO under SPAWAR contract
18 * N66001-04-C-6019 ("SEFOS").
20 * This software was developed at the University of Cambridge Computer
21 * Laboratory with support from a grant from Google, Inc.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
32 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
50 #include <sys/param.h>
51 #include <sys/capability.h>
52 #include <sys/fcntl.h>
53 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/mutex.h>
59 #include <sys/systm.h>
60 #include <sys/sysctl.h>
61 #include <sys/sysproto.h>
62 #include <sys/sysent.h>
63 #include <sys/vnode.h>
64 #include <sys/mount.h>
66 #include <sys/namei.h>
67 #include <sys/socket.h>
69 #include <sys/socketvar.h>
71 #include <security/mac/mac_framework.h>
72 #include <security/mac/mac_internal.h>
73 #include <security/mac/mac_policy.h>
77 FEATURE(security_mac, "Mandatory Access Control Framework support");
80 sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
82 char *elements, *buffer;
88 error = copyin(uap->mac_p, &mac, sizeof(mac));
92 error = mac_check_structmac_consistent(&mac);
96 tproc = pfind(uap->pid);
100 tcred = NULL; /* Satisfy gcc. */
101 error = p_cansee(td, tproc);
103 tcred = crhold(tproc->p_ucred);
108 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
109 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
111 free(elements, M_MACTEMP);
116 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
117 error = mac_cred_externalize_label(tcred->cr_label, elements,
118 buffer, mac.m_buflen);
120 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
122 free(buffer, M_MACTEMP);
123 free(elements, M_MACTEMP);
129 sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
131 char *elements, *buffer;
135 error = copyin(uap->mac_p, &mac, sizeof(mac));
139 error = mac_check_structmac_consistent(&mac);
143 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
144 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
146 free(elements, M_MACTEMP);
150 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
151 error = mac_cred_externalize_label(td->td_ucred->cr_label,
152 elements, buffer, mac.m_buflen);
154 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
156 free(buffer, M_MACTEMP);
157 free(elements, M_MACTEMP);
162 sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
164 struct ucred *newcred, *oldcred;
165 struct label *intlabel;
171 if (!(mac_labeled & MPC_OBJECT_CRED))
174 error = copyin(uap->mac_p, &mac, sizeof(mac));
178 error = mac_check_structmac_consistent(&mac);
182 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
183 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
185 free(buffer, M_MACTEMP);
189 intlabel = mac_cred_label_alloc();
190 error = mac_cred_internalize_label(intlabel, buffer);
191 free(buffer, M_MACTEMP);
199 oldcred = p->p_ucred;
201 error = mac_cred_check_relabel(oldcred, intlabel);
209 crcopy(newcred, oldcred);
210 mac_cred_relabel(newcred, intlabel);
211 p->p_ucred = newcred;
215 mac_proc_vm_revoke(td);
218 mac_cred_label_free(intlabel);
223 sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
225 char *elements, *buffer;
226 struct label *intlabel;
233 int vfslocked, error;
235 error = copyin(uap->mac_p, &mac, sizeof(mac));
239 error = mac_check_structmac_consistent(&mac);
243 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
244 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
246 free(elements, M_MACTEMP);
250 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
251 error = fget(td, uap->fd, CAP_MAC_GET, &fp);
255 label_type = fp->f_type;
256 switch (fp->f_type) {
259 if (!(mac_labeled & MPC_OBJECT_VNODE)) {
264 intlabel = mac_vnode_label_alloc();
265 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
266 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
267 mac_vnode_copy_label(vp->v_label, intlabel);
269 VFS_UNLOCK_GIANT(vfslocked);
270 error = mac_vnode_externalize_label(intlabel, elements,
271 buffer, mac.m_buflen);
272 mac_vnode_label_free(intlabel);
276 if (!(mac_labeled & MPC_OBJECT_PIPE)) {
281 intlabel = mac_pipe_label_alloc();
283 mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel);
285 error = mac_pipe_externalize_label(intlabel, elements,
286 buffer, mac.m_buflen);
287 mac_pipe_label_free(intlabel);
291 if (!(mac_labeled & MPC_OBJECT_SOCKET)) {
296 intlabel = mac_socket_label_alloc(M_WAITOK);
298 mac_socket_copy_label(so->so_label, intlabel);
300 error = mac_socket_externalize_label(intlabel, elements,
301 buffer, mac.m_buflen);
302 mac_socket_label_free(intlabel);
309 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
313 free(buffer, M_MACTEMP);
314 free(elements, M_MACTEMP);
319 sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
321 char *elements, *buffer;
323 struct label *intlabel;
325 int vfslocked, error;
327 if (!(mac_labeled & MPC_OBJECT_VNODE))
330 error = copyin(uap->mac_p, &mac, sizeof(mac));
334 error = mac_check_structmac_consistent(&mac);
338 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
339 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
341 free(elements, M_MACTEMP);
345 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
346 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
352 intlabel = mac_vnode_label_alloc();
353 vfslocked = NDHASGIANT(&nd);
354 mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
355 error = mac_vnode_externalize_label(intlabel, elements, buffer,
359 VFS_UNLOCK_GIANT(vfslocked);
360 mac_vnode_label_free(intlabel);
362 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
365 free(buffer, M_MACTEMP);
366 free(elements, M_MACTEMP);
372 sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
374 char *elements, *buffer;
376 struct label *intlabel;
378 int vfslocked, error;
380 if (!(mac_labeled & MPC_OBJECT_VNODE))
383 error = copyin(uap->mac_p, &mac, sizeof(mac));
387 error = mac_check_structmac_consistent(&mac);
391 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
392 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
394 free(elements, M_MACTEMP);
398 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
399 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
405 intlabel = mac_vnode_label_alloc();
406 vfslocked = NDHASGIANT(&nd);
407 mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
408 error = mac_vnode_externalize_label(intlabel, elements, buffer,
411 VFS_UNLOCK_GIANT(vfslocked);
412 mac_vnode_label_free(intlabel);
415 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
418 free(buffer, M_MACTEMP);
419 free(elements, M_MACTEMP);
425 sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
427 struct label *intlabel;
435 int error, vfslocked;
437 error = copyin(uap->mac_p, &mac, sizeof(mac));
441 error = mac_check_structmac_consistent(&mac);
445 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
446 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
448 free(buffer, M_MACTEMP);
452 error = fget(td, uap->fd, CAP_MAC_SET, &fp);
456 switch (fp->f_type) {
459 if (!(mac_labeled & MPC_OBJECT_VNODE)) {
463 intlabel = mac_vnode_label_alloc();
464 error = mac_vnode_internalize_label(intlabel, buffer);
466 mac_vnode_label_free(intlabel);
470 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
471 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
473 VFS_UNLOCK_GIANT(vfslocked);
474 mac_vnode_label_free(intlabel);
477 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
478 error = vn_setlabel(vp, intlabel, td->td_ucred);
480 vn_finished_write(mp);
481 VFS_UNLOCK_GIANT(vfslocked);
482 mac_vnode_label_free(intlabel);
486 if (!(mac_labeled & MPC_OBJECT_PIPE)) {
490 intlabel = mac_pipe_label_alloc();
491 error = mac_pipe_internalize_label(intlabel, buffer);
495 error = mac_pipe_label_set(td->td_ucred,
496 pipe->pipe_pair, intlabel);
499 mac_pipe_label_free(intlabel);
503 if (!(mac_labeled & MPC_OBJECT_SOCKET)) {
507 intlabel = mac_socket_label_alloc(M_WAITOK);
508 error = mac_socket_internalize_label(intlabel, buffer);
511 error = mac_socket_label_set(td->td_ucred, so,
514 mac_socket_label_free(intlabel);
523 free(buffer, M_MACTEMP);
528 sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
530 struct label *intlabel;
535 int vfslocked, error;
537 if (!(mac_labeled & MPC_OBJECT_VNODE))
540 error = copyin(uap->mac_p, &mac, sizeof(mac));
544 error = mac_check_structmac_consistent(&mac);
548 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
549 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
551 free(buffer, M_MACTEMP);
555 intlabel = mac_vnode_label_alloc();
556 error = mac_vnode_internalize_label(intlabel, buffer);
557 free(buffer, M_MACTEMP);
561 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
564 vfslocked = NDHASGIANT(&nd);
566 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
568 error = vn_setlabel(nd.ni_vp, intlabel,
570 vn_finished_write(mp);
575 VFS_UNLOCK_GIANT(vfslocked);
577 mac_vnode_label_free(intlabel);
582 sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
584 struct label *intlabel;
589 int vfslocked, error;
591 if (!(mac_labeled & MPC_OBJECT_VNODE))
594 error = copyin(uap->mac_p, &mac, sizeof(mac));
598 error = mac_check_structmac_consistent(&mac);
602 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
603 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
605 free(buffer, M_MACTEMP);
609 intlabel = mac_vnode_label_alloc();
610 error = mac_vnode_internalize_label(intlabel, buffer);
611 free(buffer, M_MACTEMP);
615 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
618 vfslocked = NDHASGIANT(&nd);
620 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
622 error = vn_setlabel(nd.ni_vp, intlabel,
624 vn_finished_write(mp);
629 VFS_UNLOCK_GIANT(vfslocked);
631 mac_vnode_label_free(intlabel);
636 sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap)
638 struct mac_policy_conf *mpc;
639 char target[MAC_MAX_POLICY_NAME];
642 error = copyinstr(uap->policy, target, sizeof(target), NULL);
647 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
648 if (strcmp(mpc->mpc_name, target) == 0 &&
649 mpc->mpc_ops->mpo_syscall != NULL) {
650 error = mpc->mpc_ops->mpo_syscall(td,
651 uap->call, uap->arg);
656 if (!LIST_EMPTY(&mac_policy_list)) {
657 mac_policy_slock_sleep();
658 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
659 if (strcmp(mpc->mpc_name, target) == 0 &&
660 mpc->mpc_ops->mpo_syscall != NULL) {
661 error = mpc->mpc_ops->mpo_syscall(td,
662 uap->call, uap->arg);
666 mac_policy_sunlock_sleep();
675 sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
682 sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
689 sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
696 sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
703 sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
710 sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
717 sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
724 sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
731 sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
738 sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap)