xref: /freebsd/sys/security/mac/mac_syscalls.c (revision cb05b60a8982e5497cd30449710deb2f4be653d4)
17bc82500SRobert Watson /*-
2471e5756SRobert Watson  * Copyright (c) 1999-2002, 2006 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.
67bc82500SRobert Watson  * All rights reserved.
77bc82500SRobert Watson  *
87bc82500SRobert Watson  * This software was developed by Robert Watson and Ilmar Habibulin for the
97bc82500SRobert Watson  * TrustedBSD Project.
107bc82500SRobert Watson  *
116201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
126201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
136201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
146201265bSRobert Watson  * as part of the DARPA CHATS research program.
157bc82500SRobert Watson  *
1649bb6870SRobert Watson  * This software was enhanced by SPARTA ISSO under SPAWAR contract
1749bb6870SRobert Watson  * N66001-04-C-6019 ("SEFOS").
1849bb6870SRobert Watson  *
197bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
207bc82500SRobert Watson  * modification, are permitted provided that the following conditions
217bc82500SRobert Watson  * are met:
227bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
237bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
247bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
257bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
267bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
277bc82500SRobert Watson  *
287bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
297bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
307bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
317bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
327bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
337bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
347bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
357bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
367bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
377bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
387bc82500SRobert Watson  * SUCH DAMAGE.
397bc82500SRobert Watson  */
40677b542eSDavid E. O'Brien 
41677b542eSDavid E. O'Brien #include <sys/cdefs.h>
42677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
43677b542eSDavid E. O'Brien 
447bc82500SRobert Watson #include "opt_mac.h"
45f9d0d524SRobert Watson 
467bc82500SRobert Watson #include <sys/param.h>
4795fab37eSRobert Watson #include <sys/kernel.h>
4895fab37eSRobert Watson #include <sys/lock.h>
49b656366bSBruce Evans #include <sys/malloc.h>
5095fab37eSRobert Watson #include <sys/mutex.h>
5195fab37eSRobert Watson #include <sys/mac.h>
5295fab37eSRobert Watson #include <sys/proc.h>
5395fab37eSRobert Watson #include <sys/systm.h>
547bc82500SRobert Watson #include <sys/sysproto.h>
557bc82500SRobert Watson #include <sys/sysent.h>
5695fab37eSRobert Watson #include <sys/vnode.h>
5795fab37eSRobert Watson #include <sys/mount.h>
5895fab37eSRobert Watson #include <sys/file.h>
5995fab37eSRobert Watson #include <sys/namei.h>
6095fab37eSRobert Watson #include <sys/socket.h>
6195fab37eSRobert Watson #include <sys/pipe.h>
6295fab37eSRobert Watson #include <sys/socketvar.h>
6395fab37eSRobert Watson 
64aed55708SRobert Watson #include <security/mac/mac_framework.h>
656fa0475dSRobert Watson #include <security/mac/mac_internal.h>
660efd6615SRobert Watson #include <security/mac/mac_policy.h>
676fa0475dSRobert Watson 
6895fab37eSRobert Watson #ifdef MAC
6995fab37eSRobert Watson 
70f7b951a8SRobert Watson int
71f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
72f7b951a8SRobert Watson {
73f7b951a8SRobert Watson 	char *elements, *buffer;
74f7b951a8SRobert Watson 	struct mac mac;
75f7b951a8SRobert Watson 	struct proc *tproc;
76f7b951a8SRobert Watson 	struct ucred *tcred;
77f7b951a8SRobert Watson 	int error;
78f7b951a8SRobert Watson 
79d1e405c5SAlfred Perlstein 	error = copyin(uap->mac_p, &mac, sizeof(mac));
80f7b951a8SRobert Watson 	if (error)
81f7b951a8SRobert Watson 		return (error);
82f7b951a8SRobert Watson 
83f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
84f7b951a8SRobert Watson 	if (error)
85f7b951a8SRobert Watson 		return (error);
86f7b951a8SRobert Watson 
87f7b951a8SRobert Watson 	tproc = pfind(uap->pid);
88f7b951a8SRobert Watson 	if (tproc == NULL)
89f7b951a8SRobert Watson 		return (ESRCH);
90f7b951a8SRobert Watson 
91f7b951a8SRobert Watson 	tcred = NULL;				/* Satisfy gcc. */
92f7b951a8SRobert Watson 	error = p_cansee(td, tproc);
93f7b951a8SRobert Watson 	if (error == 0)
94f7b951a8SRobert Watson 		tcred = crhold(tproc->p_ucred);
95f7b951a8SRobert Watson 	PROC_UNLOCK(tproc);
96f7b951a8SRobert Watson 	if (error)
97f7b951a8SRobert Watson 		return (error);
98f7b951a8SRobert Watson 
99a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
100f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
101f7b951a8SRobert Watson 	if (error) {
102f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
103f7b951a8SRobert Watson 		crfree(tcred);
104f7b951a8SRobert Watson 		return (error);
105f7b951a8SRobert Watson 	}
106f7b951a8SRobert Watson 
107a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
10830d239bcSRobert Watson 	error = mac_cred_externalize_label(tcred->cr_label, elements,
10983b7b0edSRobert Watson 	    buffer, mac.m_buflen);
110f7b951a8SRobert Watson 	if (error == 0)
111f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
112f7b951a8SRobert Watson 
113f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
114f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
115f7b951a8SRobert Watson 	crfree(tcred);
116f7b951a8SRobert Watson 	return (error);
117f7b951a8SRobert Watson }
118f7b951a8SRobert Watson 
11995fab37eSRobert Watson int
12095fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
12195fab37eSRobert Watson {
122f7b951a8SRobert Watson 	char *elements, *buffer;
123f7b951a8SRobert Watson 	struct mac mac;
12495fab37eSRobert Watson 	int error;
12595fab37eSRobert Watson 
126f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
127f7b951a8SRobert Watson 	if (error)
128f7b951a8SRobert Watson 		return (error);
12995fab37eSRobert Watson 
130f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
131f7b951a8SRobert Watson 	if (error)
132f7b951a8SRobert Watson 		return (error);
133f7b951a8SRobert Watson 
134a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
135f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
136f7b951a8SRobert Watson 	if (error) {
137f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
138f7b951a8SRobert Watson 		return (error);
139f7b951a8SRobert Watson 	}
140f7b951a8SRobert Watson 
141a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
14230d239bcSRobert Watson 	error = mac_cred_externalize_label(td->td_ucred->cr_label,
14383b7b0edSRobert Watson 	    elements, buffer, mac.m_buflen);
144f7b951a8SRobert Watson 	if (error == 0)
145f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
146f7b951a8SRobert Watson 
147f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
148f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
14995fab37eSRobert Watson 	return (error);
15095fab37eSRobert Watson }
15195fab37eSRobert Watson 
15295fab37eSRobert Watson int
15395fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
15495fab37eSRobert Watson {
15595fab37eSRobert Watson 	struct ucred *newcred, *oldcred;
156eca8a663SRobert Watson 	struct label *intlabel;
157f7b951a8SRobert Watson 	struct proc *p;
158f7b951a8SRobert Watson 	struct mac mac;
159f7b951a8SRobert Watson 	char *buffer;
16095fab37eSRobert Watson 	int error;
16195fab37eSRobert Watson 
162f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
16395fab37eSRobert Watson 	if (error)
16495fab37eSRobert Watson 		return (error);
16595fab37eSRobert Watson 
166f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
16795fab37eSRobert Watson 	if (error)
16895fab37eSRobert Watson 		return (error);
16995fab37eSRobert Watson 
170a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
171f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
172f7b951a8SRobert Watson 	if (error) {
173f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
174f7b951a8SRobert Watson 		return (error);
175f7b951a8SRobert Watson 	}
176f7b951a8SRobert Watson 
177eca8a663SRobert Watson 	intlabel = mac_cred_label_alloc();
17830d239bcSRobert Watson 	error = mac_cred_internalize_label(intlabel, buffer);
179f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
180eca8a663SRobert Watson 	if (error)
181eca8a663SRobert Watson 		goto out;
182f7b951a8SRobert Watson 
18395fab37eSRobert Watson 	newcred = crget();
18495fab37eSRobert Watson 
18595fab37eSRobert Watson 	p = td->td_proc;
18695fab37eSRobert Watson 	PROC_LOCK(p);
18795fab37eSRobert Watson 	oldcred = p->p_ucred;
18895fab37eSRobert Watson 
18930d239bcSRobert Watson 	error = mac_cred_check_relabel(oldcred, intlabel);
19095fab37eSRobert Watson 	if (error) {
19195fab37eSRobert Watson 		PROC_UNLOCK(p);
19295fab37eSRobert Watson 		crfree(newcred);
193f7b951a8SRobert Watson 		goto out;
19495fab37eSRobert Watson 	}
19595fab37eSRobert Watson 
19695fab37eSRobert Watson 	setsugid(p);
19795fab37eSRobert Watson 	crcopy(newcred, oldcred);
19830d239bcSRobert Watson 	mac_cred_relabel(newcred, intlabel);
19995fab37eSRobert Watson 	p->p_ucred = newcred;
200e5cb5e37SRobert Watson 
201e5cb5e37SRobert Watson 	/*
20217041e67SRobert Watson 	 * Grab additional reference for use while revoking mmaps, prior to
20317041e67SRobert Watson 	 * releasing the proc lock and sharing the cred.
204e5cb5e37SRobert Watson 	 */
205e5cb5e37SRobert Watson 	crhold(newcred);
20695fab37eSRobert Watson 	PROC_UNLOCK(p);
207e5cb5e37SRobert Watson 
208e5cb5e37SRobert Watson 	mac_cred_mmapped_drop_perms(td, newcred);
209e5cb5e37SRobert Watson 
210e5cb5e37SRobert Watson 	crfree(newcred);	/* Free revocation reference. */
21195fab37eSRobert Watson 	crfree(oldcred);
212f7b951a8SRobert Watson 
213f7b951a8SRobert Watson out:
214eca8a663SRobert Watson 	mac_cred_label_free(intlabel);
215f7b951a8SRobert Watson 	return (error);
21695fab37eSRobert Watson }
21795fab37eSRobert Watson 
21895fab37eSRobert Watson int
21995fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
22095fab37eSRobert Watson {
221f7b951a8SRobert Watson 	char *elements, *buffer;
222eca8a663SRobert Watson 	struct label *intlabel;
22395fab37eSRobert Watson 	struct file *fp;
224f7b951a8SRobert Watson 	struct mac mac;
22595fab37eSRobert Watson 	struct vnode *vp;
22695fab37eSRobert Watson 	struct pipe *pipe;
227b0323ea3SRobert Watson 	struct socket *so;
228f7b951a8SRobert Watson 	short label_type;
2299eea3d85SChristian S.J. Peron 	int vfslocked, error;
23095fab37eSRobert Watson 
231f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
232f7b951a8SRobert Watson 	if (error)
233f7b951a8SRobert Watson 		return (error);
23495fab37eSRobert Watson 
235f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
236f7b951a8SRobert Watson 	if (error)
237f7b951a8SRobert Watson 		return (error);
238f7b951a8SRobert Watson 
239a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
240f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
241f7b951a8SRobert Watson 	if (error) {
242f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
243f7b951a8SRobert Watson 		return (error);
244f7b951a8SRobert Watson 	}
245f7b951a8SRobert Watson 
246a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
247d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
24895fab37eSRobert Watson 	if (error)
24995fab37eSRobert Watson 		goto out;
25095fab37eSRobert Watson 
251f7b951a8SRobert Watson 	label_type = fp->f_type;
25295fab37eSRobert Watson 	switch (fp->f_type) {
25395fab37eSRobert Watson 	case DTYPE_FIFO:
25495fab37eSRobert Watson 	case DTYPE_VNODE:
2553b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
256eca8a663SRobert Watson 		intlabel = mac_vnode_label_alloc();
2579eea3d85SChristian S.J. Peron 		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
258cb05b60aSAttilio Rao 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
25930d239bcSRobert Watson 		mac_vnode_copy_label(vp->v_label, intlabel);
26095fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
2619eea3d85SChristian S.J. Peron 		VFS_UNLOCK_GIANT(vfslocked);
26230d239bcSRobert Watson 		error = mac_vnode_externalize_label(intlabel, elements,
263f0ab0442SRobert Watson 		    buffer, mac.m_buflen);
264f0ab0442SRobert Watson 		mac_vnode_label_free(intlabel);
26595fab37eSRobert Watson 		break;
266f0ab0442SRobert Watson 
26795fab37eSRobert Watson 	case DTYPE_PIPE:
26848e3128bSMatthew Dillon 		pipe = fp->f_data;
269eca8a663SRobert Watson 		intlabel = mac_pipe_label_alloc();
270f7b951a8SRobert Watson 		PIPE_LOCK(pipe);
27130d239bcSRobert Watson 		mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel);
272f7b951a8SRobert Watson 		PIPE_UNLOCK(pipe);
27330d239bcSRobert Watson 		error = mac_pipe_externalize_label(intlabel, elements,
27483b7b0edSRobert Watson 		    buffer, mac.m_buflen);
275eca8a663SRobert Watson 		mac_pipe_label_free(intlabel);
276f7b951a8SRobert Watson 		break;
27795fab37eSRobert Watson 
278b0323ea3SRobert Watson 	case DTYPE_SOCKET:
279b0323ea3SRobert Watson 		so = fp->f_data;
280b0323ea3SRobert Watson 		intlabel = mac_socket_label_alloc(M_WAITOK);
281f0c2044bSRobert Watson 		SOCK_LOCK(so);
28230d239bcSRobert Watson 		mac_socket_copy_label(so->so_label, intlabel);
283f0c2044bSRobert Watson 		SOCK_UNLOCK(so);
28430d239bcSRobert Watson 		error = mac_socket_externalize_label(intlabel, elements,
285b0323ea3SRobert Watson 		    buffer, mac.m_buflen);
286b0323ea3SRobert Watson 		mac_socket_label_free(intlabel);
287b0323ea3SRobert Watson 		break;
288b0323ea3SRobert Watson 
289f0ab0442SRobert Watson 	default:
290f0ab0442SRobert Watson 		error = EINVAL;
291f0ab0442SRobert Watson 	}
292f0ab0442SRobert Watson 	fdrop(fp, td);
29395fab37eSRobert Watson 	if (error == 0)
294f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
29595fab37eSRobert Watson 
29695fab37eSRobert Watson out:
297f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
298f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
29995fab37eSRobert Watson 	return (error);
30095fab37eSRobert Watson }
30195fab37eSRobert Watson 
30295fab37eSRobert Watson int
30395fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
30495fab37eSRobert Watson {
305f7b951a8SRobert Watson 	char *elements, *buffer;
30695fab37eSRobert Watson 	struct nameidata nd;
307eca8a663SRobert Watson 	struct label *intlabel;
308f7b951a8SRobert Watson 	struct mac mac;
3099eea3d85SChristian S.J. Peron 	int vfslocked, error;
31095fab37eSRobert Watson 
311f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
312f7b951a8SRobert Watson 	if (error)
313f7b951a8SRobert Watson 		return (error);
314f7b951a8SRobert Watson 
315f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
316f7b951a8SRobert Watson 	if (error)
317f7b951a8SRobert Watson 		return (error);
318f7b951a8SRobert Watson 
319a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
320f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
321f7b951a8SRobert Watson 	if (error) {
322f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
323f7b951a8SRobert Watson 		return (error);
324f7b951a8SRobert Watson 	}
325f7b951a8SRobert Watson 
326a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3279eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
3289eea3d85SChristian S.J. Peron 	    uap->path_p, td);
32995fab37eSRobert Watson 	error = namei(&nd);
33095fab37eSRobert Watson 	if (error)
33195fab37eSRobert Watson 		goto out;
33295fab37eSRobert Watson 
333eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
3349eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
33530d239bcSRobert Watson 	mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
33630d239bcSRobert Watson 	error = mac_vnode_externalize_label(intlabel, elements, buffer,
33783b7b0edSRobert Watson 	    mac.m_buflen);
338f7b951a8SRobert Watson 
33995fab37eSRobert Watson 	NDFREE(&nd, 0);
3409eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
341eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
342f7b951a8SRobert Watson 	if (error == 0)
343f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
344f7b951a8SRobert Watson 
345f7b951a8SRobert Watson out:
346f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
347f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
348f7b951a8SRobert Watson 
349f7b951a8SRobert Watson 	return (error);
350f7b951a8SRobert Watson }
351f7b951a8SRobert Watson 
352f7b951a8SRobert Watson int
353f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
354f7b951a8SRobert Watson {
355f7b951a8SRobert Watson 	char *elements, *buffer;
356f7b951a8SRobert Watson 	struct nameidata nd;
357eca8a663SRobert Watson 	struct label *intlabel;
358f7b951a8SRobert Watson 	struct mac mac;
3599eea3d85SChristian S.J. Peron 	int vfslocked, error;
360f7b951a8SRobert Watson 
361f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
362f7b951a8SRobert Watson 	if (error)
363f7b951a8SRobert Watson 		return (error);
364f7b951a8SRobert Watson 
365f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
366f7b951a8SRobert Watson 	if (error)
367f7b951a8SRobert Watson 		return (error);
368f7b951a8SRobert Watson 
369a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
370f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
371f7b951a8SRobert Watson 	if (error) {
372f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
373f7b951a8SRobert Watson 		return (error);
374f7b951a8SRobert Watson 	}
375f7b951a8SRobert Watson 
376a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3779eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
3789eea3d85SChristian S.J. Peron 	    uap->path_p, td);
379f7b951a8SRobert Watson 	error = namei(&nd);
38095fab37eSRobert Watson 	if (error)
38195fab37eSRobert Watson 		goto out;
38295fab37eSRobert Watson 
383eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
3849eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
38530d239bcSRobert Watson 	mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
38630d239bcSRobert Watson 	error = mac_vnode_externalize_label(intlabel, elements, buffer,
38783b7b0edSRobert Watson 	    mac.m_buflen);
388f7b951a8SRobert Watson 	NDFREE(&nd, 0);
3899eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
390eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
391f7b951a8SRobert Watson 
392f7b951a8SRobert Watson 	if (error == 0)
393f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
39495fab37eSRobert Watson 
39595fab37eSRobert Watson out:
396f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
397f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
398f7b951a8SRobert Watson 
39995fab37eSRobert Watson 	return (error);
40095fab37eSRobert Watson }
40195fab37eSRobert Watson 
40295fab37eSRobert Watson int
40395fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
40495fab37eSRobert Watson {
405eca8a663SRobert Watson 	struct label *intlabel;
406f7b951a8SRobert Watson 	struct pipe *pipe;
407b0323ea3SRobert Watson 	struct socket *so;
408f7b951a8SRobert Watson 	struct file *fp;
40995fab37eSRobert Watson 	struct mount *mp;
41095fab37eSRobert Watson 	struct vnode *vp;
411f7b951a8SRobert Watson 	struct mac mac;
412f7b951a8SRobert Watson 	char *buffer;
4139eea3d85SChristian S.J. Peron 	int error, vfslocked;
41495fab37eSRobert Watson 
415f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
416f7b951a8SRobert Watson 	if (error)
417f7b951a8SRobert Watson 		return (error);
418f7b951a8SRobert Watson 
419f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
420f7b951a8SRobert Watson 	if (error)
421f7b951a8SRobert Watson 		return (error);
422f7b951a8SRobert Watson 
423a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
424f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
425f7b951a8SRobert Watson 	if (error) {
426f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
427f7b951a8SRobert Watson 		return (error);
428f7b951a8SRobert Watson 	}
429f7b951a8SRobert Watson 
430d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
43195fab37eSRobert Watson 	if (error)
432f7b951a8SRobert Watson 		goto out;
43395fab37eSRobert Watson 
43495fab37eSRobert Watson 	switch (fp->f_type) {
43595fab37eSRobert Watson 	case DTYPE_FIFO:
43695fab37eSRobert Watson 	case DTYPE_VNODE:
437eca8a663SRobert Watson 		intlabel = mac_vnode_label_alloc();
43830d239bcSRobert Watson 		error = mac_vnode_internalize_label(intlabel, buffer);
439f7b951a8SRobert Watson 		if (error) {
440eca8a663SRobert Watson 			mac_vnode_label_free(intlabel);
441f7b951a8SRobert Watson 			break;
442f7b951a8SRobert Watson 		}
4433b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
4449eea3d85SChristian S.J. Peron 		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
44595fab37eSRobert Watson 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
446f7b951a8SRobert Watson 		if (error != 0) {
4479eea3d85SChristian S.J. Peron 			VFS_UNLOCK_GIANT(vfslocked);
448eca8a663SRobert Watson 			mac_vnode_label_free(intlabel);
44995fab37eSRobert Watson 			break;
450f7b951a8SRobert Watson 		}
451cb05b60aSAttilio Rao 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
452eca8a663SRobert Watson 		error = vn_setlabel(vp, intlabel, td->td_ucred);
45395fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
45495fab37eSRobert Watson 		vn_finished_write(mp);
4559eea3d85SChristian S.J. Peron 		VFS_UNLOCK_GIANT(vfslocked);
456eca8a663SRobert Watson 		mac_vnode_label_free(intlabel);
45795fab37eSRobert Watson 		break;
458f7b951a8SRobert Watson 
45995fab37eSRobert Watson 	case DTYPE_PIPE:
460eca8a663SRobert Watson 		intlabel = mac_pipe_label_alloc();
46130d239bcSRobert Watson 		error = mac_pipe_internalize_label(intlabel, buffer);
462f7b951a8SRobert Watson 		if (error == 0) {
46348e3128bSMatthew Dillon 			pipe = fp->f_data;
4641aa37f53SRobert Watson 			PIPE_LOCK(pipe);
4654795b82cSRobert Watson 			error = mac_pipe_label_set(td->td_ucred,
4664795b82cSRobert Watson 			    pipe->pipe_pair, intlabel);
4671aa37f53SRobert Watson 			PIPE_UNLOCK(pipe);
468f7b951a8SRobert Watson 		}
469eca8a663SRobert Watson 		mac_pipe_label_free(intlabel);
47095fab37eSRobert Watson 		break;
471f7b951a8SRobert Watson 
472b0323ea3SRobert Watson 	case DTYPE_SOCKET:
473b0323ea3SRobert Watson 		intlabel = mac_socket_label_alloc(M_WAITOK);
47430d239bcSRobert Watson 		error = mac_socket_internalize_label(intlabel, buffer);
475b0323ea3SRobert Watson 		if (error == 0) {
476b0323ea3SRobert Watson 			so = fp->f_data;
477b0323ea3SRobert Watson 			error = mac_socket_label_set(td->td_ucred, so,
478b0323ea3SRobert Watson 			    intlabel);
479b0323ea3SRobert Watson 		}
480b0323ea3SRobert Watson 		mac_socket_label_free(intlabel);
481b0323ea3SRobert Watson 		break;
482b0323ea3SRobert Watson 
48395fab37eSRobert Watson 	default:
48495fab37eSRobert Watson 		error = EINVAL;
48595fab37eSRobert Watson 	}
48695fab37eSRobert Watson 	fdrop(fp, td);
487f7b951a8SRobert Watson out:
488f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
48995fab37eSRobert Watson 	return (error);
49095fab37eSRobert Watson }
49195fab37eSRobert Watson 
49295fab37eSRobert Watson int
49395fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
49495fab37eSRobert Watson {
495eca8a663SRobert Watson 	struct label *intlabel;
496f7b951a8SRobert Watson 	struct nameidata nd;
49795fab37eSRobert Watson 	struct mount *mp;
498f7b951a8SRobert Watson 	struct mac mac;
499f7b951a8SRobert Watson 	char *buffer;
5009eea3d85SChristian S.J. Peron 	int vfslocked, error;
50195fab37eSRobert Watson 
502f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
50395fab37eSRobert Watson 	if (error)
504f7b951a8SRobert Watson 		return (error);
50595fab37eSRobert Watson 
506f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
50795fab37eSRobert Watson 	if (error)
508f7b951a8SRobert Watson 		return (error);
50995fab37eSRobert Watson 
510a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
511f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
512f7b951a8SRobert Watson 	if (error) {
513f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
51495fab37eSRobert Watson 		return (error);
51595fab37eSRobert Watson 	}
51695fab37eSRobert Watson 
517eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
51830d239bcSRobert Watson 	error = mac_vnode_internalize_label(intlabel, buffer);
519f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
520eca8a663SRobert Watson 	if (error)
521eca8a663SRobert Watson 		goto out;
522f7b951a8SRobert Watson 
5239eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
5249eea3d85SChristian S.J. Peron 	    uap->path_p, td);
525f7b951a8SRobert Watson 	error = namei(&nd);
5269eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
527f7b951a8SRobert Watson 	if (error == 0) {
528f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
529d50ef66dSTor Egge 		if (error == 0) {
530eca8a663SRobert Watson 			error = vn_setlabel(nd.ni_vp, intlabel,
531f7b951a8SRobert Watson 			    td->td_ucred);
532f7b951a8SRobert Watson 			vn_finished_write(mp);
533f7b951a8SRobert Watson 		}
534d50ef66dSTor Egge 	}
535f7b951a8SRobert Watson 
536f7b951a8SRobert Watson 	NDFREE(&nd, 0);
5379eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
538eca8a663SRobert Watson out:
539eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
540f7b951a8SRobert Watson 	return (error);
541f7b951a8SRobert Watson }
542f7b951a8SRobert Watson 
543f7b951a8SRobert Watson int
544f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
545f7b951a8SRobert Watson {
546eca8a663SRobert Watson 	struct label *intlabel;
547f7b951a8SRobert Watson 	struct nameidata nd;
548f7b951a8SRobert Watson 	struct mount *mp;
549f7b951a8SRobert Watson 	struct mac mac;
550f7b951a8SRobert Watson 	char *buffer;
5519eea3d85SChristian S.J. Peron 	int vfslocked, error;
552f7b951a8SRobert Watson 
553f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
554f7b951a8SRobert Watson 	if (error)
555f7b951a8SRobert Watson 		return (error);
556f7b951a8SRobert Watson 
557f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
558f7b951a8SRobert Watson 	if (error)
559f7b951a8SRobert Watson 		return (error);
560f7b951a8SRobert Watson 
561a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
562f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
563f7b951a8SRobert Watson 	if (error) {
564f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
565f7b951a8SRobert Watson 		return (error);
566f7b951a8SRobert Watson 	}
567f7b951a8SRobert Watson 
568eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
56930d239bcSRobert Watson 	error = mac_vnode_internalize_label(intlabel, buffer);
570f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
571eca8a663SRobert Watson 	if (error)
572eca8a663SRobert Watson 		goto out;
573f7b951a8SRobert Watson 
5749eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
5759eea3d85SChristian S.J. Peron 	    uap->path_p, td);
576f7b951a8SRobert Watson 	error = namei(&nd);
5779eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
578f7b951a8SRobert Watson 	if (error == 0) {
579f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
580d50ef66dSTor Egge 		if (error == 0) {
581eca8a663SRobert Watson 			error = vn_setlabel(nd.ni_vp, intlabel,
582f7b951a8SRobert Watson 			    td->td_ucred);
583f7b951a8SRobert Watson 			vn_finished_write(mp);
584f7b951a8SRobert Watson 		}
585d50ef66dSTor Egge 	}
586f7b951a8SRobert Watson 
587f7b951a8SRobert Watson 	NDFREE(&nd, 0);
5889eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
589eca8a663SRobert Watson out:
590eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
591f7b951a8SRobert Watson 	return (error);
592f7b951a8SRobert Watson }
593f7b951a8SRobert Watson 
59427f2eac7SRobert Watson int
59527f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
59627f2eac7SRobert Watson {
59727f2eac7SRobert Watson 	struct mac_policy_conf *mpc;
59827f2eac7SRobert Watson 	char target[MAC_MAX_POLICY_NAME];
59941a17fe3SRobert Watson 	int entrycount, error;
60027f2eac7SRobert Watson 
601d1e405c5SAlfred Perlstein 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
60227f2eac7SRobert Watson 	if (error)
60327f2eac7SRobert Watson 		return (error);
60427f2eac7SRobert Watson 
60527f2eac7SRobert Watson 	error = ENOSYS;
606a6a65b05SRobert Watson 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
60727f2eac7SRobert Watson 		if (strcmp(mpc->mpc_name, target) == 0 &&
60827f2eac7SRobert Watson 		    mpc->mpc_ops->mpo_syscall != NULL) {
60927f2eac7SRobert Watson 			error = mpc->mpc_ops->mpo_syscall(td,
610d1e405c5SAlfred Perlstein 			    uap->call, uap->arg);
61127f2eac7SRobert Watson 			goto out;
61227f2eac7SRobert Watson 		}
61327f2eac7SRobert Watson 	}
61427f2eac7SRobert Watson 
61541a17fe3SRobert Watson 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
61641a17fe3SRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
61741a17fe3SRobert Watson 			if (strcmp(mpc->mpc_name, target) == 0 &&
61841a17fe3SRobert Watson 			    mpc->mpc_ops->mpo_syscall != NULL) {
61941a17fe3SRobert Watson 				error = mpc->mpc_ops->mpo_syscall(td,
62041a17fe3SRobert Watson 				    uap->call, uap->arg);
62141a17fe3SRobert Watson 				break;
62241a17fe3SRobert Watson 			}
62341a17fe3SRobert Watson 		}
62441a17fe3SRobert Watson 		mac_policy_list_unbusy();
62541a17fe3SRobert Watson 	}
62627f2eac7SRobert Watson out:
62727f2eac7SRobert Watson 	return (error);
62827f2eac7SRobert Watson }
62927f2eac7SRobert Watson 
63095fab37eSRobert Watson #else /* !MAC */
6317bc82500SRobert Watson 
6327bc82500SRobert Watson int
633f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
634f7b951a8SRobert Watson {
635f7b951a8SRobert Watson 
636f7b951a8SRobert Watson 	return (ENOSYS);
637f7b951a8SRobert Watson }
638f7b951a8SRobert Watson 
639f7b951a8SRobert Watson int
6407bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
6417bc82500SRobert Watson {
6427bc82500SRobert Watson 
6437bc82500SRobert Watson 	return (ENOSYS);
6447bc82500SRobert Watson }
6457bc82500SRobert Watson 
6467bc82500SRobert Watson int
6477bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
6487bc82500SRobert Watson {
6497bc82500SRobert Watson 
6507bc82500SRobert Watson 	return (ENOSYS);
6517bc82500SRobert Watson }
6527bc82500SRobert Watson 
6537bc82500SRobert Watson int
6547bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
6557bc82500SRobert Watson {
6567bc82500SRobert Watson 
6577bc82500SRobert Watson 	return (ENOSYS);
6587bc82500SRobert Watson }
6597bc82500SRobert Watson 
6607bc82500SRobert Watson int
6617bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
6627bc82500SRobert Watson {
6637bc82500SRobert Watson 
6647bc82500SRobert Watson 	return (ENOSYS);
6657bc82500SRobert Watson }
6667bc82500SRobert Watson 
6677bc82500SRobert Watson int
668f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
669f7b951a8SRobert Watson {
670f7b951a8SRobert Watson 
671f7b951a8SRobert Watson 	return (ENOSYS);
672f7b951a8SRobert Watson }
673f7b951a8SRobert Watson 
674f7b951a8SRobert Watson int
6757bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
6767bc82500SRobert Watson {
6777bc82500SRobert Watson 
6787bc82500SRobert Watson 	return (ENOSYS);
6797bc82500SRobert Watson }
6807bc82500SRobert Watson 
6817bc82500SRobert Watson int
6827bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
6837bc82500SRobert Watson {
6847bc82500SRobert Watson 
6857bc82500SRobert Watson 	return (ENOSYS);
6867bc82500SRobert Watson }
68795fab37eSRobert Watson 
68827f2eac7SRobert Watson int
689f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
690f7b951a8SRobert Watson {
691f7b951a8SRobert Watson 
692f7b951a8SRobert Watson 	return (ENOSYS);
693f7b951a8SRobert Watson }
694f7b951a8SRobert Watson 
695f7b951a8SRobert Watson int
69627f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
69727f2eac7SRobert Watson {
69827f2eac7SRobert Watson 
69927f2eac7SRobert Watson 	return (ENOSYS);
70027f2eac7SRobert Watson }
70127f2eac7SRobert Watson 
70219b78822SRobert Watson #endif /* !MAC */
703