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; 233*5050aa86SKonstantin Belousov int 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: 259b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) { 260b4ef8be2SRobert Watson error = EINVAL; 261b4ef8be2SRobert Watson goto out_fdrop; 262b4ef8be2SRobert Watson } 2633b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 264eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 265cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 26630d239bcSRobert Watson mac_vnode_copy_label(vp->v_label, intlabel); 26722db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 26830d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, 269f0ab0442SRobert Watson buffer, mac.m_buflen); 270f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 27195fab37eSRobert Watson break; 272f0ab0442SRobert Watson 27395fab37eSRobert Watson case DTYPE_PIPE: 274b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) { 275b4ef8be2SRobert Watson error = EINVAL; 276b4ef8be2SRobert Watson goto out_fdrop; 277b4ef8be2SRobert Watson } 27848e3128bSMatthew Dillon pipe = fp->f_data; 279eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 280f7b951a8SRobert Watson PIPE_LOCK(pipe); 28130d239bcSRobert Watson mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel); 282f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 28330d239bcSRobert Watson error = mac_pipe_externalize_label(intlabel, elements, 28483b7b0edSRobert Watson buffer, mac.m_buflen); 285eca8a663SRobert Watson mac_pipe_label_free(intlabel); 286f7b951a8SRobert Watson break; 28795fab37eSRobert Watson 288b0323ea3SRobert Watson case DTYPE_SOCKET: 289b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 290b4ef8be2SRobert Watson error = EINVAL; 291b4ef8be2SRobert Watson goto out_fdrop; 292b4ef8be2SRobert Watson } 293b0323ea3SRobert Watson so = fp->f_data; 294b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 295f0c2044bSRobert Watson SOCK_LOCK(so); 29630d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 297f0c2044bSRobert Watson SOCK_UNLOCK(so); 29830d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, 299b0323ea3SRobert Watson buffer, mac.m_buflen); 300b0323ea3SRobert Watson mac_socket_label_free(intlabel); 301b0323ea3SRobert Watson break; 302b0323ea3SRobert Watson 303f0ab0442SRobert Watson default: 304f0ab0442SRobert Watson error = EINVAL; 305f0ab0442SRobert Watson } 30695fab37eSRobert Watson if (error == 0) 307f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 308b4ef8be2SRobert Watson out_fdrop: 309b4ef8be2SRobert Watson fdrop(fp, td); 31095fab37eSRobert Watson out: 311f7b951a8SRobert Watson free(buffer, M_MACTEMP); 312f7b951a8SRobert Watson free(elements, M_MACTEMP); 31395fab37eSRobert Watson return (error); 31495fab37eSRobert Watson } 31595fab37eSRobert Watson 31695fab37eSRobert Watson int 3178451d0ddSKip Macy sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 31895fab37eSRobert Watson { 319f7b951a8SRobert Watson char *elements, *buffer; 32095fab37eSRobert Watson struct nameidata nd; 321eca8a663SRobert Watson struct label *intlabel; 322f7b951a8SRobert Watson struct mac mac; 323*5050aa86SKonstantin Belousov int error; 32495fab37eSRobert Watson 3256356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3266356dba0SRobert Watson return (EINVAL); 3276356dba0SRobert Watson 328f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 329f7b951a8SRobert Watson if (error) 330f7b951a8SRobert Watson return (error); 331f7b951a8SRobert Watson 332f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 333f7b951a8SRobert Watson if (error) 334f7b951a8SRobert Watson return (error); 335f7b951a8SRobert Watson 336a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 337f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 338f7b951a8SRobert Watson if (error) { 339f7b951a8SRobert Watson free(elements, M_MACTEMP); 340f7b951a8SRobert Watson return (error); 341f7b951a8SRobert Watson } 342f7b951a8SRobert Watson 343a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 344*5050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3459eea3d85SChristian S.J. Peron uap->path_p, td); 34695fab37eSRobert Watson error = namei(&nd); 34795fab37eSRobert Watson if (error) 34895fab37eSRobert Watson goto out; 34995fab37eSRobert Watson 350eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 35130d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 35230d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 35383b7b0edSRobert Watson mac.m_buflen); 354f7b951a8SRobert Watson 35595fab37eSRobert Watson NDFREE(&nd, 0); 356eca8a663SRobert Watson mac_vnode_label_free(intlabel); 357f7b951a8SRobert Watson if (error == 0) 358f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 359f7b951a8SRobert Watson 360f7b951a8SRobert Watson out: 361f7b951a8SRobert Watson free(buffer, M_MACTEMP); 362f7b951a8SRobert Watson free(elements, M_MACTEMP); 363f7b951a8SRobert Watson 364f7b951a8SRobert Watson return (error); 365f7b951a8SRobert Watson } 366f7b951a8SRobert Watson 367f7b951a8SRobert Watson int 3688451d0ddSKip Macy sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 369f7b951a8SRobert Watson { 370f7b951a8SRobert Watson char *elements, *buffer; 371f7b951a8SRobert Watson struct nameidata nd; 372eca8a663SRobert Watson struct label *intlabel; 373f7b951a8SRobert Watson struct mac mac; 374*5050aa86SKonstantin Belousov int error; 375f7b951a8SRobert Watson 3766356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3776356dba0SRobert Watson return (EINVAL); 3786356dba0SRobert Watson 379f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 380f7b951a8SRobert Watson if (error) 381f7b951a8SRobert Watson return (error); 382f7b951a8SRobert Watson 383f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 384f7b951a8SRobert Watson if (error) 385f7b951a8SRobert Watson return (error); 386f7b951a8SRobert Watson 387a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 388f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 389f7b951a8SRobert Watson if (error) { 390f7b951a8SRobert Watson free(elements, M_MACTEMP); 391f7b951a8SRobert Watson return (error); 392f7b951a8SRobert Watson } 393f7b951a8SRobert Watson 394a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 395*5050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 3969eea3d85SChristian S.J. Peron uap->path_p, td); 397f7b951a8SRobert Watson error = namei(&nd); 39895fab37eSRobert Watson if (error) 39995fab37eSRobert Watson goto out; 40095fab37eSRobert Watson 401eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 40230d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 40330d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 40483b7b0edSRobert Watson mac.m_buflen); 405f7b951a8SRobert Watson NDFREE(&nd, 0); 406eca8a663SRobert Watson mac_vnode_label_free(intlabel); 407f7b951a8SRobert Watson 408f7b951a8SRobert Watson if (error == 0) 409f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 41095fab37eSRobert Watson 41195fab37eSRobert Watson out: 412f7b951a8SRobert Watson free(buffer, M_MACTEMP); 413f7b951a8SRobert Watson free(elements, M_MACTEMP); 414f7b951a8SRobert Watson 41595fab37eSRobert Watson return (error); 41695fab37eSRobert Watson } 41795fab37eSRobert Watson 41895fab37eSRobert Watson int 4198451d0ddSKip Macy sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 42095fab37eSRobert Watson { 421eca8a663SRobert Watson struct label *intlabel; 422f7b951a8SRobert Watson struct pipe *pipe; 423b0323ea3SRobert Watson struct socket *so; 424f7b951a8SRobert Watson struct file *fp; 42595fab37eSRobert Watson struct mount *mp; 42695fab37eSRobert Watson struct vnode *vp; 427f7b951a8SRobert Watson struct mac mac; 428f7b951a8SRobert Watson char *buffer; 429*5050aa86SKonstantin Belousov int error; 43095fab37eSRobert Watson 431f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 432f7b951a8SRobert Watson if (error) 433f7b951a8SRobert Watson return (error); 434f7b951a8SRobert Watson 435f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 436f7b951a8SRobert Watson if (error) 437f7b951a8SRobert Watson return (error); 438f7b951a8SRobert Watson 439a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 440f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 441f7b951a8SRobert Watson if (error) { 442f7b951a8SRobert Watson free(buffer, M_MACTEMP); 443f7b951a8SRobert Watson return (error); 444f7b951a8SRobert Watson } 445f7b951a8SRobert Watson 446a9d2f8d8SRobert Watson error = fget(td, uap->fd, CAP_MAC_SET, &fp); 44795fab37eSRobert Watson if (error) 448f7b951a8SRobert Watson goto out; 44995fab37eSRobert Watson 45095fab37eSRobert Watson switch (fp->f_type) { 45195fab37eSRobert Watson case DTYPE_FIFO: 45295fab37eSRobert Watson case DTYPE_VNODE: 453b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) { 454b4ef8be2SRobert Watson error = EINVAL; 455b4ef8be2SRobert Watson goto out_fdrop; 456b4ef8be2SRobert Watson } 457eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 45830d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 459f7b951a8SRobert Watson if (error) { 460eca8a663SRobert Watson mac_vnode_label_free(intlabel); 461f7b951a8SRobert Watson break; 462f7b951a8SRobert Watson } 4633b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 46495fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 465f7b951a8SRobert Watson if (error != 0) { 466eca8a663SRobert Watson mac_vnode_label_free(intlabel); 46795fab37eSRobert Watson break; 468f7b951a8SRobert Watson } 469cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 470eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 47122db15c0SAttilio Rao VOP_UNLOCK(vp, 0); 47295fab37eSRobert Watson vn_finished_write(mp); 473eca8a663SRobert Watson mac_vnode_label_free(intlabel); 47495fab37eSRobert Watson break; 475f7b951a8SRobert Watson 47695fab37eSRobert Watson case DTYPE_PIPE: 477b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) { 478b4ef8be2SRobert Watson error = EINVAL; 479b4ef8be2SRobert Watson goto out_fdrop; 480b4ef8be2SRobert Watson } 481eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 48230d239bcSRobert Watson error = mac_pipe_internalize_label(intlabel, buffer); 483f7b951a8SRobert Watson if (error == 0) { 48448e3128bSMatthew Dillon pipe = fp->f_data; 4851aa37f53SRobert Watson PIPE_LOCK(pipe); 4864795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 4874795b82cSRobert Watson pipe->pipe_pair, intlabel); 4881aa37f53SRobert Watson PIPE_UNLOCK(pipe); 489f7b951a8SRobert Watson } 490eca8a663SRobert Watson mac_pipe_label_free(intlabel); 49195fab37eSRobert Watson break; 492f7b951a8SRobert Watson 493b0323ea3SRobert Watson case DTYPE_SOCKET: 494b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 495b4ef8be2SRobert Watson error = EINVAL; 496b4ef8be2SRobert Watson goto out_fdrop; 497b4ef8be2SRobert Watson } 498b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 49930d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 500b0323ea3SRobert Watson if (error == 0) { 501b0323ea3SRobert Watson so = fp->f_data; 502b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 503b0323ea3SRobert Watson intlabel); 504b0323ea3SRobert Watson } 505b0323ea3SRobert Watson mac_socket_label_free(intlabel); 506b0323ea3SRobert Watson break; 507b0323ea3SRobert Watson 50895fab37eSRobert Watson default: 50995fab37eSRobert Watson error = EINVAL; 51095fab37eSRobert Watson } 511b4ef8be2SRobert Watson out_fdrop: 51295fab37eSRobert Watson fdrop(fp, td); 513f7b951a8SRobert Watson out: 514f7b951a8SRobert Watson free(buffer, M_MACTEMP); 51595fab37eSRobert Watson return (error); 51695fab37eSRobert Watson } 51795fab37eSRobert Watson 51895fab37eSRobert Watson int 5198451d0ddSKip Macy sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 52095fab37eSRobert Watson { 521eca8a663SRobert Watson struct label *intlabel; 522f7b951a8SRobert Watson struct nameidata nd; 52395fab37eSRobert Watson struct mount *mp; 524f7b951a8SRobert Watson struct mac mac; 525f7b951a8SRobert Watson char *buffer; 526*5050aa86SKonstantin Belousov int error; 52795fab37eSRobert Watson 5286356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5296356dba0SRobert Watson return (EINVAL); 5306356dba0SRobert Watson 531f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 53295fab37eSRobert Watson if (error) 533f7b951a8SRobert Watson return (error); 53495fab37eSRobert Watson 535f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 53695fab37eSRobert Watson if (error) 537f7b951a8SRobert Watson return (error); 53895fab37eSRobert Watson 539a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 540f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 541f7b951a8SRobert Watson if (error) { 542f7b951a8SRobert Watson free(buffer, M_MACTEMP); 54395fab37eSRobert Watson return (error); 54495fab37eSRobert Watson } 54595fab37eSRobert Watson 546eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 54730d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 548f7b951a8SRobert Watson free(buffer, M_MACTEMP); 549eca8a663SRobert Watson if (error) 550eca8a663SRobert Watson goto out; 551f7b951a8SRobert Watson 552*5050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 5539eea3d85SChristian S.J. Peron uap->path_p, td); 554f7b951a8SRobert Watson error = namei(&nd); 555f7b951a8SRobert Watson if (error == 0) { 556f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 557d50ef66dSTor Egge if (error == 0) { 558eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 559f7b951a8SRobert Watson td->td_ucred); 560f7b951a8SRobert Watson vn_finished_write(mp); 561f7b951a8SRobert Watson } 562d50ef66dSTor Egge } 563f7b951a8SRobert Watson 564f7b951a8SRobert Watson NDFREE(&nd, 0); 565eca8a663SRobert Watson out: 566eca8a663SRobert Watson mac_vnode_label_free(intlabel); 567f7b951a8SRobert Watson return (error); 568f7b951a8SRobert Watson } 569f7b951a8SRobert Watson 570f7b951a8SRobert Watson int 5718451d0ddSKip Macy sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 572f7b951a8SRobert Watson { 573eca8a663SRobert Watson struct label *intlabel; 574f7b951a8SRobert Watson struct nameidata nd; 575f7b951a8SRobert Watson struct mount *mp; 576f7b951a8SRobert Watson struct mac mac; 577f7b951a8SRobert Watson char *buffer; 578*5050aa86SKonstantin Belousov int error; 579f7b951a8SRobert Watson 5806356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5816356dba0SRobert Watson return (EINVAL); 5826356dba0SRobert Watson 583f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 584f7b951a8SRobert Watson if (error) 585f7b951a8SRobert Watson return (error); 586f7b951a8SRobert Watson 587f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 588f7b951a8SRobert Watson if (error) 589f7b951a8SRobert Watson return (error); 590f7b951a8SRobert Watson 591a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 592f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 593f7b951a8SRobert Watson if (error) { 594f7b951a8SRobert Watson free(buffer, M_MACTEMP); 595f7b951a8SRobert Watson return (error); 596f7b951a8SRobert Watson } 597f7b951a8SRobert Watson 598eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 59930d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 600f7b951a8SRobert Watson free(buffer, M_MACTEMP); 601eca8a663SRobert Watson if (error) 602eca8a663SRobert Watson goto out; 603f7b951a8SRobert Watson 604*5050aa86SKonstantin Belousov NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 6059eea3d85SChristian S.J. Peron uap->path_p, td); 606f7b951a8SRobert Watson error = namei(&nd); 607f7b951a8SRobert Watson if (error == 0) { 608f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 609d50ef66dSTor Egge if (error == 0) { 610eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 611f7b951a8SRobert Watson td->td_ucred); 612f7b951a8SRobert Watson vn_finished_write(mp); 613f7b951a8SRobert Watson } 614d50ef66dSTor Egge } 615f7b951a8SRobert Watson 616f7b951a8SRobert Watson NDFREE(&nd, 0); 617eca8a663SRobert Watson out: 618eca8a663SRobert Watson mac_vnode_label_free(intlabel); 619f7b951a8SRobert Watson return (error); 620f7b951a8SRobert Watson } 621f7b951a8SRobert Watson 62227f2eac7SRobert Watson int 6238451d0ddSKip Macy sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 62427f2eac7SRobert Watson { 62527f2eac7SRobert Watson struct mac_policy_conf *mpc; 62627f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 62740202729SRobert Watson int error; 62827f2eac7SRobert Watson 629d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 63027f2eac7SRobert Watson if (error) 63127f2eac7SRobert Watson return (error); 63227f2eac7SRobert Watson 63327f2eac7SRobert Watson error = ENOSYS; 634a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 63527f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 63627f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 63727f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 638d1e405c5SAlfred Perlstein uap->call, uap->arg); 63927f2eac7SRobert Watson goto out; 64027f2eac7SRobert Watson } 64127f2eac7SRobert Watson } 64227f2eac7SRobert Watson 64340202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 64440202729SRobert Watson mac_policy_slock_sleep(); 64541a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 64641a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 64741a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 64841a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 64941a17fe3SRobert Watson uap->call, uap->arg); 65041a17fe3SRobert Watson break; 65141a17fe3SRobert Watson } 65241a17fe3SRobert Watson } 65340202729SRobert Watson mac_policy_sunlock_sleep(); 65441a17fe3SRobert Watson } 65527f2eac7SRobert Watson out: 65627f2eac7SRobert Watson return (error); 65727f2eac7SRobert Watson } 65827f2eac7SRobert Watson 65995fab37eSRobert Watson #else /* !MAC */ 6607bc82500SRobert Watson 6617bc82500SRobert Watson int 6628451d0ddSKip Macy sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 663f7b951a8SRobert Watson { 664f7b951a8SRobert Watson 665f7b951a8SRobert Watson return (ENOSYS); 666f7b951a8SRobert Watson } 667f7b951a8SRobert Watson 668f7b951a8SRobert Watson int 6698451d0ddSKip Macy sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 6707bc82500SRobert Watson { 6717bc82500SRobert Watson 6727bc82500SRobert Watson return (ENOSYS); 6737bc82500SRobert Watson } 6747bc82500SRobert Watson 6757bc82500SRobert Watson int 6768451d0ddSKip Macy sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 6777bc82500SRobert Watson { 6787bc82500SRobert Watson 6797bc82500SRobert Watson return (ENOSYS); 6807bc82500SRobert Watson } 6817bc82500SRobert Watson 6827bc82500SRobert Watson int 6838451d0ddSKip Macy sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 6847bc82500SRobert Watson { 6857bc82500SRobert Watson 6867bc82500SRobert Watson return (ENOSYS); 6877bc82500SRobert Watson } 6887bc82500SRobert Watson 6897bc82500SRobert Watson int 6908451d0ddSKip Macy sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 6917bc82500SRobert Watson { 6927bc82500SRobert Watson 6937bc82500SRobert Watson return (ENOSYS); 6947bc82500SRobert Watson } 6957bc82500SRobert Watson 6967bc82500SRobert Watson int 6978451d0ddSKip Macy sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 698f7b951a8SRobert Watson { 699f7b951a8SRobert Watson 700f7b951a8SRobert Watson return (ENOSYS); 701f7b951a8SRobert Watson } 702f7b951a8SRobert Watson 703f7b951a8SRobert Watson int 7048451d0ddSKip Macy sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 7057bc82500SRobert Watson { 7067bc82500SRobert Watson 7077bc82500SRobert Watson return (ENOSYS); 7087bc82500SRobert Watson } 7097bc82500SRobert Watson 7107bc82500SRobert Watson int 7118451d0ddSKip Macy sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 7127bc82500SRobert Watson { 7137bc82500SRobert Watson 7147bc82500SRobert Watson return (ENOSYS); 7157bc82500SRobert Watson } 71695fab37eSRobert Watson 71727f2eac7SRobert Watson int 7188451d0ddSKip Macy sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 719f7b951a8SRobert Watson { 720f7b951a8SRobert Watson 721f7b951a8SRobert Watson return (ENOSYS); 722f7b951a8SRobert Watson } 723f7b951a8SRobert Watson 724f7b951a8SRobert Watson int 7258451d0ddSKip Macy sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 72627f2eac7SRobert Watson { 72727f2eac7SRobert Watson 72827f2eac7SRobert Watson return (ENOSYS); 72927f2eac7SRobert Watson } 73027f2eac7SRobert Watson 73119b78822SRobert Watson #endif /* !MAC */ 732