xref: /freebsd/sys/security/mac/mac_syscalls.c (revision de5b19526b7350b9c608ae4bf0bd80b91e51a5df)
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>
5157b4252eSKonstantin Belousov #include <sys/fcntl.h>
5295fab37eSRobert Watson #include <sys/kernel.h>
5395fab37eSRobert Watson #include <sys/lock.h>
54b656366bSBruce Evans #include <sys/malloc.h>
5595fab37eSRobert Watson #include <sys/mutex.h>
5695fab37eSRobert Watson #include <sys/mac.h>
5795fab37eSRobert Watson #include <sys/proc.h>
5895fab37eSRobert Watson #include <sys/systm.h>
59*de5b1952SAlexander Leidinger #include <sys/sysctl.h>
607bc82500SRobert Watson #include <sys/sysproto.h>
617bc82500SRobert Watson #include <sys/sysent.h>
6295fab37eSRobert Watson #include <sys/vnode.h>
6395fab37eSRobert Watson #include <sys/mount.h>
6495fab37eSRobert Watson #include <sys/file.h>
6595fab37eSRobert Watson #include <sys/namei.h>
6695fab37eSRobert Watson #include <sys/socket.h>
6795fab37eSRobert Watson #include <sys/pipe.h>
6895fab37eSRobert Watson #include <sys/socketvar.h>
6995fab37eSRobert Watson 
70aed55708SRobert Watson #include <security/mac/mac_framework.h>
716fa0475dSRobert Watson #include <security/mac/mac_internal.h>
720efd6615SRobert Watson #include <security/mac/mac_policy.h>
736fa0475dSRobert Watson 
7495fab37eSRobert Watson #ifdef MAC
7595fab37eSRobert Watson 
76*de5b1952SAlexander Leidinger FEATURE(mac, "Mandatory Access Control Framework support");
77*de5b1952SAlexander Leidinger 
78f7b951a8SRobert Watson int
79f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
80f7b951a8SRobert Watson {
81f7b951a8SRobert Watson 	char *elements, *buffer;
82f7b951a8SRobert Watson 	struct mac mac;
83f7b951a8SRobert Watson 	struct proc *tproc;
84f7b951a8SRobert Watson 	struct ucred *tcred;
85f7b951a8SRobert Watson 	int error;
86f7b951a8SRobert Watson 
87d1e405c5SAlfred Perlstein 	error = copyin(uap->mac_p, &mac, sizeof(mac));
88f7b951a8SRobert Watson 	if (error)
89f7b951a8SRobert Watson 		return (error);
90f7b951a8SRobert Watson 
91f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
92f7b951a8SRobert Watson 	if (error)
93f7b951a8SRobert Watson 		return (error);
94f7b951a8SRobert Watson 
95f7b951a8SRobert Watson 	tproc = pfind(uap->pid);
96f7b951a8SRobert Watson 	if (tproc == NULL)
97f7b951a8SRobert Watson 		return (ESRCH);
98f7b951a8SRobert Watson 
99f7b951a8SRobert Watson 	tcred = NULL;				/* Satisfy gcc. */
100f7b951a8SRobert Watson 	error = p_cansee(td, tproc);
101f7b951a8SRobert Watson 	if (error == 0)
102f7b951a8SRobert Watson 		tcred = crhold(tproc->p_ucred);
103f7b951a8SRobert Watson 	PROC_UNLOCK(tproc);
104f7b951a8SRobert Watson 	if (error)
105f7b951a8SRobert Watson 		return (error);
106f7b951a8SRobert Watson 
107a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
108f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
109f7b951a8SRobert Watson 	if (error) {
110f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
111f7b951a8SRobert Watson 		crfree(tcred);
112f7b951a8SRobert Watson 		return (error);
113f7b951a8SRobert Watson 	}
114f7b951a8SRobert Watson 
115a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
11630d239bcSRobert Watson 	error = mac_cred_externalize_label(tcred->cr_label, elements,
11783b7b0edSRobert Watson 	    buffer, mac.m_buflen);
118f7b951a8SRobert Watson 	if (error == 0)
119f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
120f7b951a8SRobert Watson 
121f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
122f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
123f7b951a8SRobert Watson 	crfree(tcred);
124f7b951a8SRobert Watson 	return (error);
125f7b951a8SRobert Watson }
126f7b951a8SRobert Watson 
12795fab37eSRobert Watson int
12895fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
12995fab37eSRobert Watson {
130f7b951a8SRobert Watson 	char *elements, *buffer;
131f7b951a8SRobert Watson 	struct mac mac;
13295fab37eSRobert Watson 	int error;
13395fab37eSRobert Watson 
134f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
135f7b951a8SRobert Watson 	if (error)
136f7b951a8SRobert Watson 		return (error);
13795fab37eSRobert Watson 
138f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
139f7b951a8SRobert Watson 	if (error)
140f7b951a8SRobert Watson 		return (error);
141f7b951a8SRobert Watson 
142a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
143f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
144f7b951a8SRobert Watson 	if (error) {
145f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
146f7b951a8SRobert Watson 		return (error);
147f7b951a8SRobert Watson 	}
148f7b951a8SRobert Watson 
149a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
15030d239bcSRobert Watson 	error = mac_cred_externalize_label(td->td_ucred->cr_label,
15183b7b0edSRobert Watson 	    elements, buffer, mac.m_buflen);
152f7b951a8SRobert Watson 	if (error == 0)
153f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
154f7b951a8SRobert Watson 
155f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
156f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
15795fab37eSRobert Watson 	return (error);
15895fab37eSRobert Watson }
15995fab37eSRobert Watson 
16095fab37eSRobert Watson int
16195fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
16295fab37eSRobert Watson {
16395fab37eSRobert Watson 	struct ucred *newcred, *oldcred;
164eca8a663SRobert Watson 	struct label *intlabel;
165f7b951a8SRobert Watson 	struct proc *p;
166f7b951a8SRobert Watson 	struct mac mac;
167f7b951a8SRobert Watson 	char *buffer;
16895fab37eSRobert Watson 	int error;
16995fab37eSRobert Watson 
1706356dba0SRobert Watson 	if (!(mac_labeled & MPC_OBJECT_CRED))
1716356dba0SRobert Watson 		return (EINVAL);
1726356dba0SRobert Watson 
173f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
17495fab37eSRobert Watson 	if (error)
17595fab37eSRobert Watson 		return (error);
17695fab37eSRobert Watson 
177f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
17895fab37eSRobert Watson 	if (error)
17995fab37eSRobert Watson 		return (error);
18095fab37eSRobert Watson 
181a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
182f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
183f7b951a8SRobert Watson 	if (error) {
184f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
185f7b951a8SRobert Watson 		return (error);
186f7b951a8SRobert Watson 	}
187f7b951a8SRobert Watson 
188eca8a663SRobert Watson 	intlabel = mac_cred_label_alloc();
18930d239bcSRobert Watson 	error = mac_cred_internalize_label(intlabel, buffer);
190f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
191eca8a663SRobert Watson 	if (error)
192eca8a663SRobert Watson 		goto out;
193f7b951a8SRobert Watson 
19495fab37eSRobert Watson 	newcred = crget();
19595fab37eSRobert Watson 
19695fab37eSRobert Watson 	p = td->td_proc;
19795fab37eSRobert Watson 	PROC_LOCK(p);
19895fab37eSRobert Watson 	oldcred = p->p_ucred;
19995fab37eSRobert Watson 
20030d239bcSRobert Watson 	error = mac_cred_check_relabel(oldcred, intlabel);
20195fab37eSRobert Watson 	if (error) {
20295fab37eSRobert Watson 		PROC_UNLOCK(p);
20395fab37eSRobert Watson 		crfree(newcred);
204f7b951a8SRobert Watson 		goto out;
20595fab37eSRobert Watson 	}
20695fab37eSRobert Watson 
20795fab37eSRobert Watson 	setsugid(p);
20895fab37eSRobert Watson 	crcopy(newcred, oldcred);
20930d239bcSRobert Watson 	mac_cred_relabel(newcred, intlabel);
21095fab37eSRobert Watson 	p->p_ucred = newcred;
211e5cb5e37SRobert Watson 
21295fab37eSRobert Watson 	PROC_UNLOCK(p);
21395fab37eSRobert Watson 	crfree(oldcred);
2149215889dSRobert Watson 	mac_proc_vm_revoke(td);
215f7b951a8SRobert Watson 
216f7b951a8SRobert Watson out:
217eca8a663SRobert Watson 	mac_cred_label_free(intlabel);
218f7b951a8SRobert Watson 	return (error);
21995fab37eSRobert Watson }
22095fab37eSRobert Watson 
22195fab37eSRobert Watson int
22295fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
22395fab37eSRobert Watson {
224f7b951a8SRobert Watson 	char *elements, *buffer;
225eca8a663SRobert Watson 	struct label *intlabel;
22695fab37eSRobert Watson 	struct file *fp;
227f7b951a8SRobert Watson 	struct mac mac;
22895fab37eSRobert Watson 	struct vnode *vp;
22995fab37eSRobert Watson 	struct pipe *pipe;
230b0323ea3SRobert Watson 	struct socket *so;
231f7b951a8SRobert Watson 	short label_type;
2329eea3d85SChristian S.J. Peron 	int vfslocked, error;
23395fab37eSRobert Watson 
234f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
235f7b951a8SRobert Watson 	if (error)
236f7b951a8SRobert Watson 		return (error);
23795fab37eSRobert Watson 
238f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
239f7b951a8SRobert Watson 	if (error)
240f7b951a8SRobert Watson 		return (error);
241f7b951a8SRobert Watson 
242a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
243f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
244f7b951a8SRobert Watson 	if (error) {
245f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
246f7b951a8SRobert Watson 		return (error);
247f7b951a8SRobert Watson 	}
248f7b951a8SRobert Watson 
249a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
250d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
25195fab37eSRobert Watson 	if (error)
25295fab37eSRobert Watson 		goto out;
25395fab37eSRobert Watson 
254f7b951a8SRobert Watson 	label_type = fp->f_type;
25595fab37eSRobert Watson 	switch (fp->f_type) {
25695fab37eSRobert Watson 	case DTYPE_FIFO:
25795fab37eSRobert Watson 	case DTYPE_VNODE:
2586356dba0SRobert Watson 		if (!(mac_labeled & MPC_OBJECT_VNODE))
2596356dba0SRobert Watson 			return (EINVAL);
2603b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
261eca8a663SRobert Watson 		intlabel = mac_vnode_label_alloc();
2629eea3d85SChristian S.J. Peron 		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
263cb05b60aSAttilio Rao 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
26430d239bcSRobert Watson 		mac_vnode_copy_label(vp->v_label, intlabel);
26522db15c0SAttilio Rao 		VOP_UNLOCK(vp, 0);
2669eea3d85SChristian S.J. Peron 		VFS_UNLOCK_GIANT(vfslocked);
26730d239bcSRobert Watson 		error = mac_vnode_externalize_label(intlabel, elements,
268f0ab0442SRobert Watson 		    buffer, mac.m_buflen);
269f0ab0442SRobert Watson 		mac_vnode_label_free(intlabel);
27095fab37eSRobert Watson 		break;
271f0ab0442SRobert Watson 
27295fab37eSRobert Watson 	case DTYPE_PIPE:
2736356dba0SRobert Watson 		if (!(mac_labeled & MPC_OBJECT_PIPE))
2746356dba0SRobert Watson 			return (EINVAL);
27548e3128bSMatthew Dillon 		pipe = fp->f_data;
276eca8a663SRobert Watson 		intlabel = mac_pipe_label_alloc();
277f7b951a8SRobert Watson 		PIPE_LOCK(pipe);
27830d239bcSRobert Watson 		mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel);
279f7b951a8SRobert Watson 		PIPE_UNLOCK(pipe);
28030d239bcSRobert Watson 		error = mac_pipe_externalize_label(intlabel, elements,
28183b7b0edSRobert Watson 		    buffer, mac.m_buflen);
282eca8a663SRobert Watson 		mac_pipe_label_free(intlabel);
283f7b951a8SRobert Watson 		break;
28495fab37eSRobert Watson 
285b0323ea3SRobert Watson 	case DTYPE_SOCKET:
2866356dba0SRobert Watson 		if (!(mac_labeled & MPC_OBJECT_SOCKET))
2876356dba0SRobert Watson 			return (EINVAL);
288b0323ea3SRobert Watson 		so = fp->f_data;
289b0323ea3SRobert Watson 		intlabel = mac_socket_label_alloc(M_WAITOK);
290f0c2044bSRobert Watson 		SOCK_LOCK(so);
29130d239bcSRobert Watson 		mac_socket_copy_label(so->so_label, intlabel);
292f0c2044bSRobert Watson 		SOCK_UNLOCK(so);
29330d239bcSRobert Watson 		error = mac_socket_externalize_label(intlabel, elements,
294b0323ea3SRobert Watson 		    buffer, mac.m_buflen);
295b0323ea3SRobert Watson 		mac_socket_label_free(intlabel);
296b0323ea3SRobert Watson 		break;
297b0323ea3SRobert Watson 
298f0ab0442SRobert Watson 	default:
299f0ab0442SRobert Watson 		error = EINVAL;
300f0ab0442SRobert Watson 	}
301f0ab0442SRobert Watson 	fdrop(fp, td);
30295fab37eSRobert Watson 	if (error == 0)
303f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
30495fab37eSRobert Watson 
30595fab37eSRobert Watson out:
306f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
307f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
30895fab37eSRobert Watson 	return (error);
30995fab37eSRobert Watson }
31095fab37eSRobert Watson 
31195fab37eSRobert Watson int
31295fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
31395fab37eSRobert Watson {
314f7b951a8SRobert Watson 	char *elements, *buffer;
31595fab37eSRobert Watson 	struct nameidata nd;
316eca8a663SRobert Watson 	struct label *intlabel;
317f7b951a8SRobert Watson 	struct mac mac;
3189eea3d85SChristian S.J. Peron 	int vfslocked, error;
31995fab37eSRobert Watson 
3206356dba0SRobert Watson 	if (!(mac_labeled & MPC_OBJECT_VNODE))
3216356dba0SRobert Watson 		return (EINVAL);
3226356dba0SRobert Watson 
323f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
324f7b951a8SRobert Watson 	if (error)
325f7b951a8SRobert Watson 		return (error);
326f7b951a8SRobert Watson 
327f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
328f7b951a8SRobert Watson 	if (error)
329f7b951a8SRobert Watson 		return (error);
330f7b951a8SRobert Watson 
331a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
332f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
333f7b951a8SRobert Watson 	if (error) {
334f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
335f7b951a8SRobert Watson 		return (error);
336f7b951a8SRobert Watson 	}
337f7b951a8SRobert Watson 
338a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3399eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
3409eea3d85SChristian S.J. Peron 	    uap->path_p, td);
34195fab37eSRobert Watson 	error = namei(&nd);
34295fab37eSRobert Watson 	if (error)
34395fab37eSRobert Watson 		goto out;
34495fab37eSRobert Watson 
345eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
3469eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
34730d239bcSRobert Watson 	mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
34830d239bcSRobert Watson 	error = mac_vnode_externalize_label(intlabel, elements, buffer,
34983b7b0edSRobert Watson 	    mac.m_buflen);
350f7b951a8SRobert Watson 
35195fab37eSRobert Watson 	NDFREE(&nd, 0);
3529eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
353eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
354f7b951a8SRobert Watson 	if (error == 0)
355f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
356f7b951a8SRobert Watson 
357f7b951a8SRobert Watson out:
358f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
359f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
360f7b951a8SRobert Watson 
361f7b951a8SRobert Watson 	return (error);
362f7b951a8SRobert Watson }
363f7b951a8SRobert Watson 
364f7b951a8SRobert Watson int
365f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
366f7b951a8SRobert Watson {
367f7b951a8SRobert Watson 	char *elements, *buffer;
368f7b951a8SRobert Watson 	struct nameidata nd;
369eca8a663SRobert Watson 	struct label *intlabel;
370f7b951a8SRobert Watson 	struct mac mac;
3719eea3d85SChristian S.J. Peron 	int vfslocked, error;
372f7b951a8SRobert Watson 
3736356dba0SRobert Watson 	if (!(mac_labeled & MPC_OBJECT_VNODE))
3746356dba0SRobert Watson 		return (EINVAL);
3756356dba0SRobert Watson 
376f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
377f7b951a8SRobert Watson 	if (error)
378f7b951a8SRobert Watson 		return (error);
379f7b951a8SRobert Watson 
380f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
381f7b951a8SRobert Watson 	if (error)
382f7b951a8SRobert Watson 		return (error);
383f7b951a8SRobert Watson 
384a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
385f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
386f7b951a8SRobert Watson 	if (error) {
387f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
388f7b951a8SRobert Watson 		return (error);
389f7b951a8SRobert Watson 	}
390f7b951a8SRobert Watson 
391a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3929eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
3939eea3d85SChristian S.J. Peron 	    uap->path_p, td);
394f7b951a8SRobert Watson 	error = namei(&nd);
39595fab37eSRobert Watson 	if (error)
39695fab37eSRobert Watson 		goto out;
39795fab37eSRobert Watson 
398eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
3999eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
40030d239bcSRobert Watson 	mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
40130d239bcSRobert Watson 	error = mac_vnode_externalize_label(intlabel, elements, buffer,
40283b7b0edSRobert Watson 	    mac.m_buflen);
403f7b951a8SRobert Watson 	NDFREE(&nd, 0);
4049eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
405eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
406f7b951a8SRobert Watson 
407f7b951a8SRobert Watson 	if (error == 0)
408f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
40995fab37eSRobert Watson 
41095fab37eSRobert Watson out:
411f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
412f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
413f7b951a8SRobert Watson 
41495fab37eSRobert Watson 	return (error);
41595fab37eSRobert Watson }
41695fab37eSRobert Watson 
41795fab37eSRobert Watson int
41895fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
41995fab37eSRobert Watson {
420eca8a663SRobert Watson 	struct label *intlabel;
421f7b951a8SRobert Watson 	struct pipe *pipe;
422b0323ea3SRobert Watson 	struct socket *so;
423f7b951a8SRobert Watson 	struct file *fp;
42495fab37eSRobert Watson 	struct mount *mp;
42595fab37eSRobert Watson 	struct vnode *vp;
426f7b951a8SRobert Watson 	struct mac mac;
427f7b951a8SRobert Watson 	char *buffer;
4289eea3d85SChristian S.J. Peron 	int error, vfslocked;
42995fab37eSRobert Watson 
430f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
431f7b951a8SRobert Watson 	if (error)
432f7b951a8SRobert Watson 		return (error);
433f7b951a8SRobert Watson 
434f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
435f7b951a8SRobert Watson 	if (error)
436f7b951a8SRobert Watson 		return (error);
437f7b951a8SRobert Watson 
438a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
439f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
440f7b951a8SRobert Watson 	if (error) {
441f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
442f7b951a8SRobert Watson 		return (error);
443f7b951a8SRobert Watson 	}
444f7b951a8SRobert Watson 
445d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
44695fab37eSRobert Watson 	if (error)
447f7b951a8SRobert Watson 		goto out;
44895fab37eSRobert Watson 
44995fab37eSRobert Watson 	switch (fp->f_type) {
45095fab37eSRobert Watson 	case DTYPE_FIFO:
45195fab37eSRobert Watson 	case DTYPE_VNODE:
4526356dba0SRobert Watson 		if (!(mac_labeled & MPC_OBJECT_VNODE))
4536356dba0SRobert Watson 			return (EINVAL);
454eca8a663SRobert Watson 		intlabel = mac_vnode_label_alloc();
45530d239bcSRobert Watson 		error = mac_vnode_internalize_label(intlabel, buffer);
456f7b951a8SRobert Watson 		if (error) {
457eca8a663SRobert Watson 			mac_vnode_label_free(intlabel);
458f7b951a8SRobert Watson 			break;
459f7b951a8SRobert Watson 		}
4603b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
4619eea3d85SChristian S.J. Peron 		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
46295fab37eSRobert Watson 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
463f7b951a8SRobert Watson 		if (error != 0) {
4649eea3d85SChristian S.J. Peron 			VFS_UNLOCK_GIANT(vfslocked);
465eca8a663SRobert Watson 			mac_vnode_label_free(intlabel);
46695fab37eSRobert Watson 			break;
467f7b951a8SRobert Watson 		}
468cb05b60aSAttilio Rao 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
469eca8a663SRobert Watson 		error = vn_setlabel(vp, intlabel, td->td_ucred);
47022db15c0SAttilio Rao 		VOP_UNLOCK(vp, 0);
47195fab37eSRobert Watson 		vn_finished_write(mp);
4729eea3d85SChristian S.J. Peron 		VFS_UNLOCK_GIANT(vfslocked);
473eca8a663SRobert Watson 		mac_vnode_label_free(intlabel);
47495fab37eSRobert Watson 		break;
475f7b951a8SRobert Watson 
47695fab37eSRobert Watson 	case DTYPE_PIPE:
4776356dba0SRobert Watson 		if (!(mac_labeled & MPC_OBJECT_PIPE))
4786356dba0SRobert Watson 			return (EINVAL);
479eca8a663SRobert Watson 		intlabel = mac_pipe_label_alloc();
48030d239bcSRobert Watson 		error = mac_pipe_internalize_label(intlabel, buffer);
481f7b951a8SRobert Watson 		if (error == 0) {
48248e3128bSMatthew Dillon 			pipe = fp->f_data;
4831aa37f53SRobert Watson 			PIPE_LOCK(pipe);
4844795b82cSRobert Watson 			error = mac_pipe_label_set(td->td_ucred,
4854795b82cSRobert Watson 			    pipe->pipe_pair, intlabel);
4861aa37f53SRobert Watson 			PIPE_UNLOCK(pipe);
487f7b951a8SRobert Watson 		}
488eca8a663SRobert Watson 		mac_pipe_label_free(intlabel);
48995fab37eSRobert Watson 		break;
490f7b951a8SRobert Watson 
491b0323ea3SRobert Watson 	case DTYPE_SOCKET:
4926356dba0SRobert Watson 		if (!(mac_labeled & MPC_OBJECT_SOCKET))
4936356dba0SRobert Watson 			return (EINVAL);
494b0323ea3SRobert Watson 		intlabel = mac_socket_label_alloc(M_WAITOK);
49530d239bcSRobert Watson 		error = mac_socket_internalize_label(intlabel, buffer);
496b0323ea3SRobert Watson 		if (error == 0) {
497b0323ea3SRobert Watson 			so = fp->f_data;
498b0323ea3SRobert Watson 			error = mac_socket_label_set(td->td_ucred, so,
499b0323ea3SRobert Watson 			    intlabel);
500b0323ea3SRobert Watson 		}
501b0323ea3SRobert Watson 		mac_socket_label_free(intlabel);
502b0323ea3SRobert Watson 		break;
503b0323ea3SRobert Watson 
50495fab37eSRobert Watson 	default:
50595fab37eSRobert Watson 		error = EINVAL;
50695fab37eSRobert Watson 	}
50795fab37eSRobert Watson 	fdrop(fp, td);
508f7b951a8SRobert Watson out:
509f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
51095fab37eSRobert Watson 	return (error);
51195fab37eSRobert Watson }
51295fab37eSRobert Watson 
51395fab37eSRobert Watson int
51495fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
51595fab37eSRobert Watson {
516eca8a663SRobert Watson 	struct label *intlabel;
517f7b951a8SRobert Watson 	struct nameidata nd;
51895fab37eSRobert Watson 	struct mount *mp;
519f7b951a8SRobert Watson 	struct mac mac;
520f7b951a8SRobert Watson 	char *buffer;
5219eea3d85SChristian S.J. Peron 	int vfslocked, error;
52295fab37eSRobert Watson 
5236356dba0SRobert Watson 	if (!(mac_labeled & MPC_OBJECT_VNODE))
5246356dba0SRobert Watson 		return (EINVAL);
5256356dba0SRobert Watson 
526f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
52795fab37eSRobert Watson 	if (error)
528f7b951a8SRobert Watson 		return (error);
52995fab37eSRobert Watson 
530f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
53195fab37eSRobert Watson 	if (error)
532f7b951a8SRobert Watson 		return (error);
53395fab37eSRobert Watson 
534a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
535f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
536f7b951a8SRobert Watson 	if (error) {
537f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
53895fab37eSRobert Watson 		return (error);
53995fab37eSRobert Watson 	}
54095fab37eSRobert Watson 
541eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
54230d239bcSRobert Watson 	error = mac_vnode_internalize_label(intlabel, buffer);
543f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
544eca8a663SRobert Watson 	if (error)
545eca8a663SRobert Watson 		goto out;
546f7b951a8SRobert Watson 
5479eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
5489eea3d85SChristian S.J. Peron 	    uap->path_p, td);
549f7b951a8SRobert Watson 	error = namei(&nd);
5509eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
551f7b951a8SRobert Watson 	if (error == 0) {
552f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
553d50ef66dSTor Egge 		if (error == 0) {
554eca8a663SRobert Watson 			error = vn_setlabel(nd.ni_vp, intlabel,
555f7b951a8SRobert Watson 			    td->td_ucred);
556f7b951a8SRobert Watson 			vn_finished_write(mp);
557f7b951a8SRobert Watson 		}
558d50ef66dSTor Egge 	}
559f7b951a8SRobert Watson 
560f7b951a8SRobert Watson 	NDFREE(&nd, 0);
5619eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
562eca8a663SRobert Watson out:
563eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
564f7b951a8SRobert Watson 	return (error);
565f7b951a8SRobert Watson }
566f7b951a8SRobert Watson 
567f7b951a8SRobert Watson int
568f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
569f7b951a8SRobert Watson {
570eca8a663SRobert Watson 	struct label *intlabel;
571f7b951a8SRobert Watson 	struct nameidata nd;
572f7b951a8SRobert Watson 	struct mount *mp;
573f7b951a8SRobert Watson 	struct mac mac;
574f7b951a8SRobert Watson 	char *buffer;
5759eea3d85SChristian S.J. Peron 	int vfslocked, error;
576f7b951a8SRobert Watson 
5776356dba0SRobert Watson 	if (!(mac_labeled & MPC_OBJECT_VNODE))
5786356dba0SRobert Watson 		return (EINVAL);
5796356dba0SRobert Watson 
580f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
581f7b951a8SRobert Watson 	if (error)
582f7b951a8SRobert Watson 		return (error);
583f7b951a8SRobert Watson 
584f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
585f7b951a8SRobert Watson 	if (error)
586f7b951a8SRobert Watson 		return (error);
587f7b951a8SRobert Watson 
588a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
589f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
590f7b951a8SRobert Watson 	if (error) {
591f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
592f7b951a8SRobert Watson 		return (error);
593f7b951a8SRobert Watson 	}
594f7b951a8SRobert Watson 
595eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
59630d239bcSRobert Watson 	error = mac_vnode_internalize_label(intlabel, buffer);
597f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
598eca8a663SRobert Watson 	if (error)
599eca8a663SRobert Watson 		goto out;
600f7b951a8SRobert Watson 
6019eea3d85SChristian S.J. Peron 	NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
6029eea3d85SChristian S.J. Peron 	    uap->path_p, td);
603f7b951a8SRobert Watson 	error = namei(&nd);
6049eea3d85SChristian S.J. Peron 	vfslocked = NDHASGIANT(&nd);
605f7b951a8SRobert Watson 	if (error == 0) {
606f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
607d50ef66dSTor Egge 		if (error == 0) {
608eca8a663SRobert Watson 			error = vn_setlabel(nd.ni_vp, intlabel,
609f7b951a8SRobert Watson 			    td->td_ucred);
610f7b951a8SRobert Watson 			vn_finished_write(mp);
611f7b951a8SRobert Watson 		}
612d50ef66dSTor Egge 	}
613f7b951a8SRobert Watson 
614f7b951a8SRobert Watson 	NDFREE(&nd, 0);
6159eea3d85SChristian S.J. Peron 	VFS_UNLOCK_GIANT(vfslocked);
616eca8a663SRobert Watson out:
617eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
618f7b951a8SRobert Watson 	return (error);
619f7b951a8SRobert Watson }
620f7b951a8SRobert Watson 
62127f2eac7SRobert Watson int
62227f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
62327f2eac7SRobert Watson {
62427f2eac7SRobert Watson 	struct mac_policy_conf *mpc;
62527f2eac7SRobert Watson 	char target[MAC_MAX_POLICY_NAME];
62640202729SRobert Watson 	int error;
62727f2eac7SRobert Watson 
628d1e405c5SAlfred Perlstein 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
62927f2eac7SRobert Watson 	if (error)
63027f2eac7SRobert Watson 		return (error);
63127f2eac7SRobert Watson 
63227f2eac7SRobert Watson 	error = ENOSYS;
633a6a65b05SRobert Watson 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
63427f2eac7SRobert Watson 		if (strcmp(mpc->mpc_name, target) == 0 &&
63527f2eac7SRobert Watson 		    mpc->mpc_ops->mpo_syscall != NULL) {
63627f2eac7SRobert Watson 			error = mpc->mpc_ops->mpo_syscall(td,
637d1e405c5SAlfred Perlstein 			    uap->call, uap->arg);
63827f2eac7SRobert Watson 			goto out;
63927f2eac7SRobert Watson 		}
64027f2eac7SRobert Watson 	}
64127f2eac7SRobert Watson 
64240202729SRobert Watson 	if (!LIST_EMPTY(&mac_policy_list)) {
64340202729SRobert Watson 		mac_policy_slock_sleep();
64441a17fe3SRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
64541a17fe3SRobert Watson 			if (strcmp(mpc->mpc_name, target) == 0 &&
64641a17fe3SRobert Watson 			    mpc->mpc_ops->mpo_syscall != NULL) {
64741a17fe3SRobert Watson 				error = mpc->mpc_ops->mpo_syscall(td,
64841a17fe3SRobert Watson 				    uap->call, uap->arg);
64941a17fe3SRobert Watson 				break;
65041a17fe3SRobert Watson 			}
65141a17fe3SRobert Watson 		}
65240202729SRobert Watson 		mac_policy_sunlock_sleep();
65341a17fe3SRobert Watson 	}
65427f2eac7SRobert Watson out:
65527f2eac7SRobert Watson 	return (error);
65627f2eac7SRobert Watson }
65727f2eac7SRobert Watson 
65895fab37eSRobert Watson #else /* !MAC */
6597bc82500SRobert Watson 
6607bc82500SRobert Watson int
661f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
662f7b951a8SRobert Watson {
663f7b951a8SRobert Watson 
664f7b951a8SRobert Watson 	return (ENOSYS);
665f7b951a8SRobert Watson }
666f7b951a8SRobert Watson 
667f7b951a8SRobert Watson int
6687bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
6697bc82500SRobert Watson {
6707bc82500SRobert Watson 
6717bc82500SRobert Watson 	return (ENOSYS);
6727bc82500SRobert Watson }
6737bc82500SRobert Watson 
6747bc82500SRobert Watson int
6757bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
6767bc82500SRobert Watson {
6777bc82500SRobert Watson 
6787bc82500SRobert Watson 	return (ENOSYS);
6797bc82500SRobert Watson }
6807bc82500SRobert Watson 
6817bc82500SRobert Watson int
6827bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
6837bc82500SRobert Watson {
6847bc82500SRobert Watson 
6857bc82500SRobert Watson 	return (ENOSYS);
6867bc82500SRobert Watson }
6877bc82500SRobert Watson 
6887bc82500SRobert Watson int
6897bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
6907bc82500SRobert Watson {
6917bc82500SRobert Watson 
6927bc82500SRobert Watson 	return (ENOSYS);
6937bc82500SRobert Watson }
6947bc82500SRobert Watson 
6957bc82500SRobert Watson int
696f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
697f7b951a8SRobert Watson {
698f7b951a8SRobert Watson 
699f7b951a8SRobert Watson 	return (ENOSYS);
700f7b951a8SRobert Watson }
701f7b951a8SRobert Watson 
702f7b951a8SRobert Watson int
7037bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
7047bc82500SRobert Watson {
7057bc82500SRobert Watson 
7067bc82500SRobert Watson 	return (ENOSYS);
7077bc82500SRobert Watson }
7087bc82500SRobert Watson 
7097bc82500SRobert Watson int
7107bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
7117bc82500SRobert Watson {
7127bc82500SRobert Watson 
7137bc82500SRobert Watson 	return (ENOSYS);
7147bc82500SRobert Watson }
71595fab37eSRobert Watson 
71627f2eac7SRobert Watson int
717f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
718f7b951a8SRobert Watson {
719f7b951a8SRobert Watson 
720f7b951a8SRobert Watson 	return (ENOSYS);
721f7b951a8SRobert Watson }
722f7b951a8SRobert Watson 
723f7b951a8SRobert Watson int
72427f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
72527f2eac7SRobert Watson {
72627f2eac7SRobert Watson 
72727f2eac7SRobert Watson 	return (ENOSYS);
72827f2eac7SRobert Watson }
72927f2eac7SRobert Watson 
73019b78822SRobert Watson #endif /* !MAC */
731