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