2 * Copyright (c) 1999-2002, 2006 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.
8 * This software was developed by Robert Watson and Ilmar Habibulin for the
11 * This software was developed for the FreeBSD Project in part by Network
12 * Associates Laboratories, the Security Research Division of Network
13 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
14 * as part of the DARPA CHATS research program.
16 * This software was enhanced by SPARTA ISSO under SPAWAR contract
17 * N66001-04-C-6019 ("SEFOS").
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
46 #include <sys/param.h>
47 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/mutex.h>
53 #include <sys/systm.h>
54 #include <sys/sysproto.h>
55 #include <sys/sysent.h>
56 #include <sys/vnode.h>
57 #include <sys/mount.h>
59 #include <sys/namei.h>
60 #include <sys/socket.h>
62 #include <sys/socketvar.h>
64 #include <security/mac/mac_framework.h>
65 #include <security/mac/mac_internal.h>
66 #include <security/mac/mac_policy.h>
71 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
73 char *elements, *buffer;
79 error = copyin(uap->mac_p, &mac, sizeof(mac));
83 error = mac_check_structmac_consistent(&mac);
87 tproc = pfind(uap->pid);
91 tcred = NULL; /* Satisfy gcc. */
92 error = p_cansee(td, tproc);
94 tcred = crhold(tproc->p_ucred);
99 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
100 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
102 free(elements, M_MACTEMP);
107 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
108 error = mac_cred_externalize_label(tcred->cr_label, elements,
109 buffer, mac.m_buflen);
111 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
113 free(buffer, M_MACTEMP);
114 free(elements, M_MACTEMP);
120 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
122 char *elements, *buffer;
126 error = copyin(uap->mac_p, &mac, sizeof(mac));
130 error = mac_check_structmac_consistent(&mac);
134 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
135 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
137 free(elements, M_MACTEMP);
141 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
142 error = mac_cred_externalize_label(td->td_ucred->cr_label,
143 elements, buffer, mac.m_buflen);
145 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
147 free(buffer, M_MACTEMP);
148 free(elements, M_MACTEMP);
153 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
155 struct ucred *newcred, *oldcred;
156 struct label *intlabel;
162 error = copyin(uap->mac_p, &mac, sizeof(mac));
166 error = mac_check_structmac_consistent(&mac);
170 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
171 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
173 free(buffer, M_MACTEMP);
177 intlabel = mac_cred_label_alloc();
178 error = mac_cred_internalize_label(intlabel, buffer);
179 free(buffer, M_MACTEMP);
187 oldcred = p->p_ucred;
189 error = mac_cred_check_relabel(oldcred, intlabel);
197 crcopy(newcred, oldcred);
198 mac_cred_relabel(newcred, intlabel);
199 p->p_ucred = newcred;
202 * Grab additional reference for use while revoking mmaps, prior to
203 * releasing the proc lock and sharing the cred.
208 mac_cred_mmapped_drop_perms(td, newcred);
210 crfree(newcred); /* Free revocation reference. */
214 mac_cred_label_free(intlabel);
219 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
221 char *elements, *buffer;
222 struct label *intlabel;
229 int vfslocked, error;
231 error = copyin(uap->mac_p, &mac, sizeof(mac));
235 error = mac_check_structmac_consistent(&mac);
239 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
240 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
242 free(elements, M_MACTEMP);
246 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
247 error = fget(td, uap->fd, &fp);
251 label_type = fp->f_type;
252 switch (fp->f_type) {
256 intlabel = mac_vnode_label_alloc();
257 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
258 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
259 mac_vnode_copy_label(vp->v_label, intlabel);
260 VOP_UNLOCK(vp, 0, td);
261 VFS_UNLOCK_GIANT(vfslocked);
262 error = mac_vnode_externalize_label(intlabel, elements,
263 buffer, mac.m_buflen);
264 mac_vnode_label_free(intlabel);
269 intlabel = mac_pipe_label_alloc();
271 mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel);
273 error = mac_pipe_externalize_label(intlabel, elements,
274 buffer, mac.m_buflen);
275 mac_pipe_label_free(intlabel);
280 intlabel = mac_socket_label_alloc(M_WAITOK);
282 mac_socket_copy_label(so->so_label, intlabel);
284 error = mac_socket_externalize_label(intlabel, elements,
285 buffer, mac.m_buflen);
286 mac_socket_label_free(intlabel);
294 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
297 free(buffer, M_MACTEMP);
298 free(elements, M_MACTEMP);
303 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
305 char *elements, *buffer;
307 struct label *intlabel;
309 int vfslocked, error;
311 error = copyin(uap->mac_p, &mac, sizeof(mac));
315 error = mac_check_structmac_consistent(&mac);
319 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
320 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
322 free(elements, M_MACTEMP);
326 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
327 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
333 intlabel = mac_vnode_label_alloc();
334 vfslocked = NDHASGIANT(&nd);
335 mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
336 error = mac_vnode_externalize_label(intlabel, elements, buffer,
340 VFS_UNLOCK_GIANT(vfslocked);
341 mac_vnode_label_free(intlabel);
343 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
346 free(buffer, M_MACTEMP);
347 free(elements, M_MACTEMP);
353 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
355 char *elements, *buffer;
357 struct label *intlabel;
359 int vfslocked, error;
361 error = copyin(uap->mac_p, &mac, sizeof(mac));
365 error = mac_check_structmac_consistent(&mac);
369 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
370 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
372 free(elements, M_MACTEMP);
376 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
377 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
383 intlabel = mac_vnode_label_alloc();
384 vfslocked = NDHASGIANT(&nd);
385 mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
386 error = mac_vnode_externalize_label(intlabel, elements, buffer,
389 VFS_UNLOCK_GIANT(vfslocked);
390 mac_vnode_label_free(intlabel);
393 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
396 free(buffer, M_MACTEMP);
397 free(elements, M_MACTEMP);
403 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
405 struct label *intlabel;
413 int error, vfslocked;
415 error = copyin(uap->mac_p, &mac, sizeof(mac));
419 error = mac_check_structmac_consistent(&mac);
423 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
424 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
426 free(buffer, M_MACTEMP);
430 error = fget(td, uap->fd, &fp);
434 switch (fp->f_type) {
437 intlabel = mac_vnode_label_alloc();
438 error = mac_vnode_internalize_label(intlabel, buffer);
440 mac_vnode_label_free(intlabel);
444 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
445 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
447 VFS_UNLOCK_GIANT(vfslocked);
448 mac_vnode_label_free(intlabel);
451 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
452 error = vn_setlabel(vp, intlabel, td->td_ucred);
453 VOP_UNLOCK(vp, 0, td);
454 vn_finished_write(mp);
455 VFS_UNLOCK_GIANT(vfslocked);
456 mac_vnode_label_free(intlabel);
460 intlabel = mac_pipe_label_alloc();
461 error = mac_pipe_internalize_label(intlabel, buffer);
465 error = mac_pipe_label_set(td->td_ucred,
466 pipe->pipe_pair, intlabel);
469 mac_pipe_label_free(intlabel);
473 intlabel = mac_socket_label_alloc(M_WAITOK);
474 error = mac_socket_internalize_label(intlabel, buffer);
477 error = mac_socket_label_set(td->td_ucred, so,
480 mac_socket_label_free(intlabel);
488 free(buffer, M_MACTEMP);
493 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
495 struct label *intlabel;
500 int vfslocked, error;
502 error = copyin(uap->mac_p, &mac, sizeof(mac));
506 error = mac_check_structmac_consistent(&mac);
510 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
511 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
513 free(buffer, M_MACTEMP);
517 intlabel = mac_vnode_label_alloc();
518 error = mac_vnode_internalize_label(intlabel, buffer);
519 free(buffer, M_MACTEMP);
523 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
526 vfslocked = NDHASGIANT(&nd);
528 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
530 error = vn_setlabel(nd.ni_vp, intlabel,
532 vn_finished_write(mp);
537 VFS_UNLOCK_GIANT(vfslocked);
539 mac_vnode_label_free(intlabel);
544 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
546 struct label *intlabel;
551 int vfslocked, error;
553 error = copyin(uap->mac_p, &mac, sizeof(mac));
557 error = mac_check_structmac_consistent(&mac);
561 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
562 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
564 free(buffer, M_MACTEMP);
568 intlabel = mac_vnode_label_alloc();
569 error = mac_vnode_internalize_label(intlabel, buffer);
570 free(buffer, M_MACTEMP);
574 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
577 vfslocked = NDHASGIANT(&nd);
579 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
581 error = vn_setlabel(nd.ni_vp, intlabel,
583 vn_finished_write(mp);
588 VFS_UNLOCK_GIANT(vfslocked);
590 mac_vnode_label_free(intlabel);
595 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
597 struct mac_policy_conf *mpc;
598 char target[MAC_MAX_POLICY_NAME];
599 int entrycount, error;
601 error = copyinstr(uap->policy, target, sizeof(target), NULL);
606 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
607 if (strcmp(mpc->mpc_name, target) == 0 &&
608 mpc->mpc_ops->mpo_syscall != NULL) {
609 error = mpc->mpc_ops->mpo_syscall(td,
610 uap->call, uap->arg);
615 if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
616 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
617 if (strcmp(mpc->mpc_name, target) == 0 &&
618 mpc->mpc_ops->mpo_syscall != NULL) {
619 error = mpc->mpc_ops->mpo_syscall(td,
620 uap->call, uap->arg);
624 mac_policy_list_unbusy();
633 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
640 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
647 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
654 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
661 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
668 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
675 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
682 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
689 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
696 mac_syscall(struct thread *td, struct mac_syscall_args *uap)