17bc82500SRobert Watson /*- 240202729SRobert Watson * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 4f0c2044bSRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5aed55708SRobert Watson * Copyright (c) 2005-2006 SPARTA, Inc. 66356dba0SRobert Watson * Copyright (c) 2008 Apple Inc. 77bc82500SRobert Watson * All rights reserved. 87bc82500SRobert Watson * 97bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 107bc82500SRobert Watson * TrustedBSD Project. 117bc82500SRobert Watson * 126201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network 136201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network 146201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 156201265bSRobert Watson * as part of the DARPA CHATS research program. 167bc82500SRobert Watson * 1749bb6870SRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 1849bb6870SRobert Watson * N66001-04-C-6019 ("SEFOS"). 1949bb6870SRobert Watson * 2040202729SRobert Watson * This software was developed at the University of Cambridge Computer 2140202729SRobert Watson * Laboratory with support from a grant from Google, Inc. 2240202729SRobert Watson * 237bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 247bc82500SRobert Watson * modification, are permitted provided that the following conditions 257bc82500SRobert Watson * are met: 267bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 277bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 287bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 297bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 307bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 317bc82500SRobert Watson * 327bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 337bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 347bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 357bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 367bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 377bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 387bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 397bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 407bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 417bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 427bc82500SRobert Watson * SUCH DAMAGE. 437bc82500SRobert Watson */ 44677b542eSDavid E. O'Brien 45677b542eSDavid E. O'Brien #include <sys/cdefs.h> 46677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 47677b542eSDavid E. O'Brien 487bc82500SRobert Watson #include "opt_mac.h" 49f9d0d524SRobert Watson 507bc82500SRobert Watson #include <sys/param.h> 51a9d2f8d8SRobert Watson #include <sys/capability.h> 5257b4252eSKonstantin Belousov #include <sys/fcntl.h> 5395fab37eSRobert Watson #include <sys/kernel.h> 5495fab37eSRobert Watson #include <sys/lock.h> 55b656366bSBruce Evans #include <sys/malloc.h> 5695fab37eSRobert Watson #include <sys/mutex.h> 5795fab37eSRobert Watson #include <sys/mac.h> 5895fab37eSRobert Watson #include <sys/proc.h> 5995fab37eSRobert Watson #include <sys/systm.h> 60de5b1952SAlexander Leidinger #include <sys/sysctl.h> 617bc82500SRobert Watson #include <sys/sysproto.h> 627bc82500SRobert Watson #include <sys/sysent.h> 6395fab37eSRobert Watson #include <sys/vnode.h> 6495fab37eSRobert Watson #include <sys/mount.h> 6595fab37eSRobert Watson #include <sys/file.h> 6695fab37eSRobert Watson #include <sys/namei.h> 6795fab37eSRobert Watson #include <sys/socket.h> 6895fab37eSRobert Watson #include <sys/pipe.h> 6995fab37eSRobert Watson #include <sys/socketvar.h> 7095fab37eSRobert Watson 71aed55708SRobert Watson #include <security/mac/mac_framework.h> 726fa0475dSRobert Watson #include <security/mac/mac_internal.h> 730efd6615SRobert Watson #include <security/mac/mac_policy.h> 746fa0475dSRobert Watson 7595fab37eSRobert Watson #ifdef MAC 7695fab37eSRobert Watson 77d783bbd2SAlexander Leidinger FEATURE(security_mac, "Mandatory Access Control Framework support"); 78de5b1952SAlexander Leidinger 79f7b951a8SRobert Watson int 808451d0ddSKip Macy sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 81f7b951a8SRobert Watson { 82f7b951a8SRobert Watson char *elements, *buffer; 83f7b951a8SRobert Watson struct mac mac; 84f7b951a8SRobert Watson struct proc *tproc; 85f7b951a8SRobert Watson struct ucred *tcred; 86f7b951a8SRobert Watson int error; 87f7b951a8SRobert Watson 88d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 89f7b951a8SRobert Watson if (error) 90f7b951a8SRobert Watson return (error); 91f7b951a8SRobert Watson 92f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 93f7b951a8SRobert Watson if (error) 94f7b951a8SRobert Watson return (error); 95f7b951a8SRobert Watson 96f7b951a8SRobert Watson tproc = pfind(uap->pid); 97f7b951a8SRobert Watson if (tproc == NULL) 98f7b951a8SRobert Watson return (ESRCH); 99f7b951a8SRobert Watson 100f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 101f7b951a8SRobert Watson error = p_cansee(td, tproc); 102f7b951a8SRobert Watson if (error == 0) 103f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 104f7b951a8SRobert Watson PROC_UNLOCK(tproc); 105f7b951a8SRobert Watson if (error) 106f7b951a8SRobert Watson return (error); 107f7b951a8SRobert Watson 108a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 109f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 110f7b951a8SRobert Watson if (error) { 111f7b951a8SRobert Watson free(elements, M_MACTEMP); 112f7b951a8SRobert Watson crfree(tcred); 113f7b951a8SRobert Watson return (error); 114f7b951a8SRobert Watson } 115f7b951a8SRobert Watson 116a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 11730d239bcSRobert Watson error = mac_cred_externalize_label(tcred->cr_label, elements, 11883b7b0edSRobert Watson buffer, mac.m_buflen); 119f7b951a8SRobert Watson if (error == 0) 120f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 121f7b951a8SRobert Watson 122f7b951a8SRobert Watson free(buffer, M_MACTEMP); 123f7b951a8SRobert Watson free(elements, M_MACTEMP); 124f7b951a8SRobert Watson crfree(tcred); 125f7b951a8SRobert Watson return (error); 126f7b951a8SRobert Watson } 127f7b951a8SRobert Watson 12895fab37eSRobert Watson int 1298451d0ddSKip Macy sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 13095fab37eSRobert Watson { 131f7b951a8SRobert Watson char *elements, *buffer; 132f7b951a8SRobert Watson struct mac mac; 13395fab37eSRobert Watson int error; 13495fab37eSRobert Watson 135f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 136f7b951a8SRobert Watson if (error) 137f7b951a8SRobert Watson return (error); 13895fab37eSRobert Watson 139f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 140f7b951a8SRobert Watson if (error) 141f7b951a8SRobert Watson return (error); 142f7b951a8SRobert Watson 143a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 144f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 145f7b951a8SRobert Watson if (error) { 146f7b951a8SRobert Watson free(elements, M_MACTEMP); 147f7b951a8SRobert Watson return (error); 148f7b951a8SRobert Watson } 149f7b951a8SRobert Watson 150a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 15130d239bcSRobert Watson error = mac_cred_externalize_label(td->td_ucred->cr_label, 15283b7b0edSRobert Watson elements, buffer, mac.m_buflen); 153f7b951a8SRobert Watson if (error == 0) 154f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 155f7b951a8SRobert Watson 156f7b951a8SRobert Watson free(buffer, M_MACTEMP); 157f7b951a8SRobert Watson free(elements, M_MACTEMP); 15895fab37eSRobert Watson return (error); 15995fab37eSRobert Watson } 16095fab37eSRobert Watson 16195fab37eSRobert Watson int 1628451d0ddSKip Macy sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 16395fab37eSRobert Watson { 16495fab37eSRobert Watson struct ucred *newcred, *oldcred; 165eca8a663SRobert Watson struct label *intlabel; 166f7b951a8SRobert Watson struct proc *p; 167f7b951a8SRobert Watson struct mac mac; 168f7b951a8SRobert Watson char *buffer; 16995fab37eSRobert Watson int error; 17095fab37eSRobert Watson 1716356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_CRED)) 1726356dba0SRobert Watson return (EINVAL); 1736356dba0SRobert Watson 174f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 17595fab37eSRobert Watson if (error) 17695fab37eSRobert Watson return (error); 17795fab37eSRobert Watson 178f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 17995fab37eSRobert Watson if (error) 18095fab37eSRobert Watson return (error); 18195fab37eSRobert Watson 182a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 183f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 184f7b951a8SRobert Watson if (error) { 185f7b951a8SRobert Watson free(buffer, M_MACTEMP); 186f7b951a8SRobert Watson return (error); 187f7b951a8SRobert Watson } 188f7b951a8SRobert Watson 189eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 19030d239bcSRobert Watson error = mac_cred_internalize_label(intlabel, buffer); 191f7b951a8SRobert Watson free(buffer, M_MACTEMP); 192eca8a663SRobert Watson if (error) 193eca8a663SRobert Watson goto out; 194f7b951a8SRobert Watson 19595fab37eSRobert Watson newcred = crget(); 19695fab37eSRobert Watson 19795fab37eSRobert Watson p = td->td_proc; 19895fab37eSRobert Watson PROC_LOCK(p); 19995fab37eSRobert Watson oldcred = p->p_ucred; 20095fab37eSRobert Watson 20130d239bcSRobert Watson error = mac_cred_check_relabel(oldcred, intlabel); 20295fab37eSRobert Watson if (error) { 20395fab37eSRobert Watson PROC_UNLOCK(p); 20495fab37eSRobert Watson crfree(newcred); 205f7b951a8SRobert Watson goto out; 20695fab37eSRobert Watson } 20795fab37eSRobert Watson 20895fab37eSRobert Watson setsugid(p); 20995fab37eSRobert Watson crcopy(newcred, oldcred); 21030d239bcSRobert Watson mac_cred_relabel(newcred, intlabel); 21195fab37eSRobert Watson p->p_ucred = newcred; 212e5cb5e37SRobert Watson 21395fab37eSRobert Watson PROC_UNLOCK(p); 21495fab37eSRobert Watson crfree(oldcred); 2159215889dSRobert Watson mac_proc_vm_revoke(td); 216f7b951a8SRobert Watson 217f7b951a8SRobert Watson out: 218eca8a663SRobert Watson mac_cred_label_free(intlabel); 219f7b951a8SRobert Watson return (error); 22095fab37eSRobert Watson } 22195fab37eSRobert Watson 22295fab37eSRobert Watson int 2238451d0ddSKip Macy sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 22495fab37eSRobert Watson { 225f7b951a8SRobert Watson char *elements, *buffer; 226eca8a663SRobert Watson struct label *intlabel; 22795fab37eSRobert Watson struct file *fp; 228f7b951a8SRobert Watson struct mac mac; 22995fab37eSRobert Watson struct vnode *vp; 23095fab37eSRobert Watson struct pipe *pipe; 231b0323ea3SRobert Watson struct socket *so; 232f7b951a8SRobert Watson short label_type; 2339eea3d85SChristian S.J. Peron int vfslocked, error; 23495fab37eSRobert Watson 235f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 236f7b951a8SRobert Watson if (error) 237f7b951a8SRobert Watson return (error); 23895fab37eSRobert Watson 239f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 240f7b951a8SRobert Watson if (error) 241f7b951a8SRobert Watson return (error); 242f7b951a8SRobert Watson 243a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 244f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 245f7b951a8SRobert Watson if (error) { 246f7b951a8SRobert Watson free(elements, M_MACTEMP); 247f7b951a8SRobert Watson return (error); 248f7b951a8SRobert Watson } 249f7b951a8SRobert Watson 250a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 251a9d2f8d8SRobert Watson error = fget(td, uap->fd, CAP_MAC_GET, &fp); 25295fab37eSRobert Watson if (error) 25395fab37eSRobert Watson goto out; 25495fab37eSRobert Watson 255f7b951a8SRobert Watson label_type = fp->f_type; 25695fab37eSRobert Watson switch (fp->f_type) { 25795fab37eSRobert Watson case DTYPE_FIFO: 25895fab37eSRobert Watson case DTYPE_VNODE: 259*b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) { 260*b4ef8be2SRobert Watson error = EINVAL; 261*b4ef8be2SRobert Watson goto out_fdrop; 262*b4ef8be2SRobert Watson } 2633b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 264eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 2659eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 266cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 26730d239bcSRobert Watson mac_vnode_copy_label(vp->v_label, intlabel); 26822db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2699eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 27030d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, 271f0ab0442SRobert Watson buffer, mac.m_buflen); 272f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 27395fab37eSRobert Watson break; 274f0ab0442SRobert Watson 27595fab37eSRobert Watson case DTYPE_PIPE: 276*b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) { 277*b4ef8be2SRobert Watson error = EINVAL; 278*b4ef8be2SRobert Watson goto out_fdrop; 279*b4ef8be2SRobert Watson } 28048e3128bSMatthew Dillon pipe = fp->f_data; 281eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 282f7b951a8SRobert Watson PIPE_LOCK(pipe); 28330d239bcSRobert Watson mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel); 284f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 28530d239bcSRobert Watson error = mac_pipe_externalize_label(intlabel, elements, 28683b7b0edSRobert Watson buffer, mac.m_buflen); 287eca8a663SRobert Watson mac_pipe_label_free(intlabel); 288f7b951a8SRobert Watson break; 28995fab37eSRobert Watson 290b0323ea3SRobert Watson case DTYPE_SOCKET: 291*b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 292*b4ef8be2SRobert Watson error = EINVAL; 293*b4ef8be2SRobert Watson goto out_fdrop; 294*b4ef8be2SRobert Watson } 295b0323ea3SRobert Watson so = fp->f_data; 296b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 297f0c2044bSRobert Watson SOCK_LOCK(so); 29830d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 299f0c2044bSRobert Watson SOCK_UNLOCK(so); 30030d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, 301b0323ea3SRobert Watson buffer, mac.m_buflen); 302b0323ea3SRobert Watson mac_socket_label_free(intlabel); 303b0323ea3SRobert Watson break; 304b0323ea3SRobert Watson 305f0ab0442SRobert Watson default: 306f0ab0442SRobert Watson error = EINVAL; 307f0ab0442SRobert Watson } 30895fab37eSRobert Watson if (error == 0) 309f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 310*b4ef8be2SRobert Watson out_fdrop: 311*b4ef8be2SRobert Watson fdrop(fp, td); 31295fab37eSRobert Watson out: 313f7b951a8SRobert Watson free(buffer, M_MACTEMP); 314f7b951a8SRobert Watson free(elements, M_MACTEMP); 31595fab37eSRobert Watson return (error); 31695fab37eSRobert Watson } 31795fab37eSRobert Watson 31895fab37eSRobert Watson int 3198451d0ddSKip Macy sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 32095fab37eSRobert Watson { 321f7b951a8SRobert Watson char *elements, *buffer; 32295fab37eSRobert Watson struct nameidata nd; 323eca8a663SRobert Watson struct label *intlabel; 324f7b951a8SRobert Watson struct mac mac; 3259eea3d85SChristian S.J. Peron int vfslocked, error; 32695fab37eSRobert Watson 3276356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3286356dba0SRobert Watson return (EINVAL); 3296356dba0SRobert Watson 330f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 331f7b951a8SRobert Watson if (error) 332f7b951a8SRobert Watson return (error); 333f7b951a8SRobert Watson 334f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 335f7b951a8SRobert Watson if (error) 336f7b951a8SRobert Watson return (error); 337f7b951a8SRobert Watson 338a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 339f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 340f7b951a8SRobert Watson if (error) { 341f7b951a8SRobert Watson free(elements, M_MACTEMP); 342f7b951a8SRobert Watson return (error); 343f7b951a8SRobert Watson } 344f7b951a8SRobert Watson 345a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3469eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 3479eea3d85SChristian S.J. Peron uap->path_p, td); 34895fab37eSRobert Watson error = namei(&nd); 34995fab37eSRobert Watson if (error) 35095fab37eSRobert Watson goto out; 35195fab37eSRobert Watson 352eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 3539eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 35430d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 35530d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 35683b7b0edSRobert Watson mac.m_buflen); 357f7b951a8SRobert Watson 35895fab37eSRobert Watson NDFREE(&nd, 0); 3599eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 360eca8a663SRobert Watson mac_vnode_label_free(intlabel); 361f7b951a8SRobert Watson if (error == 0) 362f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 363f7b951a8SRobert Watson 364f7b951a8SRobert Watson out: 365f7b951a8SRobert Watson free(buffer, M_MACTEMP); 366f7b951a8SRobert Watson free(elements, M_MACTEMP); 367f7b951a8SRobert Watson 368f7b951a8SRobert Watson return (error); 369f7b951a8SRobert Watson } 370f7b951a8SRobert Watson 371f7b951a8SRobert Watson int 3728451d0ddSKip Macy sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 373f7b951a8SRobert Watson { 374f7b951a8SRobert Watson char *elements, *buffer; 375f7b951a8SRobert Watson struct nameidata nd; 376eca8a663SRobert Watson struct label *intlabel; 377f7b951a8SRobert Watson struct mac mac; 3789eea3d85SChristian S.J. Peron int vfslocked, error; 379f7b951a8SRobert Watson 3806356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3816356dba0SRobert Watson return (EINVAL); 3826356dba0SRobert Watson 383f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 384f7b951a8SRobert Watson if (error) 385f7b951a8SRobert Watson return (error); 386f7b951a8SRobert Watson 387f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 388f7b951a8SRobert Watson if (error) 389f7b951a8SRobert Watson return (error); 390f7b951a8SRobert Watson 391a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 392f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 393f7b951a8SRobert Watson if (error) { 394f7b951a8SRobert Watson free(elements, M_MACTEMP); 395f7b951a8SRobert Watson return (error); 396f7b951a8SRobert Watson } 397f7b951a8SRobert Watson 398a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3999eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 4009eea3d85SChristian S.J. Peron uap->path_p, td); 401f7b951a8SRobert Watson error = namei(&nd); 40295fab37eSRobert Watson if (error) 40395fab37eSRobert Watson goto out; 40495fab37eSRobert Watson 405eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 4069eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 40730d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 40830d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 40983b7b0edSRobert Watson mac.m_buflen); 410f7b951a8SRobert Watson NDFREE(&nd, 0); 4119eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 412eca8a663SRobert Watson mac_vnode_label_free(intlabel); 413f7b951a8SRobert Watson 414f7b951a8SRobert Watson if (error == 0) 415f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 41695fab37eSRobert Watson 41795fab37eSRobert Watson out: 418f7b951a8SRobert Watson free(buffer, M_MACTEMP); 419f7b951a8SRobert Watson free(elements, M_MACTEMP); 420f7b951a8SRobert Watson 42195fab37eSRobert Watson return (error); 42295fab37eSRobert Watson } 42395fab37eSRobert Watson 42495fab37eSRobert Watson int 4258451d0ddSKip Macy sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 42695fab37eSRobert Watson { 427eca8a663SRobert Watson struct label *intlabel; 428f7b951a8SRobert Watson struct pipe *pipe; 429b0323ea3SRobert Watson struct socket *so; 430f7b951a8SRobert Watson struct file *fp; 43195fab37eSRobert Watson struct mount *mp; 43295fab37eSRobert Watson struct vnode *vp; 433f7b951a8SRobert Watson struct mac mac; 434f7b951a8SRobert Watson char *buffer; 4359eea3d85SChristian S.J. Peron int error, vfslocked; 43695fab37eSRobert Watson 437f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 438f7b951a8SRobert Watson if (error) 439f7b951a8SRobert Watson return (error); 440f7b951a8SRobert Watson 441f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 442f7b951a8SRobert Watson if (error) 443f7b951a8SRobert Watson return (error); 444f7b951a8SRobert Watson 445a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 446f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 447f7b951a8SRobert Watson if (error) { 448f7b951a8SRobert Watson free(buffer, M_MACTEMP); 449f7b951a8SRobert Watson return (error); 450f7b951a8SRobert Watson } 451f7b951a8SRobert Watson 452a9d2f8d8SRobert Watson error = fget(td, uap->fd, CAP_MAC_SET, &fp); 45395fab37eSRobert Watson if (error) 454f7b951a8SRobert Watson goto out; 45595fab37eSRobert Watson 45695fab37eSRobert Watson switch (fp->f_type) { 45795fab37eSRobert Watson case DTYPE_FIFO: 45895fab37eSRobert Watson case DTYPE_VNODE: 459*b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) { 460*b4ef8be2SRobert Watson error = EINVAL; 461*b4ef8be2SRobert Watson goto out_fdrop; 462*b4ef8be2SRobert Watson } 463eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 46430d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 465f7b951a8SRobert Watson if (error) { 466eca8a663SRobert Watson mac_vnode_label_free(intlabel); 467f7b951a8SRobert Watson break; 468f7b951a8SRobert Watson } 4693b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 4709eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 47195fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 472f7b951a8SRobert Watson if (error != 0) { 4739eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 474eca8a663SRobert Watson mac_vnode_label_free(intlabel); 47595fab37eSRobert Watson break; 476f7b951a8SRobert Watson } 477cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 478eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 47922db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 48095fab37eSRobert Watson vn_finished_write(mp); 4819eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 482eca8a663SRobert Watson mac_vnode_label_free(intlabel); 48395fab37eSRobert Watson break; 484f7b951a8SRobert Watson 48595fab37eSRobert Watson case DTYPE_PIPE: 486*b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) { 487*b4ef8be2SRobert Watson error = EINVAL; 488*b4ef8be2SRobert Watson goto out_fdrop; 489*b4ef8be2SRobert Watson } 490eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 49130d239bcSRobert Watson error = mac_pipe_internalize_label(intlabel, buffer); 492f7b951a8SRobert Watson if (error == 0) { 49348e3128bSMatthew Dillon pipe = fp->f_data; 4941aa37f53SRobert Watson PIPE_LOCK(pipe); 4954795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 4964795b82cSRobert Watson pipe->pipe_pair, intlabel); 4971aa37f53SRobert Watson PIPE_UNLOCK(pipe); 498f7b951a8SRobert Watson } 499eca8a663SRobert Watson mac_pipe_label_free(intlabel); 50095fab37eSRobert Watson break; 501f7b951a8SRobert Watson 502b0323ea3SRobert Watson case DTYPE_SOCKET: 503*b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 504*b4ef8be2SRobert Watson error = EINVAL; 505*b4ef8be2SRobert Watson goto out_fdrop; 506*b4ef8be2SRobert Watson } 507b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 50830d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 509b0323ea3SRobert Watson if (error == 0) { 510b0323ea3SRobert Watson so = fp->f_data; 511b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 512b0323ea3SRobert Watson intlabel); 513b0323ea3SRobert Watson } 514b0323ea3SRobert Watson mac_socket_label_free(intlabel); 515b0323ea3SRobert Watson break; 516b0323ea3SRobert Watson 51795fab37eSRobert Watson default: 51895fab37eSRobert Watson error = EINVAL; 51995fab37eSRobert Watson } 520*b4ef8be2SRobert Watson out_fdrop: 52195fab37eSRobert Watson fdrop(fp, td); 522f7b951a8SRobert Watson out: 523f7b951a8SRobert Watson free(buffer, M_MACTEMP); 52495fab37eSRobert Watson return (error); 52595fab37eSRobert Watson } 52695fab37eSRobert Watson 52795fab37eSRobert Watson int 5288451d0ddSKip Macy sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 52995fab37eSRobert Watson { 530eca8a663SRobert Watson struct label *intlabel; 531f7b951a8SRobert Watson struct nameidata nd; 53295fab37eSRobert Watson struct mount *mp; 533f7b951a8SRobert Watson struct mac mac; 534f7b951a8SRobert Watson char *buffer; 5359eea3d85SChristian S.J. Peron int vfslocked, error; 53695fab37eSRobert Watson 5376356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5386356dba0SRobert Watson return (EINVAL); 5396356dba0SRobert Watson 540f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 54195fab37eSRobert Watson if (error) 542f7b951a8SRobert Watson return (error); 54395fab37eSRobert Watson 544f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 54595fab37eSRobert Watson if (error) 546f7b951a8SRobert Watson return (error); 54795fab37eSRobert Watson 548a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 549f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 550f7b951a8SRobert Watson if (error) { 551f7b951a8SRobert Watson free(buffer, M_MACTEMP); 55295fab37eSRobert Watson return (error); 55395fab37eSRobert Watson } 55495fab37eSRobert Watson 555eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 55630d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 557f7b951a8SRobert Watson free(buffer, M_MACTEMP); 558eca8a663SRobert Watson if (error) 559eca8a663SRobert Watson goto out; 560f7b951a8SRobert Watson 5619eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 5629eea3d85SChristian S.J. Peron uap->path_p, td); 563f7b951a8SRobert Watson error = namei(&nd); 5649eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 565f7b951a8SRobert Watson if (error == 0) { 566f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 567d50ef66dSTor Egge if (error == 0) { 568eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 569f7b951a8SRobert Watson td->td_ucred); 570f7b951a8SRobert Watson vn_finished_write(mp); 571f7b951a8SRobert Watson } 572d50ef66dSTor Egge } 573f7b951a8SRobert Watson 574f7b951a8SRobert Watson NDFREE(&nd, 0); 5759eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 576eca8a663SRobert Watson out: 577eca8a663SRobert Watson mac_vnode_label_free(intlabel); 578f7b951a8SRobert Watson return (error); 579f7b951a8SRobert Watson } 580f7b951a8SRobert Watson 581f7b951a8SRobert Watson int 5828451d0ddSKip Macy sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 583f7b951a8SRobert Watson { 584eca8a663SRobert Watson struct label *intlabel; 585f7b951a8SRobert Watson struct nameidata nd; 586f7b951a8SRobert Watson struct mount *mp; 587f7b951a8SRobert Watson struct mac mac; 588f7b951a8SRobert Watson char *buffer; 5899eea3d85SChristian S.J. Peron int vfslocked, error; 590f7b951a8SRobert Watson 5916356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5926356dba0SRobert Watson return (EINVAL); 5936356dba0SRobert Watson 594f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 595f7b951a8SRobert Watson if (error) 596f7b951a8SRobert Watson return (error); 597f7b951a8SRobert Watson 598f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 599f7b951a8SRobert Watson if (error) 600f7b951a8SRobert Watson return (error); 601f7b951a8SRobert Watson 602a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 603f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 604f7b951a8SRobert Watson if (error) { 605f7b951a8SRobert Watson free(buffer, M_MACTEMP); 606f7b951a8SRobert Watson return (error); 607f7b951a8SRobert Watson } 608f7b951a8SRobert Watson 609eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 61030d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 611f7b951a8SRobert Watson free(buffer, M_MACTEMP); 612eca8a663SRobert Watson if (error) 613eca8a663SRobert Watson goto out; 614f7b951a8SRobert Watson 6159eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 6169eea3d85SChristian S.J. Peron uap->path_p, td); 617f7b951a8SRobert Watson error = namei(&nd); 6189eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 619f7b951a8SRobert Watson if (error == 0) { 620f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 621d50ef66dSTor Egge if (error == 0) { 622eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 623f7b951a8SRobert Watson td->td_ucred); 624f7b951a8SRobert Watson vn_finished_write(mp); 625f7b951a8SRobert Watson } 626d50ef66dSTor Egge } 627f7b951a8SRobert Watson 628f7b951a8SRobert Watson NDFREE(&nd, 0); 6299eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 630eca8a663SRobert Watson out: 631eca8a663SRobert Watson mac_vnode_label_free(intlabel); 632f7b951a8SRobert Watson return (error); 633f7b951a8SRobert Watson } 634f7b951a8SRobert Watson 63527f2eac7SRobert Watson int 6368451d0ddSKip Macy sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 63727f2eac7SRobert Watson { 63827f2eac7SRobert Watson struct mac_policy_conf *mpc; 63927f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 64040202729SRobert Watson int error; 64127f2eac7SRobert Watson 642d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 64327f2eac7SRobert Watson if (error) 64427f2eac7SRobert Watson return (error); 64527f2eac7SRobert Watson 64627f2eac7SRobert Watson error = ENOSYS; 647a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 64827f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 64927f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 65027f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 651d1e405c5SAlfred Perlstein uap->call, uap->arg); 65227f2eac7SRobert Watson goto out; 65327f2eac7SRobert Watson } 65427f2eac7SRobert Watson } 65527f2eac7SRobert Watson 65640202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 65740202729SRobert Watson mac_policy_slock_sleep(); 65841a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 65941a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 66041a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 66141a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 66241a17fe3SRobert Watson uap->call, uap->arg); 66341a17fe3SRobert Watson break; 66441a17fe3SRobert Watson } 66541a17fe3SRobert Watson } 66640202729SRobert Watson mac_policy_sunlock_sleep(); 66741a17fe3SRobert Watson } 66827f2eac7SRobert Watson out: 66927f2eac7SRobert Watson return (error); 67027f2eac7SRobert Watson } 67127f2eac7SRobert Watson 67295fab37eSRobert Watson #else /* !MAC */ 6737bc82500SRobert Watson 6747bc82500SRobert Watson int 6758451d0ddSKip Macy sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 676f7b951a8SRobert Watson { 677f7b951a8SRobert Watson 678f7b951a8SRobert Watson return (ENOSYS); 679f7b951a8SRobert Watson } 680f7b951a8SRobert Watson 681f7b951a8SRobert Watson int 6828451d0ddSKip Macy sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 6837bc82500SRobert Watson { 6847bc82500SRobert Watson 6857bc82500SRobert Watson return (ENOSYS); 6867bc82500SRobert Watson } 6877bc82500SRobert Watson 6887bc82500SRobert Watson int 6898451d0ddSKip Macy sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 6907bc82500SRobert Watson { 6917bc82500SRobert Watson 6927bc82500SRobert Watson return (ENOSYS); 6937bc82500SRobert Watson } 6947bc82500SRobert Watson 6957bc82500SRobert Watson int 6968451d0ddSKip Macy sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 6977bc82500SRobert Watson { 6987bc82500SRobert Watson 6997bc82500SRobert Watson return (ENOSYS); 7007bc82500SRobert Watson } 7017bc82500SRobert Watson 7027bc82500SRobert Watson int 7038451d0ddSKip Macy sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 7047bc82500SRobert Watson { 7057bc82500SRobert Watson 7067bc82500SRobert Watson return (ENOSYS); 7077bc82500SRobert Watson } 7087bc82500SRobert Watson 7097bc82500SRobert Watson int 7108451d0ddSKip Macy sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 711f7b951a8SRobert Watson { 712f7b951a8SRobert Watson 713f7b951a8SRobert Watson return (ENOSYS); 714f7b951a8SRobert Watson } 715f7b951a8SRobert Watson 716f7b951a8SRobert Watson int 7178451d0ddSKip Macy sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 7187bc82500SRobert Watson { 7197bc82500SRobert Watson 7207bc82500SRobert Watson return (ENOSYS); 7217bc82500SRobert Watson } 7227bc82500SRobert Watson 7237bc82500SRobert Watson int 7248451d0ddSKip Macy sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 7257bc82500SRobert Watson { 7267bc82500SRobert Watson 7277bc82500SRobert Watson return (ENOSYS); 7287bc82500SRobert Watson } 72995fab37eSRobert Watson 73027f2eac7SRobert Watson int 7318451d0ddSKip Macy sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 732f7b951a8SRobert Watson { 733f7b951a8SRobert Watson 734f7b951a8SRobert Watson return (ENOSYS); 735f7b951a8SRobert Watson } 736f7b951a8SRobert Watson 737f7b951a8SRobert Watson int 7388451d0ddSKip Macy sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 73927f2eac7SRobert Watson { 74027f2eac7SRobert Watson 74127f2eac7SRobert Watson return (ENOSYS); 74227f2eac7SRobert Watson } 74327f2eac7SRobert Watson 74419b78822SRobert Watson #endif /* !MAC */ 745