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> 5157b4252eSKonstantin Belousov #include <sys/fcntl.h> 5295fab37eSRobert Watson #include <sys/kernel.h> 5395fab37eSRobert Watson #include <sys/lock.h> 54b656366bSBruce Evans #include <sys/malloc.h> 5595fab37eSRobert Watson #include <sys/mutex.h> 5695fab37eSRobert Watson #include <sys/mac.h> 5795fab37eSRobert Watson #include <sys/proc.h> 5895fab37eSRobert Watson #include <sys/systm.h> 59*de5b1952SAlexander Leidinger #include <sys/sysctl.h> 607bc82500SRobert Watson #include <sys/sysproto.h> 617bc82500SRobert Watson #include <sys/sysent.h> 6295fab37eSRobert Watson #include <sys/vnode.h> 6395fab37eSRobert Watson #include <sys/mount.h> 6495fab37eSRobert Watson #include <sys/file.h> 6595fab37eSRobert Watson #include <sys/namei.h> 6695fab37eSRobert Watson #include <sys/socket.h> 6795fab37eSRobert Watson #include <sys/pipe.h> 6895fab37eSRobert Watson #include <sys/socketvar.h> 6995fab37eSRobert Watson 70aed55708SRobert Watson #include <security/mac/mac_framework.h> 716fa0475dSRobert Watson #include <security/mac/mac_internal.h> 720efd6615SRobert Watson #include <security/mac/mac_policy.h> 736fa0475dSRobert Watson 7495fab37eSRobert Watson #ifdef MAC 7595fab37eSRobert Watson 76*de5b1952SAlexander Leidinger FEATURE(mac, "Mandatory Access Control Framework support"); 77*de5b1952SAlexander Leidinger 78f7b951a8SRobert Watson int 79f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 80f7b951a8SRobert Watson { 81f7b951a8SRobert Watson char *elements, *buffer; 82f7b951a8SRobert Watson struct mac mac; 83f7b951a8SRobert Watson struct proc *tproc; 84f7b951a8SRobert Watson struct ucred *tcred; 85f7b951a8SRobert Watson int error; 86f7b951a8SRobert Watson 87d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 88f7b951a8SRobert Watson if (error) 89f7b951a8SRobert Watson return (error); 90f7b951a8SRobert Watson 91f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 92f7b951a8SRobert Watson if (error) 93f7b951a8SRobert Watson return (error); 94f7b951a8SRobert Watson 95f7b951a8SRobert Watson tproc = pfind(uap->pid); 96f7b951a8SRobert Watson if (tproc == NULL) 97f7b951a8SRobert Watson return (ESRCH); 98f7b951a8SRobert Watson 99f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 100f7b951a8SRobert Watson error = p_cansee(td, tproc); 101f7b951a8SRobert Watson if (error == 0) 102f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 103f7b951a8SRobert Watson PROC_UNLOCK(tproc); 104f7b951a8SRobert Watson if (error) 105f7b951a8SRobert Watson return (error); 106f7b951a8SRobert Watson 107a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 108f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 109f7b951a8SRobert Watson if (error) { 110f7b951a8SRobert Watson free(elements, M_MACTEMP); 111f7b951a8SRobert Watson crfree(tcred); 112f7b951a8SRobert Watson return (error); 113f7b951a8SRobert Watson } 114f7b951a8SRobert Watson 115a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 11630d239bcSRobert Watson error = mac_cred_externalize_label(tcred->cr_label, elements, 11783b7b0edSRobert Watson buffer, mac.m_buflen); 118f7b951a8SRobert Watson if (error == 0) 119f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 120f7b951a8SRobert Watson 121f7b951a8SRobert Watson free(buffer, M_MACTEMP); 122f7b951a8SRobert Watson free(elements, M_MACTEMP); 123f7b951a8SRobert Watson crfree(tcred); 124f7b951a8SRobert Watson return (error); 125f7b951a8SRobert Watson } 126f7b951a8SRobert Watson 12795fab37eSRobert Watson int 12895fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 12995fab37eSRobert Watson { 130f7b951a8SRobert Watson char *elements, *buffer; 131f7b951a8SRobert Watson struct mac mac; 13295fab37eSRobert Watson int error; 13395fab37eSRobert Watson 134f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 135f7b951a8SRobert Watson if (error) 136f7b951a8SRobert Watson return (error); 13795fab37eSRobert Watson 138f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 139f7b951a8SRobert Watson if (error) 140f7b951a8SRobert Watson return (error); 141f7b951a8SRobert Watson 142a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 143f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 144f7b951a8SRobert Watson if (error) { 145f7b951a8SRobert Watson free(elements, M_MACTEMP); 146f7b951a8SRobert Watson return (error); 147f7b951a8SRobert Watson } 148f7b951a8SRobert Watson 149a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 15030d239bcSRobert Watson error = mac_cred_externalize_label(td->td_ucred->cr_label, 15183b7b0edSRobert Watson elements, buffer, mac.m_buflen); 152f7b951a8SRobert Watson if (error == 0) 153f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 154f7b951a8SRobert Watson 155f7b951a8SRobert Watson free(buffer, M_MACTEMP); 156f7b951a8SRobert Watson free(elements, M_MACTEMP); 15795fab37eSRobert Watson return (error); 15895fab37eSRobert Watson } 15995fab37eSRobert Watson 16095fab37eSRobert Watson int 16195fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 16295fab37eSRobert Watson { 16395fab37eSRobert Watson struct ucred *newcred, *oldcred; 164eca8a663SRobert Watson struct label *intlabel; 165f7b951a8SRobert Watson struct proc *p; 166f7b951a8SRobert Watson struct mac mac; 167f7b951a8SRobert Watson char *buffer; 16895fab37eSRobert Watson int error; 16995fab37eSRobert Watson 1706356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_CRED)) 1716356dba0SRobert Watson return (EINVAL); 1726356dba0SRobert Watson 173f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 17495fab37eSRobert Watson if (error) 17595fab37eSRobert Watson return (error); 17695fab37eSRobert Watson 177f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 17895fab37eSRobert Watson if (error) 17995fab37eSRobert Watson return (error); 18095fab37eSRobert Watson 181a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 182f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 183f7b951a8SRobert Watson if (error) { 184f7b951a8SRobert Watson free(buffer, M_MACTEMP); 185f7b951a8SRobert Watson return (error); 186f7b951a8SRobert Watson } 187f7b951a8SRobert Watson 188eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 18930d239bcSRobert Watson error = mac_cred_internalize_label(intlabel, buffer); 190f7b951a8SRobert Watson free(buffer, M_MACTEMP); 191eca8a663SRobert Watson if (error) 192eca8a663SRobert Watson goto out; 193f7b951a8SRobert Watson 19495fab37eSRobert Watson newcred = crget(); 19595fab37eSRobert Watson 19695fab37eSRobert Watson p = td->td_proc; 19795fab37eSRobert Watson PROC_LOCK(p); 19895fab37eSRobert Watson oldcred = p->p_ucred; 19995fab37eSRobert Watson 20030d239bcSRobert Watson error = mac_cred_check_relabel(oldcred, intlabel); 20195fab37eSRobert Watson if (error) { 20295fab37eSRobert Watson PROC_UNLOCK(p); 20395fab37eSRobert Watson crfree(newcred); 204f7b951a8SRobert Watson goto out; 20595fab37eSRobert Watson } 20695fab37eSRobert Watson 20795fab37eSRobert Watson setsugid(p); 20895fab37eSRobert Watson crcopy(newcred, oldcred); 20930d239bcSRobert Watson mac_cred_relabel(newcred, intlabel); 21095fab37eSRobert Watson p->p_ucred = newcred; 211e5cb5e37SRobert Watson 21295fab37eSRobert Watson PROC_UNLOCK(p); 21395fab37eSRobert Watson crfree(oldcred); 2149215889dSRobert Watson mac_proc_vm_revoke(td); 215f7b951a8SRobert Watson 216f7b951a8SRobert Watson out: 217eca8a663SRobert Watson mac_cred_label_free(intlabel); 218f7b951a8SRobert Watson return (error); 21995fab37eSRobert Watson } 22095fab37eSRobert Watson 22195fab37eSRobert Watson int 22295fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 22395fab37eSRobert Watson { 224f7b951a8SRobert Watson char *elements, *buffer; 225eca8a663SRobert Watson struct label *intlabel; 22695fab37eSRobert Watson struct file *fp; 227f7b951a8SRobert Watson struct mac mac; 22895fab37eSRobert Watson struct vnode *vp; 22995fab37eSRobert Watson struct pipe *pipe; 230b0323ea3SRobert Watson struct socket *so; 231f7b951a8SRobert Watson short label_type; 2329eea3d85SChristian S.J. Peron int vfslocked, error; 23395fab37eSRobert Watson 234f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 235f7b951a8SRobert Watson if (error) 236f7b951a8SRobert Watson return (error); 23795fab37eSRobert Watson 238f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 239f7b951a8SRobert Watson if (error) 240f7b951a8SRobert Watson return (error); 241f7b951a8SRobert Watson 242a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 243f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 244f7b951a8SRobert Watson if (error) { 245f7b951a8SRobert Watson free(elements, M_MACTEMP); 246f7b951a8SRobert Watson return (error); 247f7b951a8SRobert Watson } 248f7b951a8SRobert Watson 249a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 250d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 25195fab37eSRobert Watson if (error) 25295fab37eSRobert Watson goto out; 25395fab37eSRobert Watson 254f7b951a8SRobert Watson label_type = fp->f_type; 25595fab37eSRobert Watson switch (fp->f_type) { 25695fab37eSRobert Watson case DTYPE_FIFO: 25795fab37eSRobert Watson case DTYPE_VNODE: 2586356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 2596356dba0SRobert Watson return (EINVAL); 2603b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 261eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 2629eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 263cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 26430d239bcSRobert Watson mac_vnode_copy_label(vp->v_label, intlabel); 26522db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 2669eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 26730d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, 268f0ab0442SRobert Watson buffer, mac.m_buflen); 269f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 27095fab37eSRobert Watson break; 271f0ab0442SRobert Watson 27295fab37eSRobert Watson case DTYPE_PIPE: 2736356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) 2746356dba0SRobert Watson return (EINVAL); 27548e3128bSMatthew Dillon pipe = fp->f_data; 276eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 277f7b951a8SRobert Watson PIPE_LOCK(pipe); 27830d239bcSRobert Watson mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel); 279f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 28030d239bcSRobert Watson error = mac_pipe_externalize_label(intlabel, elements, 28183b7b0edSRobert Watson buffer, mac.m_buflen); 282eca8a663SRobert Watson mac_pipe_label_free(intlabel); 283f7b951a8SRobert Watson break; 28495fab37eSRobert Watson 285b0323ea3SRobert Watson case DTYPE_SOCKET: 2866356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 2876356dba0SRobert Watson return (EINVAL); 288b0323ea3SRobert Watson so = fp->f_data; 289b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 290f0c2044bSRobert Watson SOCK_LOCK(so); 29130d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 292f0c2044bSRobert Watson SOCK_UNLOCK(so); 29330d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, 294b0323ea3SRobert Watson buffer, mac.m_buflen); 295b0323ea3SRobert Watson mac_socket_label_free(intlabel); 296b0323ea3SRobert Watson break; 297b0323ea3SRobert Watson 298f0ab0442SRobert Watson default: 299f0ab0442SRobert Watson error = EINVAL; 300f0ab0442SRobert Watson } 301f0ab0442SRobert Watson fdrop(fp, td); 30295fab37eSRobert Watson if (error == 0) 303f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 30495fab37eSRobert Watson 30595fab37eSRobert Watson out: 306f7b951a8SRobert Watson free(buffer, M_MACTEMP); 307f7b951a8SRobert Watson free(elements, M_MACTEMP); 30895fab37eSRobert Watson return (error); 30995fab37eSRobert Watson } 31095fab37eSRobert Watson 31195fab37eSRobert Watson int 31295fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 31395fab37eSRobert Watson { 314f7b951a8SRobert Watson char *elements, *buffer; 31595fab37eSRobert Watson struct nameidata nd; 316eca8a663SRobert Watson struct label *intlabel; 317f7b951a8SRobert Watson struct mac mac; 3189eea3d85SChristian S.J. Peron int vfslocked, error; 31995fab37eSRobert Watson 3206356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3216356dba0SRobert Watson return (EINVAL); 3226356dba0SRobert Watson 323f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 324f7b951a8SRobert Watson if (error) 325f7b951a8SRobert Watson return (error); 326f7b951a8SRobert Watson 327f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 328f7b951a8SRobert Watson if (error) 329f7b951a8SRobert Watson return (error); 330f7b951a8SRobert Watson 331a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 332f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 333f7b951a8SRobert Watson if (error) { 334f7b951a8SRobert Watson free(elements, M_MACTEMP); 335f7b951a8SRobert Watson return (error); 336f7b951a8SRobert Watson } 337f7b951a8SRobert Watson 338a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3399eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 3409eea3d85SChristian S.J. Peron uap->path_p, td); 34195fab37eSRobert Watson error = namei(&nd); 34295fab37eSRobert Watson if (error) 34395fab37eSRobert Watson goto out; 34495fab37eSRobert Watson 345eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 3469eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 34730d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 34830d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 34983b7b0edSRobert Watson mac.m_buflen); 350f7b951a8SRobert Watson 35195fab37eSRobert Watson NDFREE(&nd, 0); 3529eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 353eca8a663SRobert Watson mac_vnode_label_free(intlabel); 354f7b951a8SRobert Watson if (error == 0) 355f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 356f7b951a8SRobert Watson 357f7b951a8SRobert Watson out: 358f7b951a8SRobert Watson free(buffer, M_MACTEMP); 359f7b951a8SRobert Watson free(elements, M_MACTEMP); 360f7b951a8SRobert Watson 361f7b951a8SRobert Watson return (error); 362f7b951a8SRobert Watson } 363f7b951a8SRobert Watson 364f7b951a8SRobert Watson int 365f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 366f7b951a8SRobert Watson { 367f7b951a8SRobert Watson char *elements, *buffer; 368f7b951a8SRobert Watson struct nameidata nd; 369eca8a663SRobert Watson struct label *intlabel; 370f7b951a8SRobert Watson struct mac mac; 3719eea3d85SChristian S.J. Peron int vfslocked, error; 372f7b951a8SRobert Watson 3736356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3746356dba0SRobert Watson return (EINVAL); 3756356dba0SRobert Watson 376f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 377f7b951a8SRobert Watson if (error) 378f7b951a8SRobert Watson return (error); 379f7b951a8SRobert Watson 380f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 381f7b951a8SRobert Watson if (error) 382f7b951a8SRobert Watson return (error); 383f7b951a8SRobert Watson 384a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 385f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 386f7b951a8SRobert Watson if (error) { 387f7b951a8SRobert Watson free(elements, M_MACTEMP); 388f7b951a8SRobert Watson return (error); 389f7b951a8SRobert Watson } 390f7b951a8SRobert Watson 391a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3929eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 3939eea3d85SChristian S.J. Peron uap->path_p, td); 394f7b951a8SRobert Watson error = namei(&nd); 39595fab37eSRobert Watson if (error) 39695fab37eSRobert Watson goto out; 39795fab37eSRobert Watson 398eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 3999eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 40030d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 40130d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 40283b7b0edSRobert Watson mac.m_buflen); 403f7b951a8SRobert Watson NDFREE(&nd, 0); 4049eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 405eca8a663SRobert Watson mac_vnode_label_free(intlabel); 406f7b951a8SRobert Watson 407f7b951a8SRobert Watson if (error == 0) 408f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 40995fab37eSRobert Watson 41095fab37eSRobert Watson out: 411f7b951a8SRobert Watson free(buffer, M_MACTEMP); 412f7b951a8SRobert Watson free(elements, M_MACTEMP); 413f7b951a8SRobert Watson 41495fab37eSRobert Watson return (error); 41595fab37eSRobert Watson } 41695fab37eSRobert Watson 41795fab37eSRobert Watson int 41895fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 41995fab37eSRobert Watson { 420eca8a663SRobert Watson struct label *intlabel; 421f7b951a8SRobert Watson struct pipe *pipe; 422b0323ea3SRobert Watson struct socket *so; 423f7b951a8SRobert Watson struct file *fp; 42495fab37eSRobert Watson struct mount *mp; 42595fab37eSRobert Watson struct vnode *vp; 426f7b951a8SRobert Watson struct mac mac; 427f7b951a8SRobert Watson char *buffer; 4289eea3d85SChristian S.J. Peron int error, vfslocked; 42995fab37eSRobert Watson 430f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 431f7b951a8SRobert Watson if (error) 432f7b951a8SRobert Watson return (error); 433f7b951a8SRobert Watson 434f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 435f7b951a8SRobert Watson if (error) 436f7b951a8SRobert Watson return (error); 437f7b951a8SRobert Watson 438a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 439f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 440f7b951a8SRobert Watson if (error) { 441f7b951a8SRobert Watson free(buffer, M_MACTEMP); 442f7b951a8SRobert Watson return (error); 443f7b951a8SRobert Watson } 444f7b951a8SRobert Watson 445d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 44695fab37eSRobert Watson if (error) 447f7b951a8SRobert Watson goto out; 44895fab37eSRobert Watson 44995fab37eSRobert Watson switch (fp->f_type) { 45095fab37eSRobert Watson case DTYPE_FIFO: 45195fab37eSRobert Watson case DTYPE_VNODE: 4526356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 4536356dba0SRobert Watson return (EINVAL); 454eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 45530d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 456f7b951a8SRobert Watson if (error) { 457eca8a663SRobert Watson mac_vnode_label_free(intlabel); 458f7b951a8SRobert Watson break; 459f7b951a8SRobert Watson } 4603b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 4619eea3d85SChristian S.J. Peron vfslocked = VFS_LOCK_GIANT(vp->v_mount); 46295fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 463f7b951a8SRobert Watson if (error != 0) { 4649eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 465eca8a663SRobert Watson mac_vnode_label_free(intlabel); 46695fab37eSRobert Watson break; 467f7b951a8SRobert Watson } 468cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 469eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 47022db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 47195fab37eSRobert Watson vn_finished_write(mp); 4729eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 473eca8a663SRobert Watson mac_vnode_label_free(intlabel); 47495fab37eSRobert Watson break; 475f7b951a8SRobert Watson 47695fab37eSRobert Watson case DTYPE_PIPE: 4776356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) 4786356dba0SRobert Watson return (EINVAL); 479eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 48030d239bcSRobert Watson error = mac_pipe_internalize_label(intlabel, buffer); 481f7b951a8SRobert Watson if (error == 0) { 48248e3128bSMatthew Dillon pipe = fp->f_data; 4831aa37f53SRobert Watson PIPE_LOCK(pipe); 4844795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 4854795b82cSRobert Watson pipe->pipe_pair, intlabel); 4861aa37f53SRobert Watson PIPE_UNLOCK(pipe); 487f7b951a8SRobert Watson } 488eca8a663SRobert Watson mac_pipe_label_free(intlabel); 48995fab37eSRobert Watson break; 490f7b951a8SRobert Watson 491b0323ea3SRobert Watson case DTYPE_SOCKET: 4926356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 4936356dba0SRobert Watson return (EINVAL); 494b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 49530d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 496b0323ea3SRobert Watson if (error == 0) { 497b0323ea3SRobert Watson so = fp->f_data; 498b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 499b0323ea3SRobert Watson intlabel); 500b0323ea3SRobert Watson } 501b0323ea3SRobert Watson mac_socket_label_free(intlabel); 502b0323ea3SRobert Watson break; 503b0323ea3SRobert Watson 50495fab37eSRobert Watson default: 50595fab37eSRobert Watson error = EINVAL; 50695fab37eSRobert Watson } 50795fab37eSRobert Watson fdrop(fp, td); 508f7b951a8SRobert Watson out: 509f7b951a8SRobert Watson free(buffer, M_MACTEMP); 51095fab37eSRobert Watson return (error); 51195fab37eSRobert Watson } 51295fab37eSRobert Watson 51395fab37eSRobert Watson int 51495fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 51595fab37eSRobert Watson { 516eca8a663SRobert Watson struct label *intlabel; 517f7b951a8SRobert Watson struct nameidata nd; 51895fab37eSRobert Watson struct mount *mp; 519f7b951a8SRobert Watson struct mac mac; 520f7b951a8SRobert Watson char *buffer; 5219eea3d85SChristian S.J. Peron int vfslocked, error; 52295fab37eSRobert Watson 5236356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5246356dba0SRobert Watson return (EINVAL); 5256356dba0SRobert Watson 526f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 52795fab37eSRobert Watson if (error) 528f7b951a8SRobert Watson return (error); 52995fab37eSRobert Watson 530f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 53195fab37eSRobert Watson if (error) 532f7b951a8SRobert Watson return (error); 53395fab37eSRobert Watson 534a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 535f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 536f7b951a8SRobert Watson if (error) { 537f7b951a8SRobert Watson free(buffer, M_MACTEMP); 53895fab37eSRobert Watson return (error); 53995fab37eSRobert Watson } 54095fab37eSRobert Watson 541eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 54230d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 543f7b951a8SRobert Watson free(buffer, M_MACTEMP); 544eca8a663SRobert Watson if (error) 545eca8a663SRobert Watson goto out; 546f7b951a8SRobert Watson 5479eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 5489eea3d85SChristian S.J. Peron uap->path_p, td); 549f7b951a8SRobert Watson error = namei(&nd); 5509eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 551f7b951a8SRobert Watson if (error == 0) { 552f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 553d50ef66dSTor Egge if (error == 0) { 554eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 555f7b951a8SRobert Watson td->td_ucred); 556f7b951a8SRobert Watson vn_finished_write(mp); 557f7b951a8SRobert Watson } 558d50ef66dSTor Egge } 559f7b951a8SRobert Watson 560f7b951a8SRobert Watson NDFREE(&nd, 0); 5619eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 562eca8a663SRobert Watson out: 563eca8a663SRobert Watson mac_vnode_label_free(intlabel); 564f7b951a8SRobert Watson return (error); 565f7b951a8SRobert Watson } 566f7b951a8SRobert Watson 567f7b951a8SRobert Watson int 568f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 569f7b951a8SRobert Watson { 570eca8a663SRobert Watson struct label *intlabel; 571f7b951a8SRobert Watson struct nameidata nd; 572f7b951a8SRobert Watson struct mount *mp; 573f7b951a8SRobert Watson struct mac mac; 574f7b951a8SRobert Watson char *buffer; 5759eea3d85SChristian S.J. Peron int vfslocked, error; 576f7b951a8SRobert Watson 5776356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5786356dba0SRobert Watson return (EINVAL); 5796356dba0SRobert Watson 580f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 581f7b951a8SRobert Watson if (error) 582f7b951a8SRobert Watson return (error); 583f7b951a8SRobert Watson 584f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 585f7b951a8SRobert Watson if (error) 586f7b951a8SRobert Watson return (error); 587f7b951a8SRobert Watson 588a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 589f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 590f7b951a8SRobert Watson if (error) { 591f7b951a8SRobert Watson free(buffer, M_MACTEMP); 592f7b951a8SRobert Watson return (error); 593f7b951a8SRobert Watson } 594f7b951a8SRobert Watson 595eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 59630d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 597f7b951a8SRobert Watson free(buffer, M_MACTEMP); 598eca8a663SRobert Watson if (error) 599eca8a663SRobert Watson goto out; 600f7b951a8SRobert Watson 6019eea3d85SChristian S.J. Peron NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 6029eea3d85SChristian S.J. Peron uap->path_p, td); 603f7b951a8SRobert Watson error = namei(&nd); 6049eea3d85SChristian S.J. Peron vfslocked = NDHASGIANT(&nd); 605f7b951a8SRobert Watson if (error == 0) { 606f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 607d50ef66dSTor Egge if (error == 0) { 608eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 609f7b951a8SRobert Watson td->td_ucred); 610f7b951a8SRobert Watson vn_finished_write(mp); 611f7b951a8SRobert Watson } 612d50ef66dSTor Egge } 613f7b951a8SRobert Watson 614f7b951a8SRobert Watson NDFREE(&nd, 0); 6159eea3d85SChristian S.J. Peron VFS_UNLOCK_GIANT(vfslocked); 616eca8a663SRobert Watson out: 617eca8a663SRobert Watson mac_vnode_label_free(intlabel); 618f7b951a8SRobert Watson return (error); 619f7b951a8SRobert Watson } 620f7b951a8SRobert Watson 62127f2eac7SRobert Watson int 62227f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 62327f2eac7SRobert Watson { 62427f2eac7SRobert Watson struct mac_policy_conf *mpc; 62527f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 62640202729SRobert Watson int error; 62727f2eac7SRobert Watson 628d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 62927f2eac7SRobert Watson if (error) 63027f2eac7SRobert Watson return (error); 63127f2eac7SRobert Watson 63227f2eac7SRobert Watson error = ENOSYS; 633a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 63427f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 63527f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 63627f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 637d1e405c5SAlfred Perlstein uap->call, uap->arg); 63827f2eac7SRobert Watson goto out; 63927f2eac7SRobert Watson } 64027f2eac7SRobert Watson } 64127f2eac7SRobert Watson 64240202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 64340202729SRobert Watson mac_policy_slock_sleep(); 64441a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 64541a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 64641a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 64741a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 64841a17fe3SRobert Watson uap->call, uap->arg); 64941a17fe3SRobert Watson break; 65041a17fe3SRobert Watson } 65141a17fe3SRobert Watson } 65240202729SRobert Watson mac_policy_sunlock_sleep(); 65341a17fe3SRobert Watson } 65427f2eac7SRobert Watson out: 65527f2eac7SRobert Watson return (error); 65627f2eac7SRobert Watson } 65727f2eac7SRobert Watson 65895fab37eSRobert Watson #else /* !MAC */ 6597bc82500SRobert Watson 6607bc82500SRobert Watson int 661f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 662f7b951a8SRobert Watson { 663f7b951a8SRobert Watson 664f7b951a8SRobert Watson return (ENOSYS); 665f7b951a8SRobert Watson } 666f7b951a8SRobert Watson 667f7b951a8SRobert Watson int 6687bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 6697bc82500SRobert Watson { 6707bc82500SRobert Watson 6717bc82500SRobert Watson return (ENOSYS); 6727bc82500SRobert Watson } 6737bc82500SRobert Watson 6747bc82500SRobert Watson int 6757bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 6767bc82500SRobert Watson { 6777bc82500SRobert Watson 6787bc82500SRobert Watson return (ENOSYS); 6797bc82500SRobert Watson } 6807bc82500SRobert Watson 6817bc82500SRobert Watson int 6827bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 6837bc82500SRobert Watson { 6847bc82500SRobert Watson 6857bc82500SRobert Watson return (ENOSYS); 6867bc82500SRobert Watson } 6877bc82500SRobert Watson 6887bc82500SRobert Watson int 6897bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 6907bc82500SRobert Watson { 6917bc82500SRobert Watson 6927bc82500SRobert Watson return (ENOSYS); 6937bc82500SRobert Watson } 6947bc82500SRobert Watson 6957bc82500SRobert Watson int 696f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 697f7b951a8SRobert Watson { 698f7b951a8SRobert Watson 699f7b951a8SRobert Watson return (ENOSYS); 700f7b951a8SRobert Watson } 701f7b951a8SRobert Watson 702f7b951a8SRobert Watson int 7037bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 7047bc82500SRobert Watson { 7057bc82500SRobert Watson 7067bc82500SRobert Watson return (ENOSYS); 7077bc82500SRobert Watson } 7087bc82500SRobert Watson 7097bc82500SRobert Watson int 7107bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 7117bc82500SRobert Watson { 7127bc82500SRobert Watson 7137bc82500SRobert Watson return (ENOSYS); 7147bc82500SRobert Watson } 71595fab37eSRobert Watson 71627f2eac7SRobert Watson int 717f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 718f7b951a8SRobert Watson { 719f7b951a8SRobert Watson 720f7b951a8SRobert Watson return (ENOSYS); 721f7b951a8SRobert Watson } 722f7b951a8SRobert Watson 723f7b951a8SRobert Watson int 72427f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 72527f2eac7SRobert Watson { 72627f2eac7SRobert Watson 72727f2eac7SRobert Watson return (ENOSYS); 72827f2eac7SRobert Watson } 72927f2eac7SRobert Watson 73019b78822SRobert Watson #endif /* !MAC */ 731