xref: /freebsd/sys/security/mac/mac_syscalls.c (revision 5050aa86cff105784877fb886a7b1d25bca5813b)
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