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> 514a144410SRobert Watson #include <sys/capsicum.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> 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 76d783bbd2SAlexander Leidinger FEATURE(security_mac, "Mandatory Access Control Framework support"); 77de5b1952SAlexander Leidinger 78d88fe103SBrooks Davis static int kern___mac_get_path(struct thread *td, const char *path_p, 79d88fe103SBrooks Davis struct mac *mac_p, int follow); 80d88fe103SBrooks Davis static int kern___mac_set_path(struct thread *td, const char *path_p, 81d88fe103SBrooks Davis struct mac *mac_p, int follow); 82d88fe103SBrooks Davis 83f7b951a8SRobert Watson int 848451d0ddSKip Macy sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 85f7b951a8SRobert Watson { 86f7b951a8SRobert Watson char *elements, *buffer; 87f7b951a8SRobert Watson struct mac mac; 88f7b951a8SRobert Watson struct proc *tproc; 89f7b951a8SRobert Watson struct ucred *tcred; 90f7b951a8SRobert Watson int error; 91f7b951a8SRobert Watson 92d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 93f7b951a8SRobert Watson if (error) 94f7b951a8SRobert Watson return (error); 95f7b951a8SRobert Watson 96f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 97f7b951a8SRobert Watson if (error) 98f7b951a8SRobert Watson return (error); 99f7b951a8SRobert Watson 100f7b951a8SRobert Watson tproc = pfind(uap->pid); 101f7b951a8SRobert Watson if (tproc == NULL) 102f7b951a8SRobert Watson return (ESRCH); 103f7b951a8SRobert Watson 104f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 105f7b951a8SRobert Watson error = p_cansee(td, tproc); 106f7b951a8SRobert Watson if (error == 0) 107f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 108f7b951a8SRobert Watson PROC_UNLOCK(tproc); 109f7b951a8SRobert Watson if (error) 110f7b951a8SRobert Watson return (error); 111f7b951a8SRobert Watson 112a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 113f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 114f7b951a8SRobert Watson if (error) { 115f7b951a8SRobert Watson free(elements, M_MACTEMP); 116f7b951a8SRobert Watson crfree(tcred); 117f7b951a8SRobert Watson return (error); 118f7b951a8SRobert Watson } 119f7b951a8SRobert Watson 120a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 12130d239bcSRobert Watson error = mac_cred_externalize_label(tcred->cr_label, elements, 12283b7b0edSRobert Watson buffer, mac.m_buflen); 123f7b951a8SRobert Watson if (error == 0) 124f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 125f7b951a8SRobert Watson 126f7b951a8SRobert Watson free(buffer, M_MACTEMP); 127f7b951a8SRobert Watson free(elements, M_MACTEMP); 128f7b951a8SRobert Watson crfree(tcred); 129f7b951a8SRobert Watson return (error); 130f7b951a8SRobert Watson } 131f7b951a8SRobert Watson 13295fab37eSRobert Watson int 1338451d0ddSKip Macy sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 13495fab37eSRobert Watson { 135f7b951a8SRobert Watson char *elements, *buffer; 136f7b951a8SRobert Watson struct mac mac; 13795fab37eSRobert Watson int error; 13895fab37eSRobert Watson 139f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 140f7b951a8SRobert Watson if (error) 141f7b951a8SRobert Watson return (error); 14295fab37eSRobert Watson 143f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 144f7b951a8SRobert Watson if (error) 145f7b951a8SRobert Watson return (error); 146f7b951a8SRobert Watson 147a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 148f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 149f7b951a8SRobert Watson if (error) { 150f7b951a8SRobert Watson free(elements, M_MACTEMP); 151f7b951a8SRobert Watson return (error); 152f7b951a8SRobert Watson } 153f7b951a8SRobert Watson 154a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 15530d239bcSRobert Watson error = mac_cred_externalize_label(td->td_ucred->cr_label, 15683b7b0edSRobert Watson elements, buffer, mac.m_buflen); 157f7b951a8SRobert Watson if (error == 0) 158f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 159f7b951a8SRobert Watson 160f7b951a8SRobert Watson free(buffer, M_MACTEMP); 161f7b951a8SRobert Watson free(elements, M_MACTEMP); 16295fab37eSRobert Watson return (error); 16395fab37eSRobert Watson } 16495fab37eSRobert Watson 16595fab37eSRobert Watson int 1668451d0ddSKip Macy sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 16795fab37eSRobert Watson { 16895fab37eSRobert Watson struct ucred *newcred, *oldcred; 169eca8a663SRobert Watson struct label *intlabel; 170f7b951a8SRobert Watson struct proc *p; 171f7b951a8SRobert Watson struct mac mac; 172f7b951a8SRobert Watson char *buffer; 17395fab37eSRobert Watson int error; 17495fab37eSRobert Watson 1756356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_CRED)) 1766356dba0SRobert Watson return (EINVAL); 1776356dba0SRobert Watson 178f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 17995fab37eSRobert Watson if (error) 18095fab37eSRobert Watson return (error); 18195fab37eSRobert Watson 182f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 18395fab37eSRobert Watson if (error) 18495fab37eSRobert Watson return (error); 18595fab37eSRobert Watson 186a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 187f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 188f7b951a8SRobert Watson if (error) { 189f7b951a8SRobert Watson free(buffer, M_MACTEMP); 190f7b951a8SRobert Watson return (error); 191f7b951a8SRobert Watson } 192f7b951a8SRobert Watson 193eca8a663SRobert Watson intlabel = mac_cred_label_alloc(); 19430d239bcSRobert Watson error = mac_cred_internalize_label(intlabel, buffer); 195f7b951a8SRobert Watson free(buffer, M_MACTEMP); 196eca8a663SRobert Watson if (error) 197eca8a663SRobert Watson goto out; 198f7b951a8SRobert Watson 19995fab37eSRobert Watson newcred = crget(); 20095fab37eSRobert Watson 20195fab37eSRobert Watson p = td->td_proc; 20295fab37eSRobert Watson PROC_LOCK(p); 20395fab37eSRobert Watson oldcred = p->p_ucred; 20495fab37eSRobert Watson 20530d239bcSRobert Watson error = mac_cred_check_relabel(oldcred, intlabel); 20695fab37eSRobert Watson if (error) { 20795fab37eSRobert Watson PROC_UNLOCK(p); 20895fab37eSRobert Watson crfree(newcred); 209f7b951a8SRobert Watson goto out; 21095fab37eSRobert Watson } 21195fab37eSRobert Watson 21295fab37eSRobert Watson setsugid(p); 21395fab37eSRobert Watson crcopy(newcred, oldcred); 21430d239bcSRobert Watson mac_cred_relabel(newcred, intlabel); 215daf63fd2SMateusz Guzik proc_set_cred(p, newcred); 216e5cb5e37SRobert Watson 21795fab37eSRobert Watson PROC_UNLOCK(p); 21895fab37eSRobert Watson crfree(oldcred); 2199215889dSRobert Watson mac_proc_vm_revoke(td); 220f7b951a8SRobert Watson 221f7b951a8SRobert Watson out: 222eca8a663SRobert Watson mac_cred_label_free(intlabel); 223f7b951a8SRobert Watson return (error); 22495fab37eSRobert Watson } 22595fab37eSRobert Watson 22695fab37eSRobert Watson int 2278451d0ddSKip Macy sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 22895fab37eSRobert Watson { 229f7b951a8SRobert Watson char *elements, *buffer; 230eca8a663SRobert Watson struct label *intlabel; 23195fab37eSRobert Watson struct file *fp; 232f7b951a8SRobert Watson struct mac mac; 23395fab37eSRobert Watson struct vnode *vp; 23495fab37eSRobert Watson struct pipe *pipe; 235b0323ea3SRobert Watson struct socket *so; 2367008be5bSPawel Jakub Dawidek cap_rights_t rights; 2375050aa86SKonstantin Belousov int error; 23895fab37eSRobert Watson 239f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 240f7b951a8SRobert Watson if (error) 241f7b951a8SRobert Watson return (error); 24295fab37eSRobert Watson 243f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 244f7b951a8SRobert Watson if (error) 245f7b951a8SRobert Watson return (error); 246f7b951a8SRobert Watson 247a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 248f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 249f7b951a8SRobert Watson if (error) { 250f7b951a8SRobert Watson free(elements, M_MACTEMP); 251f7b951a8SRobert Watson return (error); 252f7b951a8SRobert Watson } 253f7b951a8SRobert Watson 254a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2556b3a9a0fSMateusz Guzik error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_GET), 2566b3a9a0fSMateusz Guzik &fp); 25795fab37eSRobert Watson if (error) 25895fab37eSRobert Watson goto out; 25995fab37eSRobert Watson 26095fab37eSRobert Watson switch (fp->f_type) { 26195fab37eSRobert Watson case DTYPE_FIFO: 26295fab37eSRobert Watson case DTYPE_VNODE: 263b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) { 264b4ef8be2SRobert Watson error = EINVAL; 265b4ef8be2SRobert Watson goto out_fdrop; 266b4ef8be2SRobert Watson } 2673b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 268eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 269cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 27030d239bcSRobert Watson mac_vnode_copy_label(vp->v_label, intlabel); 271b249ce48SMateusz Guzik VOP_UNLOCK(vp); 27230d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, 273f0ab0442SRobert Watson buffer, mac.m_buflen); 274f0ab0442SRobert Watson mac_vnode_label_free(intlabel); 27595fab37eSRobert Watson break; 276f0ab0442SRobert Watson 27795fab37eSRobert Watson case DTYPE_PIPE: 278b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) { 279b4ef8be2SRobert Watson error = EINVAL; 280b4ef8be2SRobert Watson goto out_fdrop; 281b4ef8be2SRobert Watson } 28248e3128bSMatthew Dillon pipe = fp->f_data; 283eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 284f7b951a8SRobert Watson PIPE_LOCK(pipe); 28530d239bcSRobert Watson mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel); 286f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 28730d239bcSRobert Watson error = mac_pipe_externalize_label(intlabel, elements, 28883b7b0edSRobert Watson buffer, mac.m_buflen); 289eca8a663SRobert Watson mac_pipe_label_free(intlabel); 290f7b951a8SRobert Watson break; 29195fab37eSRobert Watson 292b0323ea3SRobert Watson case DTYPE_SOCKET: 293b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 294b4ef8be2SRobert Watson error = EINVAL; 295b4ef8be2SRobert Watson goto out_fdrop; 296b4ef8be2SRobert Watson } 297b0323ea3SRobert Watson so = fp->f_data; 298b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 299f0c2044bSRobert Watson SOCK_LOCK(so); 30030d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 301f0c2044bSRobert Watson SOCK_UNLOCK(so); 30230d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, 303b0323ea3SRobert Watson buffer, mac.m_buflen); 304b0323ea3SRobert Watson mac_socket_label_free(intlabel); 305b0323ea3SRobert Watson break; 306b0323ea3SRobert Watson 307f0ab0442SRobert Watson default: 308f0ab0442SRobert Watson error = EINVAL; 309f0ab0442SRobert Watson } 31095fab37eSRobert Watson if (error == 0) 311f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 312b4ef8be2SRobert Watson out_fdrop: 313b4ef8be2SRobert Watson fdrop(fp, td); 31495fab37eSRobert Watson out: 315f7b951a8SRobert Watson free(buffer, M_MACTEMP); 316f7b951a8SRobert Watson free(elements, M_MACTEMP); 31795fab37eSRobert Watson return (error); 31895fab37eSRobert Watson } 31995fab37eSRobert Watson 32095fab37eSRobert Watson int 3218451d0ddSKip Macy sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 32295fab37eSRobert Watson { 32395fab37eSRobert Watson 324d88fe103SBrooks Davis return (kern___mac_get_path(td, uap->path_p, uap->mac_p, FOLLOW)); 325f7b951a8SRobert Watson } 326f7b951a8SRobert Watson 327f7b951a8SRobert Watson int 3288451d0ddSKip Macy sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 329f7b951a8SRobert Watson { 330d88fe103SBrooks Davis 331d88fe103SBrooks Davis return (kern___mac_get_path(td, uap->path_p, uap->mac_p, NOFOLLOW)); 332d88fe103SBrooks Davis } 333d88fe103SBrooks Davis 334d88fe103SBrooks Davis static int 335d88fe103SBrooks Davis kern___mac_get_path(struct thread *td, const char *path_p, struct mac *mac_p, 336d88fe103SBrooks Davis int follow) 337d88fe103SBrooks Davis { 338f7b951a8SRobert Watson char *elements, *buffer; 339f7b951a8SRobert Watson struct nameidata nd; 340eca8a663SRobert Watson struct label *intlabel; 341f7b951a8SRobert Watson struct mac mac; 3425050aa86SKonstantin Belousov int error; 343f7b951a8SRobert Watson 3446356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 3456356dba0SRobert Watson return (EINVAL); 3466356dba0SRobert Watson 347d88fe103SBrooks Davis error = copyin(mac_p, &mac, sizeof(mac)); 348f7b951a8SRobert Watson if (error) 349f7b951a8SRobert Watson return (error); 350f7b951a8SRobert Watson 351f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 352f7b951a8SRobert Watson if (error) 353f7b951a8SRobert Watson return (error); 354f7b951a8SRobert Watson 355a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 356f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 357f7b951a8SRobert Watson if (error) { 358f7b951a8SRobert Watson free(elements, M_MACTEMP); 359f7b951a8SRobert Watson return (error); 360f7b951a8SRobert Watson } 361f7b951a8SRobert Watson 362a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3637e1d3eefSMateusz Guzik NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p); 364f7b951a8SRobert Watson error = namei(&nd); 36595fab37eSRobert Watson if (error) 36695fab37eSRobert Watson goto out; 36795fab37eSRobert Watson 368eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 36930d239bcSRobert Watson mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 37030d239bcSRobert Watson error = mac_vnode_externalize_label(intlabel, elements, buffer, 37183b7b0edSRobert Watson mac.m_buflen); 372*85dac03eSMateusz Guzik vput(nd.ni_vp); 373*85dac03eSMateusz Guzik NDFREE_PNBUF(&nd); 374eca8a663SRobert Watson mac_vnode_label_free(intlabel); 375f7b951a8SRobert Watson 376f7b951a8SRobert Watson if (error == 0) 377f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 37895fab37eSRobert Watson 37995fab37eSRobert Watson out: 380f7b951a8SRobert Watson free(buffer, M_MACTEMP); 381f7b951a8SRobert Watson free(elements, M_MACTEMP); 382f7b951a8SRobert Watson 38395fab37eSRobert Watson return (error); 38495fab37eSRobert Watson } 38595fab37eSRobert Watson 38695fab37eSRobert Watson int 3878451d0ddSKip Macy sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 38895fab37eSRobert Watson { 389eca8a663SRobert Watson struct label *intlabel; 390f7b951a8SRobert Watson struct pipe *pipe; 391b0323ea3SRobert Watson struct socket *so; 392f7b951a8SRobert Watson struct file *fp; 39395fab37eSRobert Watson struct mount *mp; 39495fab37eSRobert Watson struct vnode *vp; 395f7b951a8SRobert Watson struct mac mac; 3967008be5bSPawel Jakub Dawidek cap_rights_t rights; 397f7b951a8SRobert Watson char *buffer; 3985050aa86SKonstantin Belousov int error; 39995fab37eSRobert Watson 400f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 401f7b951a8SRobert Watson if (error) 402f7b951a8SRobert Watson return (error); 403f7b951a8SRobert Watson 404f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 405f7b951a8SRobert Watson if (error) 406f7b951a8SRobert Watson return (error); 407f7b951a8SRobert Watson 408a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 409f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 410f7b951a8SRobert Watson if (error) { 411f7b951a8SRobert Watson free(buffer, M_MACTEMP); 412f7b951a8SRobert Watson return (error); 413f7b951a8SRobert Watson } 414f7b951a8SRobert Watson 4156b3a9a0fSMateusz Guzik error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_SET), 4166b3a9a0fSMateusz Guzik &fp); 41795fab37eSRobert Watson if (error) 418f7b951a8SRobert Watson goto out; 41995fab37eSRobert Watson 42095fab37eSRobert Watson switch (fp->f_type) { 42195fab37eSRobert Watson case DTYPE_FIFO: 42295fab37eSRobert Watson case DTYPE_VNODE: 423b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) { 424b4ef8be2SRobert Watson error = EINVAL; 425b4ef8be2SRobert Watson goto out_fdrop; 426b4ef8be2SRobert Watson } 427eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 42830d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 429f7b951a8SRobert Watson if (error) { 430eca8a663SRobert Watson mac_vnode_label_free(intlabel); 431f7b951a8SRobert Watson break; 432f7b951a8SRobert Watson } 4333b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 434a75d1dddSMateusz Guzik error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH); 435f7b951a8SRobert Watson if (error != 0) { 436eca8a663SRobert Watson mac_vnode_label_free(intlabel); 43795fab37eSRobert Watson break; 438f7b951a8SRobert Watson } 439cb05b60aSAttilio Rao vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 440eca8a663SRobert Watson error = vn_setlabel(vp, intlabel, td->td_ucred); 441b249ce48SMateusz Guzik VOP_UNLOCK(vp); 44295fab37eSRobert Watson vn_finished_write(mp); 443eca8a663SRobert Watson mac_vnode_label_free(intlabel); 44495fab37eSRobert Watson break; 445f7b951a8SRobert Watson 44695fab37eSRobert Watson case DTYPE_PIPE: 447b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_PIPE)) { 448b4ef8be2SRobert Watson error = EINVAL; 449b4ef8be2SRobert Watson goto out_fdrop; 450b4ef8be2SRobert Watson } 451eca8a663SRobert Watson intlabel = mac_pipe_label_alloc(); 45230d239bcSRobert Watson error = mac_pipe_internalize_label(intlabel, buffer); 453f7b951a8SRobert Watson if (error == 0) { 45448e3128bSMatthew Dillon pipe = fp->f_data; 4551aa37f53SRobert Watson PIPE_LOCK(pipe); 4564795b82cSRobert Watson error = mac_pipe_label_set(td->td_ucred, 4574795b82cSRobert Watson pipe->pipe_pair, intlabel); 4581aa37f53SRobert Watson PIPE_UNLOCK(pipe); 459f7b951a8SRobert Watson } 460eca8a663SRobert Watson mac_pipe_label_free(intlabel); 46195fab37eSRobert Watson break; 462f7b951a8SRobert Watson 463b0323ea3SRobert Watson case DTYPE_SOCKET: 464b4ef8be2SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 465b4ef8be2SRobert Watson error = EINVAL; 466b4ef8be2SRobert Watson goto out_fdrop; 467b4ef8be2SRobert Watson } 468b0323ea3SRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 46930d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 470b0323ea3SRobert Watson if (error == 0) { 471b0323ea3SRobert Watson so = fp->f_data; 472b0323ea3SRobert Watson error = mac_socket_label_set(td->td_ucred, so, 473b0323ea3SRobert Watson intlabel); 474b0323ea3SRobert Watson } 475b0323ea3SRobert Watson mac_socket_label_free(intlabel); 476b0323ea3SRobert Watson break; 477b0323ea3SRobert Watson 47895fab37eSRobert Watson default: 47995fab37eSRobert Watson error = EINVAL; 48095fab37eSRobert Watson } 481b4ef8be2SRobert Watson out_fdrop: 48295fab37eSRobert Watson fdrop(fp, td); 483f7b951a8SRobert Watson out: 484f7b951a8SRobert Watson free(buffer, M_MACTEMP); 48595fab37eSRobert Watson return (error); 48695fab37eSRobert Watson } 48795fab37eSRobert Watson 48895fab37eSRobert Watson int 4898451d0ddSKip Macy sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 49095fab37eSRobert Watson { 49195fab37eSRobert Watson 492d88fe103SBrooks Davis return (kern___mac_set_path(td, uap->path_p, uap->mac_p, FOLLOW)); 493f7b951a8SRobert Watson } 494f7b951a8SRobert Watson 495f7b951a8SRobert Watson int 4968451d0ddSKip Macy sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 497f7b951a8SRobert Watson { 498d88fe103SBrooks Davis 499d88fe103SBrooks Davis return (kern___mac_set_path(td, uap->path_p, uap->mac_p, NOFOLLOW)); 500d88fe103SBrooks Davis } 501d88fe103SBrooks Davis 502d88fe103SBrooks Davis static int 503d88fe103SBrooks Davis kern___mac_set_path(struct thread *td, const char *path_p, struct mac *mac_p, 504d88fe103SBrooks Davis int follow) 505d88fe103SBrooks Davis { 506eca8a663SRobert Watson struct label *intlabel; 507f7b951a8SRobert Watson struct nameidata nd; 508f7b951a8SRobert Watson struct mount *mp; 509f7b951a8SRobert Watson struct mac mac; 510f7b951a8SRobert Watson char *buffer; 5115050aa86SKonstantin Belousov int error; 512f7b951a8SRobert Watson 5136356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_VNODE)) 5146356dba0SRobert Watson return (EINVAL); 5156356dba0SRobert Watson 516d88fe103SBrooks Davis error = copyin(mac_p, &mac, sizeof(mac)); 517f7b951a8SRobert Watson if (error) 518f7b951a8SRobert Watson return (error); 519f7b951a8SRobert Watson 520f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 521f7b951a8SRobert Watson if (error) 522f7b951a8SRobert Watson return (error); 523f7b951a8SRobert Watson 524a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 525f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 526f7b951a8SRobert Watson if (error) { 527f7b951a8SRobert Watson free(buffer, M_MACTEMP); 528f7b951a8SRobert Watson return (error); 529f7b951a8SRobert Watson } 530f7b951a8SRobert Watson 531eca8a663SRobert Watson intlabel = mac_vnode_label_alloc(); 53230d239bcSRobert Watson error = mac_vnode_internalize_label(intlabel, buffer); 533f7b951a8SRobert Watson free(buffer, M_MACTEMP); 534eca8a663SRobert Watson if (error) 535eca8a663SRobert Watson goto out; 536f7b951a8SRobert Watson 5377e1d3eefSMateusz Guzik NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p); 538f7b951a8SRobert Watson error = namei(&nd); 539f7b951a8SRobert Watson if (error == 0) { 540a75d1dddSMateusz Guzik error = vn_start_write(nd.ni_vp, &mp, V_WAIT | V_PCATCH); 541d50ef66dSTor Egge if (error == 0) { 542eca8a663SRobert Watson error = vn_setlabel(nd.ni_vp, intlabel, 543f7b951a8SRobert Watson td->td_ucred); 544f7b951a8SRobert Watson vn_finished_write(mp); 545f7b951a8SRobert Watson } 546*85dac03eSMateusz Guzik vput(nd.ni_vp); 547*85dac03eSMateusz Guzik NDFREE_PNBUF(&nd); 548d50ef66dSTor Egge } 549eca8a663SRobert Watson out: 550eca8a663SRobert Watson mac_vnode_label_free(intlabel); 551f7b951a8SRobert Watson return (error); 552f7b951a8SRobert Watson } 553f7b951a8SRobert Watson 55427f2eac7SRobert Watson int 5558451d0ddSKip Macy sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 55627f2eac7SRobert Watson { 55727f2eac7SRobert Watson struct mac_policy_conf *mpc; 55827f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 55940202729SRobert Watson int error; 56027f2eac7SRobert Watson 561d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 56227f2eac7SRobert Watson if (error) 56327f2eac7SRobert Watson return (error); 56427f2eac7SRobert Watson 56527f2eac7SRobert Watson error = ENOSYS; 566a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 56727f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 56827f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 56927f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 570d1e405c5SAlfred Perlstein uap->call, uap->arg); 57127f2eac7SRobert Watson goto out; 57227f2eac7SRobert Watson } 57327f2eac7SRobert Watson } 57427f2eac7SRobert Watson 57540202729SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 57640202729SRobert Watson mac_policy_slock_sleep(); 57741a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 57841a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 57941a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 58041a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 58141a17fe3SRobert Watson uap->call, uap->arg); 58241a17fe3SRobert Watson break; 58341a17fe3SRobert Watson } 58441a17fe3SRobert Watson } 58540202729SRobert Watson mac_policy_sunlock_sleep(); 58641a17fe3SRobert Watson } 58727f2eac7SRobert Watson out: 58827f2eac7SRobert Watson return (error); 58927f2eac7SRobert Watson } 59027f2eac7SRobert Watson 59195fab37eSRobert Watson #else /* !MAC */ 5927bc82500SRobert Watson 5937bc82500SRobert Watson int 5948451d0ddSKip Macy sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 595f7b951a8SRobert Watson { 596f7b951a8SRobert Watson 597f7b951a8SRobert Watson return (ENOSYS); 598f7b951a8SRobert Watson } 599f7b951a8SRobert Watson 600f7b951a8SRobert Watson int 6018451d0ddSKip Macy sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 6027bc82500SRobert Watson { 6037bc82500SRobert Watson 6047bc82500SRobert Watson return (ENOSYS); 6057bc82500SRobert Watson } 6067bc82500SRobert Watson 6077bc82500SRobert Watson int 6088451d0ddSKip Macy sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 6097bc82500SRobert Watson { 6107bc82500SRobert Watson 6117bc82500SRobert Watson return (ENOSYS); 6127bc82500SRobert Watson } 6137bc82500SRobert Watson 6147bc82500SRobert Watson int 6158451d0ddSKip Macy sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 6167bc82500SRobert Watson { 6177bc82500SRobert Watson 6187bc82500SRobert Watson return (ENOSYS); 6197bc82500SRobert Watson } 6207bc82500SRobert Watson 6217bc82500SRobert Watson int 6228451d0ddSKip Macy sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 6237bc82500SRobert Watson { 6247bc82500SRobert Watson 6257bc82500SRobert Watson return (ENOSYS); 6267bc82500SRobert Watson } 6277bc82500SRobert Watson 6287bc82500SRobert Watson int 6298451d0ddSKip Macy sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 630f7b951a8SRobert Watson { 631f7b951a8SRobert Watson 632f7b951a8SRobert Watson return (ENOSYS); 633f7b951a8SRobert Watson } 634f7b951a8SRobert Watson 635f7b951a8SRobert Watson int 6368451d0ddSKip Macy sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 6377bc82500SRobert Watson { 6387bc82500SRobert Watson 6397bc82500SRobert Watson return (ENOSYS); 6407bc82500SRobert Watson } 6417bc82500SRobert Watson 6427bc82500SRobert Watson int 6438451d0ddSKip Macy sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 6447bc82500SRobert Watson { 6457bc82500SRobert Watson 6467bc82500SRobert Watson return (ENOSYS); 6477bc82500SRobert Watson } 64895fab37eSRobert Watson 64927f2eac7SRobert Watson int 6508451d0ddSKip Macy sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 651f7b951a8SRobert Watson { 652f7b951a8SRobert Watson 653f7b951a8SRobert Watson return (ENOSYS); 654f7b951a8SRobert Watson } 655f7b951a8SRobert Watson 656f7b951a8SRobert Watson int 6578451d0ddSKip Macy sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 65827f2eac7SRobert Watson { 65927f2eac7SRobert Watson 66027f2eac7SRobert Watson return (ENOSYS); 66127f2eac7SRobert Watson } 66227f2eac7SRobert Watson 66319b78822SRobert Watson #endif /* !MAC */ 664