1a9643ea8Slogwang /*-
2a9643ea8Slogwang * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson
3a9643ea8Slogwang * Copyright (c) 2001 Ilmar S. Habibulin
4a9643ea8Slogwang * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5a9643ea8Slogwang * Copyright (c) 2005-2006 SPARTA, Inc.
6a9643ea8Slogwang * Copyright (c) 2008 Apple Inc.
7a9643ea8Slogwang * All rights reserved.
8a9643ea8Slogwang *
9a9643ea8Slogwang * This software was developed by Robert Watson and Ilmar Habibulin for the
10a9643ea8Slogwang * TrustedBSD Project.
11a9643ea8Slogwang *
12a9643ea8Slogwang * This software was developed for the FreeBSD Project in part by Network
13a9643ea8Slogwang * Associates Laboratories, the Security Research Division of Network
14a9643ea8Slogwang * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
15a9643ea8Slogwang * as part of the DARPA CHATS research program.
16a9643ea8Slogwang *
17a9643ea8Slogwang * This software was enhanced by SPARTA ISSO under SPAWAR contract
18a9643ea8Slogwang * N66001-04-C-6019 ("SEFOS").
19a9643ea8Slogwang *
20a9643ea8Slogwang * This software was developed at the University of Cambridge Computer
21a9643ea8Slogwang * Laboratory with support from a grant from Google, Inc.
22a9643ea8Slogwang *
23a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without
24a9643ea8Slogwang * modification, are permitted provided that the following conditions
25a9643ea8Slogwang * are met:
26a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright
27a9643ea8Slogwang * notice, this list of conditions and the following disclaimer.
28a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright
29a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the
30a9643ea8Slogwang * documentation and/or other materials provided with the distribution.
31a9643ea8Slogwang *
32a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
33a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
36a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42a9643ea8Slogwang * SUCH DAMAGE.
43a9643ea8Slogwang */
44a9643ea8Slogwang
45a9643ea8Slogwang #include <sys/cdefs.h>
46a9643ea8Slogwang __FBSDID("$FreeBSD$");
47a9643ea8Slogwang
48a9643ea8Slogwang #include "opt_mac.h"
49a9643ea8Slogwang
50a9643ea8Slogwang #include <sys/param.h>
51a9643ea8Slogwang #include <sys/capsicum.h>
52a9643ea8Slogwang #include <sys/fcntl.h>
53a9643ea8Slogwang #include <sys/kernel.h>
54a9643ea8Slogwang #include <sys/lock.h>
55a9643ea8Slogwang #include <sys/malloc.h>
56a9643ea8Slogwang #include <sys/mutex.h>
57a9643ea8Slogwang #include <sys/mac.h>
58a9643ea8Slogwang #include <sys/proc.h>
59a9643ea8Slogwang #include <sys/systm.h>
60a9643ea8Slogwang #include <sys/sysctl.h>
61a9643ea8Slogwang #include <sys/sysproto.h>
62a9643ea8Slogwang #include <sys/sysent.h>
63a9643ea8Slogwang #include <sys/vnode.h>
64a9643ea8Slogwang #include <sys/mount.h>
65a9643ea8Slogwang #include <sys/file.h>
66a9643ea8Slogwang #include <sys/namei.h>
67a9643ea8Slogwang #include <sys/socket.h>
68a9643ea8Slogwang #include <sys/pipe.h>
69a9643ea8Slogwang #include <sys/socketvar.h>
70a9643ea8Slogwang
71a9643ea8Slogwang #include <security/mac/mac_framework.h>
72a9643ea8Slogwang #include <security/mac/mac_internal.h>
73a9643ea8Slogwang #include <security/mac/mac_policy.h>
74a9643ea8Slogwang
75a9643ea8Slogwang #ifdef MAC
76a9643ea8Slogwang
77a9643ea8Slogwang FEATURE(security_mac, "Mandatory Access Control Framework support");
78a9643ea8Slogwang
79*22ce4affSfengbojiang static int kern___mac_get_path(struct thread *td, const char *path_p,
80*22ce4affSfengbojiang struct mac *mac_p, int follow);
81*22ce4affSfengbojiang static int kern___mac_set_path(struct thread *td, const char *path_p,
82*22ce4affSfengbojiang struct mac *mac_p, int follow);
83*22ce4affSfengbojiang
84a9643ea8Slogwang int
sys___mac_get_pid(struct thread * td,struct __mac_get_pid_args * uap)85a9643ea8Slogwang sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
86a9643ea8Slogwang {
87a9643ea8Slogwang char *elements, *buffer;
88a9643ea8Slogwang struct mac mac;
89a9643ea8Slogwang struct proc *tproc;
90a9643ea8Slogwang struct ucred *tcred;
91a9643ea8Slogwang int error;
92a9643ea8Slogwang
93a9643ea8Slogwang error = copyin(uap->mac_p, &mac, sizeof(mac));
94a9643ea8Slogwang if (error)
95a9643ea8Slogwang return (error);
96a9643ea8Slogwang
97a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
98a9643ea8Slogwang if (error)
99a9643ea8Slogwang return (error);
100a9643ea8Slogwang
101a9643ea8Slogwang tproc = pfind(uap->pid);
102a9643ea8Slogwang if (tproc == NULL)
103a9643ea8Slogwang return (ESRCH);
104a9643ea8Slogwang
105a9643ea8Slogwang tcred = NULL; /* Satisfy gcc. */
106a9643ea8Slogwang error = p_cansee(td, tproc);
107a9643ea8Slogwang if (error == 0)
108a9643ea8Slogwang tcred = crhold(tproc->p_ucred);
109a9643ea8Slogwang PROC_UNLOCK(tproc);
110a9643ea8Slogwang if (error)
111a9643ea8Slogwang return (error);
112a9643ea8Slogwang
113a9643ea8Slogwang elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
114a9643ea8Slogwang error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
115a9643ea8Slogwang if (error) {
116a9643ea8Slogwang free(elements, M_MACTEMP);
117a9643ea8Slogwang crfree(tcred);
118a9643ea8Slogwang return (error);
119a9643ea8Slogwang }
120a9643ea8Slogwang
121a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
122a9643ea8Slogwang error = mac_cred_externalize_label(tcred->cr_label, elements,
123a9643ea8Slogwang buffer, mac.m_buflen);
124a9643ea8Slogwang if (error == 0)
125a9643ea8Slogwang error = copyout(buffer, mac.m_string, strlen(buffer)+1);
126a9643ea8Slogwang
127a9643ea8Slogwang free(buffer, M_MACTEMP);
128a9643ea8Slogwang free(elements, M_MACTEMP);
129a9643ea8Slogwang crfree(tcred);
130a9643ea8Slogwang return (error);
131a9643ea8Slogwang }
132a9643ea8Slogwang
133a9643ea8Slogwang int
sys___mac_get_proc(struct thread * td,struct __mac_get_proc_args * uap)134a9643ea8Slogwang sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
135a9643ea8Slogwang {
136a9643ea8Slogwang char *elements, *buffer;
137a9643ea8Slogwang struct mac mac;
138a9643ea8Slogwang int error;
139a9643ea8Slogwang
140a9643ea8Slogwang error = copyin(uap->mac_p, &mac, sizeof(mac));
141a9643ea8Slogwang if (error)
142a9643ea8Slogwang return (error);
143a9643ea8Slogwang
144a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
145a9643ea8Slogwang if (error)
146a9643ea8Slogwang return (error);
147a9643ea8Slogwang
148a9643ea8Slogwang elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
149a9643ea8Slogwang error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
150a9643ea8Slogwang if (error) {
151a9643ea8Slogwang free(elements, M_MACTEMP);
152a9643ea8Slogwang return (error);
153a9643ea8Slogwang }
154a9643ea8Slogwang
155a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
156a9643ea8Slogwang error = mac_cred_externalize_label(td->td_ucred->cr_label,
157a9643ea8Slogwang elements, buffer, mac.m_buflen);
158a9643ea8Slogwang if (error == 0)
159a9643ea8Slogwang error = copyout(buffer, mac.m_string, strlen(buffer)+1);
160a9643ea8Slogwang
161a9643ea8Slogwang free(buffer, M_MACTEMP);
162a9643ea8Slogwang free(elements, M_MACTEMP);
163a9643ea8Slogwang return (error);
164a9643ea8Slogwang }
165a9643ea8Slogwang
166a9643ea8Slogwang int
sys___mac_set_proc(struct thread * td,struct __mac_set_proc_args * uap)167a9643ea8Slogwang sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
168a9643ea8Slogwang {
169a9643ea8Slogwang struct ucred *newcred, *oldcred;
170a9643ea8Slogwang struct label *intlabel;
171a9643ea8Slogwang struct proc *p;
172a9643ea8Slogwang struct mac mac;
173a9643ea8Slogwang char *buffer;
174a9643ea8Slogwang int error;
175a9643ea8Slogwang
176a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_CRED))
177a9643ea8Slogwang return (EINVAL);
178a9643ea8Slogwang
179a9643ea8Slogwang error = copyin(uap->mac_p, &mac, sizeof(mac));
180a9643ea8Slogwang if (error)
181a9643ea8Slogwang return (error);
182a9643ea8Slogwang
183a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
184a9643ea8Slogwang if (error)
185a9643ea8Slogwang return (error);
186a9643ea8Slogwang
187a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
188a9643ea8Slogwang error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
189a9643ea8Slogwang if (error) {
190a9643ea8Slogwang free(buffer, M_MACTEMP);
191a9643ea8Slogwang return (error);
192a9643ea8Slogwang }
193a9643ea8Slogwang
194a9643ea8Slogwang intlabel = mac_cred_label_alloc();
195a9643ea8Slogwang error = mac_cred_internalize_label(intlabel, buffer);
196a9643ea8Slogwang free(buffer, M_MACTEMP);
197a9643ea8Slogwang if (error)
198a9643ea8Slogwang goto out;
199a9643ea8Slogwang
200a9643ea8Slogwang newcred = crget();
201a9643ea8Slogwang
202a9643ea8Slogwang p = td->td_proc;
203a9643ea8Slogwang PROC_LOCK(p);
204a9643ea8Slogwang oldcred = p->p_ucred;
205a9643ea8Slogwang
206a9643ea8Slogwang error = mac_cred_check_relabel(oldcred, intlabel);
207a9643ea8Slogwang if (error) {
208a9643ea8Slogwang PROC_UNLOCK(p);
209a9643ea8Slogwang crfree(newcred);
210a9643ea8Slogwang goto out;
211a9643ea8Slogwang }
212a9643ea8Slogwang
213a9643ea8Slogwang setsugid(p);
214a9643ea8Slogwang crcopy(newcred, oldcred);
215a9643ea8Slogwang mac_cred_relabel(newcred, intlabel);
216a9643ea8Slogwang proc_set_cred(p, newcred);
217a9643ea8Slogwang
218a9643ea8Slogwang PROC_UNLOCK(p);
219a9643ea8Slogwang crfree(oldcred);
220a9643ea8Slogwang mac_proc_vm_revoke(td);
221a9643ea8Slogwang
222a9643ea8Slogwang out:
223a9643ea8Slogwang mac_cred_label_free(intlabel);
224a9643ea8Slogwang return (error);
225a9643ea8Slogwang }
226a9643ea8Slogwang
227a9643ea8Slogwang int
sys___mac_get_fd(struct thread * td,struct __mac_get_fd_args * uap)228a9643ea8Slogwang sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
229a9643ea8Slogwang {
230a9643ea8Slogwang char *elements, *buffer;
231a9643ea8Slogwang struct label *intlabel;
232a9643ea8Slogwang struct file *fp;
233a9643ea8Slogwang struct mac mac;
234a9643ea8Slogwang struct vnode *vp;
235a9643ea8Slogwang struct pipe *pipe;
236a9643ea8Slogwang struct socket *so;
237a9643ea8Slogwang cap_rights_t rights;
238a9643ea8Slogwang int error;
239a9643ea8Slogwang
240a9643ea8Slogwang error = copyin(uap->mac_p, &mac, sizeof(mac));
241a9643ea8Slogwang if (error)
242a9643ea8Slogwang return (error);
243a9643ea8Slogwang
244a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
245a9643ea8Slogwang if (error)
246a9643ea8Slogwang return (error);
247a9643ea8Slogwang
248a9643ea8Slogwang elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
249a9643ea8Slogwang error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
250a9643ea8Slogwang if (error) {
251a9643ea8Slogwang free(elements, M_MACTEMP);
252a9643ea8Slogwang return (error);
253a9643ea8Slogwang }
254a9643ea8Slogwang
255a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
256*22ce4affSfengbojiang error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_GET),
257*22ce4affSfengbojiang &fp);
258a9643ea8Slogwang if (error)
259a9643ea8Slogwang goto out;
260a9643ea8Slogwang
261a9643ea8Slogwang switch (fp->f_type) {
262a9643ea8Slogwang case DTYPE_FIFO:
263a9643ea8Slogwang case DTYPE_VNODE:
264a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_VNODE)) {
265a9643ea8Slogwang error = EINVAL;
266a9643ea8Slogwang goto out_fdrop;
267a9643ea8Slogwang }
268a9643ea8Slogwang vp = fp->f_vnode;
269a9643ea8Slogwang intlabel = mac_vnode_label_alloc();
270a9643ea8Slogwang vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
271a9643ea8Slogwang mac_vnode_copy_label(vp->v_label, intlabel);
272*22ce4affSfengbojiang VOP_UNLOCK(vp);
273a9643ea8Slogwang error = mac_vnode_externalize_label(intlabel, elements,
274a9643ea8Slogwang buffer, mac.m_buflen);
275a9643ea8Slogwang mac_vnode_label_free(intlabel);
276a9643ea8Slogwang break;
277a9643ea8Slogwang
278a9643ea8Slogwang case DTYPE_PIPE:
279a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_PIPE)) {
280a9643ea8Slogwang error = EINVAL;
281a9643ea8Slogwang goto out_fdrop;
282a9643ea8Slogwang }
283a9643ea8Slogwang pipe = fp->f_data;
284a9643ea8Slogwang intlabel = mac_pipe_label_alloc();
285a9643ea8Slogwang PIPE_LOCK(pipe);
286a9643ea8Slogwang mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel);
287a9643ea8Slogwang PIPE_UNLOCK(pipe);
288a9643ea8Slogwang error = mac_pipe_externalize_label(intlabel, elements,
289a9643ea8Slogwang buffer, mac.m_buflen);
290a9643ea8Slogwang mac_pipe_label_free(intlabel);
291a9643ea8Slogwang break;
292a9643ea8Slogwang
293a9643ea8Slogwang case DTYPE_SOCKET:
294a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_SOCKET)) {
295a9643ea8Slogwang error = EINVAL;
296a9643ea8Slogwang goto out_fdrop;
297a9643ea8Slogwang }
298a9643ea8Slogwang so = fp->f_data;
299a9643ea8Slogwang intlabel = mac_socket_label_alloc(M_WAITOK);
300a9643ea8Slogwang SOCK_LOCK(so);
301a9643ea8Slogwang mac_socket_copy_label(so->so_label, intlabel);
302a9643ea8Slogwang SOCK_UNLOCK(so);
303a9643ea8Slogwang error = mac_socket_externalize_label(intlabel, elements,
304a9643ea8Slogwang buffer, mac.m_buflen);
305a9643ea8Slogwang mac_socket_label_free(intlabel);
306a9643ea8Slogwang break;
307a9643ea8Slogwang
308a9643ea8Slogwang default:
309a9643ea8Slogwang error = EINVAL;
310a9643ea8Slogwang }
311a9643ea8Slogwang if (error == 0)
312a9643ea8Slogwang error = copyout(buffer, mac.m_string, strlen(buffer)+1);
313a9643ea8Slogwang out_fdrop:
314a9643ea8Slogwang fdrop(fp, td);
315a9643ea8Slogwang out:
316a9643ea8Slogwang free(buffer, M_MACTEMP);
317a9643ea8Slogwang free(elements, M_MACTEMP);
318a9643ea8Slogwang return (error);
319a9643ea8Slogwang }
320a9643ea8Slogwang
321a9643ea8Slogwang int
sys___mac_get_file(struct thread * td,struct __mac_get_file_args * uap)322a9643ea8Slogwang sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
323a9643ea8Slogwang {
324a9643ea8Slogwang
325*22ce4affSfengbojiang return (kern___mac_get_path(td, uap->path_p, uap->mac_p, FOLLOW));
326a9643ea8Slogwang }
327a9643ea8Slogwang
328a9643ea8Slogwang int
sys___mac_get_link(struct thread * td,struct __mac_get_link_args * uap)329a9643ea8Slogwang sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
330a9643ea8Slogwang {
331*22ce4affSfengbojiang
332*22ce4affSfengbojiang return (kern___mac_get_path(td, uap->path_p, uap->mac_p, NOFOLLOW));
333*22ce4affSfengbojiang }
334*22ce4affSfengbojiang
335*22ce4affSfengbojiang static int
kern___mac_get_path(struct thread * td,const char * path_p,struct mac * mac_p,int follow)336*22ce4affSfengbojiang kern___mac_get_path(struct thread *td, const char *path_p, struct mac *mac_p,
337*22ce4affSfengbojiang int follow)
338*22ce4affSfengbojiang {
339a9643ea8Slogwang char *elements, *buffer;
340a9643ea8Slogwang struct nameidata nd;
341a9643ea8Slogwang struct label *intlabel;
342a9643ea8Slogwang struct mac mac;
343a9643ea8Slogwang int error;
344a9643ea8Slogwang
345a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_VNODE))
346a9643ea8Slogwang return (EINVAL);
347a9643ea8Slogwang
348*22ce4affSfengbojiang error = copyin(mac_p, &mac, sizeof(mac));
349a9643ea8Slogwang if (error)
350a9643ea8Slogwang return (error);
351a9643ea8Slogwang
352a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
353a9643ea8Slogwang if (error)
354a9643ea8Slogwang return (error);
355a9643ea8Slogwang
356a9643ea8Slogwang elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
357a9643ea8Slogwang error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
358a9643ea8Slogwang if (error) {
359a9643ea8Slogwang free(elements, M_MACTEMP);
360a9643ea8Slogwang return (error);
361a9643ea8Slogwang }
362a9643ea8Slogwang
363a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
364*22ce4affSfengbojiang NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p, td);
365a9643ea8Slogwang error = namei(&nd);
366a9643ea8Slogwang if (error)
367a9643ea8Slogwang goto out;
368a9643ea8Slogwang
369a9643ea8Slogwang intlabel = mac_vnode_label_alloc();
370a9643ea8Slogwang mac_vnode_copy_label(nd.ni_vp->v_label, intlabel);
371a9643ea8Slogwang error = mac_vnode_externalize_label(intlabel, elements, buffer,
372a9643ea8Slogwang mac.m_buflen);
373a9643ea8Slogwang NDFREE(&nd, 0);
374a9643ea8Slogwang mac_vnode_label_free(intlabel);
375a9643ea8Slogwang
376a9643ea8Slogwang if (error == 0)
377a9643ea8Slogwang error = copyout(buffer, mac.m_string, strlen(buffer)+1);
378a9643ea8Slogwang
379a9643ea8Slogwang out:
380a9643ea8Slogwang free(buffer, M_MACTEMP);
381a9643ea8Slogwang free(elements, M_MACTEMP);
382a9643ea8Slogwang
383a9643ea8Slogwang return (error);
384a9643ea8Slogwang }
385a9643ea8Slogwang
386a9643ea8Slogwang int
sys___mac_set_fd(struct thread * td,struct __mac_set_fd_args * uap)387a9643ea8Slogwang sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
388a9643ea8Slogwang {
389a9643ea8Slogwang struct label *intlabel;
390a9643ea8Slogwang struct pipe *pipe;
391a9643ea8Slogwang struct socket *so;
392a9643ea8Slogwang struct file *fp;
393a9643ea8Slogwang struct mount *mp;
394a9643ea8Slogwang struct vnode *vp;
395a9643ea8Slogwang struct mac mac;
396a9643ea8Slogwang cap_rights_t rights;
397a9643ea8Slogwang char *buffer;
398a9643ea8Slogwang int error;
399a9643ea8Slogwang
400a9643ea8Slogwang error = copyin(uap->mac_p, &mac, sizeof(mac));
401a9643ea8Slogwang if (error)
402a9643ea8Slogwang return (error);
403a9643ea8Slogwang
404a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
405a9643ea8Slogwang if (error)
406a9643ea8Slogwang return (error);
407a9643ea8Slogwang
408a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
409a9643ea8Slogwang error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
410a9643ea8Slogwang if (error) {
411a9643ea8Slogwang free(buffer, M_MACTEMP);
412a9643ea8Slogwang return (error);
413a9643ea8Slogwang }
414a9643ea8Slogwang
415*22ce4affSfengbojiang error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_SET),
416*22ce4affSfengbojiang &fp);
417a9643ea8Slogwang if (error)
418a9643ea8Slogwang goto out;
419a9643ea8Slogwang
420a9643ea8Slogwang switch (fp->f_type) {
421a9643ea8Slogwang case DTYPE_FIFO:
422a9643ea8Slogwang case DTYPE_VNODE:
423a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_VNODE)) {
424a9643ea8Slogwang error = EINVAL;
425a9643ea8Slogwang goto out_fdrop;
426a9643ea8Slogwang }
427a9643ea8Slogwang intlabel = mac_vnode_label_alloc();
428a9643ea8Slogwang error = mac_vnode_internalize_label(intlabel, buffer);
429a9643ea8Slogwang if (error) {
430a9643ea8Slogwang mac_vnode_label_free(intlabel);
431a9643ea8Slogwang break;
432a9643ea8Slogwang }
433a9643ea8Slogwang vp = fp->f_vnode;
434a9643ea8Slogwang error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
435a9643ea8Slogwang if (error != 0) {
436a9643ea8Slogwang mac_vnode_label_free(intlabel);
437a9643ea8Slogwang break;
438a9643ea8Slogwang }
439a9643ea8Slogwang vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
440a9643ea8Slogwang error = vn_setlabel(vp, intlabel, td->td_ucred);
441*22ce4affSfengbojiang VOP_UNLOCK(vp);
442a9643ea8Slogwang vn_finished_write(mp);
443a9643ea8Slogwang mac_vnode_label_free(intlabel);
444a9643ea8Slogwang break;
445a9643ea8Slogwang
446a9643ea8Slogwang case DTYPE_PIPE:
447a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_PIPE)) {
448a9643ea8Slogwang error = EINVAL;
449a9643ea8Slogwang goto out_fdrop;
450a9643ea8Slogwang }
451a9643ea8Slogwang intlabel = mac_pipe_label_alloc();
452a9643ea8Slogwang error = mac_pipe_internalize_label(intlabel, buffer);
453a9643ea8Slogwang if (error == 0) {
454a9643ea8Slogwang pipe = fp->f_data;
455a9643ea8Slogwang PIPE_LOCK(pipe);
456a9643ea8Slogwang error = mac_pipe_label_set(td->td_ucred,
457a9643ea8Slogwang pipe->pipe_pair, intlabel);
458a9643ea8Slogwang PIPE_UNLOCK(pipe);
459a9643ea8Slogwang }
460a9643ea8Slogwang mac_pipe_label_free(intlabel);
461a9643ea8Slogwang break;
462a9643ea8Slogwang
463a9643ea8Slogwang case DTYPE_SOCKET:
464a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_SOCKET)) {
465a9643ea8Slogwang error = EINVAL;
466a9643ea8Slogwang goto out_fdrop;
467a9643ea8Slogwang }
468a9643ea8Slogwang intlabel = mac_socket_label_alloc(M_WAITOK);
469a9643ea8Slogwang error = mac_socket_internalize_label(intlabel, buffer);
470a9643ea8Slogwang if (error == 0) {
471a9643ea8Slogwang so = fp->f_data;
472a9643ea8Slogwang error = mac_socket_label_set(td->td_ucred, so,
473a9643ea8Slogwang intlabel);
474a9643ea8Slogwang }
475a9643ea8Slogwang mac_socket_label_free(intlabel);
476a9643ea8Slogwang break;
477a9643ea8Slogwang
478a9643ea8Slogwang default:
479a9643ea8Slogwang error = EINVAL;
480a9643ea8Slogwang }
481a9643ea8Slogwang out_fdrop:
482a9643ea8Slogwang fdrop(fp, td);
483a9643ea8Slogwang out:
484a9643ea8Slogwang free(buffer, M_MACTEMP);
485a9643ea8Slogwang return (error);
486a9643ea8Slogwang }
487a9643ea8Slogwang
488a9643ea8Slogwang int
sys___mac_set_file(struct thread * td,struct __mac_set_file_args * uap)489a9643ea8Slogwang sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
490a9643ea8Slogwang {
491a9643ea8Slogwang
492*22ce4affSfengbojiang return (kern___mac_set_path(td, uap->path_p, uap->mac_p, FOLLOW));
493a9643ea8Slogwang }
494a9643ea8Slogwang
495a9643ea8Slogwang int
sys___mac_set_link(struct thread * td,struct __mac_set_link_args * uap)496a9643ea8Slogwang sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
497a9643ea8Slogwang {
498*22ce4affSfengbojiang
499*22ce4affSfengbojiang return (kern___mac_set_path(td, uap->path_p, uap->mac_p, NOFOLLOW));
500*22ce4affSfengbojiang }
501*22ce4affSfengbojiang
502*22ce4affSfengbojiang static int
kern___mac_set_path(struct thread * td,const char * path_p,struct mac * mac_p,int follow)503*22ce4affSfengbojiang kern___mac_set_path(struct thread *td, const char *path_p, struct mac *mac_p,
504*22ce4affSfengbojiang int follow)
505*22ce4affSfengbojiang {
506a9643ea8Slogwang struct label *intlabel;
507a9643ea8Slogwang struct nameidata nd;
508a9643ea8Slogwang struct mount *mp;
509a9643ea8Slogwang struct mac mac;
510a9643ea8Slogwang char *buffer;
511a9643ea8Slogwang int error;
512a9643ea8Slogwang
513a9643ea8Slogwang if (!(mac_labeled & MPC_OBJECT_VNODE))
514a9643ea8Slogwang return (EINVAL);
515a9643ea8Slogwang
516*22ce4affSfengbojiang error = copyin(mac_p, &mac, sizeof(mac));
517a9643ea8Slogwang if (error)
518a9643ea8Slogwang return (error);
519a9643ea8Slogwang
520a9643ea8Slogwang error = mac_check_structmac_consistent(&mac);
521a9643ea8Slogwang if (error)
522a9643ea8Slogwang return (error);
523a9643ea8Slogwang
524a9643ea8Slogwang buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
525a9643ea8Slogwang error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
526a9643ea8Slogwang if (error) {
527a9643ea8Slogwang free(buffer, M_MACTEMP);
528a9643ea8Slogwang return (error);
529a9643ea8Slogwang }
530a9643ea8Slogwang
531a9643ea8Slogwang intlabel = mac_vnode_label_alloc();
532a9643ea8Slogwang error = mac_vnode_internalize_label(intlabel, buffer);
533a9643ea8Slogwang free(buffer, M_MACTEMP);
534a9643ea8Slogwang if (error)
535a9643ea8Slogwang goto out;
536a9643ea8Slogwang
537*22ce4affSfengbojiang NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p, td);
538a9643ea8Slogwang error = namei(&nd);
539a9643ea8Slogwang if (error == 0) {
540a9643ea8Slogwang error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
541a9643ea8Slogwang if (error == 0) {
542a9643ea8Slogwang error = vn_setlabel(nd.ni_vp, intlabel,
543a9643ea8Slogwang td->td_ucred);
544a9643ea8Slogwang vn_finished_write(mp);
545a9643ea8Slogwang }
546a9643ea8Slogwang }
547a9643ea8Slogwang
548a9643ea8Slogwang NDFREE(&nd, 0);
549a9643ea8Slogwang out:
550a9643ea8Slogwang mac_vnode_label_free(intlabel);
551a9643ea8Slogwang return (error);
552a9643ea8Slogwang }
553a9643ea8Slogwang
554a9643ea8Slogwang int
sys_mac_syscall(struct thread * td,struct mac_syscall_args * uap)555a9643ea8Slogwang sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap)
556a9643ea8Slogwang {
557a9643ea8Slogwang struct mac_policy_conf *mpc;
558a9643ea8Slogwang char target[MAC_MAX_POLICY_NAME];
559a9643ea8Slogwang int error;
560a9643ea8Slogwang
561a9643ea8Slogwang error = copyinstr(uap->policy, target, sizeof(target), NULL);
562a9643ea8Slogwang if (error)
563a9643ea8Slogwang return (error);
564a9643ea8Slogwang
565a9643ea8Slogwang error = ENOSYS;
566a9643ea8Slogwang LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
567a9643ea8Slogwang if (strcmp(mpc->mpc_name, target) == 0 &&
568a9643ea8Slogwang mpc->mpc_ops->mpo_syscall != NULL) {
569a9643ea8Slogwang error = mpc->mpc_ops->mpo_syscall(td,
570a9643ea8Slogwang uap->call, uap->arg);
571a9643ea8Slogwang goto out;
572a9643ea8Slogwang }
573a9643ea8Slogwang }
574a9643ea8Slogwang
575a9643ea8Slogwang if (!LIST_EMPTY(&mac_policy_list)) {
576a9643ea8Slogwang mac_policy_slock_sleep();
577a9643ea8Slogwang LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
578a9643ea8Slogwang if (strcmp(mpc->mpc_name, target) == 0 &&
579a9643ea8Slogwang mpc->mpc_ops->mpo_syscall != NULL) {
580a9643ea8Slogwang error = mpc->mpc_ops->mpo_syscall(td,
581a9643ea8Slogwang uap->call, uap->arg);
582a9643ea8Slogwang break;
583a9643ea8Slogwang }
584a9643ea8Slogwang }
585a9643ea8Slogwang mac_policy_sunlock_sleep();
586a9643ea8Slogwang }
587a9643ea8Slogwang out:
588a9643ea8Slogwang return (error);
589a9643ea8Slogwang }
590a9643ea8Slogwang
591a9643ea8Slogwang #else /* !MAC */
592a9643ea8Slogwang
593a9643ea8Slogwang int
sys___mac_get_pid(struct thread * td,struct __mac_get_pid_args * uap)594a9643ea8Slogwang sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
595a9643ea8Slogwang {
596a9643ea8Slogwang
597a9643ea8Slogwang return (ENOSYS);
598a9643ea8Slogwang }
599a9643ea8Slogwang
600a9643ea8Slogwang int
sys___mac_get_proc(struct thread * td,struct __mac_get_proc_args * uap)601a9643ea8Slogwang sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
602a9643ea8Slogwang {
603a9643ea8Slogwang
604a9643ea8Slogwang return (ENOSYS);
605a9643ea8Slogwang }
606a9643ea8Slogwang
607a9643ea8Slogwang int
sys___mac_set_proc(struct thread * td,struct __mac_set_proc_args * uap)608a9643ea8Slogwang sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
609a9643ea8Slogwang {
610a9643ea8Slogwang
611a9643ea8Slogwang return (ENOSYS);
612a9643ea8Slogwang }
613a9643ea8Slogwang
614a9643ea8Slogwang int
sys___mac_get_fd(struct thread * td,struct __mac_get_fd_args * uap)615a9643ea8Slogwang sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
616a9643ea8Slogwang {
617a9643ea8Slogwang
618a9643ea8Slogwang return (ENOSYS);
619a9643ea8Slogwang }
620a9643ea8Slogwang
621a9643ea8Slogwang int
sys___mac_get_file(struct thread * td,struct __mac_get_file_args * uap)622a9643ea8Slogwang sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
623a9643ea8Slogwang {
624a9643ea8Slogwang
625a9643ea8Slogwang return (ENOSYS);
626a9643ea8Slogwang }
627a9643ea8Slogwang
628a9643ea8Slogwang int
sys___mac_get_link(struct thread * td,struct __mac_get_link_args * uap)629a9643ea8Slogwang sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
630a9643ea8Slogwang {
631a9643ea8Slogwang
632a9643ea8Slogwang return (ENOSYS);
633a9643ea8Slogwang }
634a9643ea8Slogwang
635a9643ea8Slogwang int
sys___mac_set_fd(struct thread * td,struct __mac_set_fd_args * uap)636a9643ea8Slogwang sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
637a9643ea8Slogwang {
638a9643ea8Slogwang
639a9643ea8Slogwang return (ENOSYS);
640a9643ea8Slogwang }
641a9643ea8Slogwang
642a9643ea8Slogwang int
sys___mac_set_file(struct thread * td,struct __mac_set_file_args * uap)643a9643ea8Slogwang sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
644a9643ea8Slogwang {
645a9643ea8Slogwang
646a9643ea8Slogwang return (ENOSYS);
647a9643ea8Slogwang }
648a9643ea8Slogwang
649a9643ea8Slogwang int
sys___mac_set_link(struct thread * td,struct __mac_set_link_args * uap)650a9643ea8Slogwang sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
651a9643ea8Slogwang {
652a9643ea8Slogwang
653a9643ea8Slogwang return (ENOSYS);
654a9643ea8Slogwang }
655a9643ea8Slogwang
656a9643ea8Slogwang int
sys_mac_syscall(struct thread * td,struct mac_syscall_args * uap)657a9643ea8Slogwang sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap)
658a9643ea8Slogwang {
659a9643ea8Slogwang
660a9643ea8Slogwang return (ENOSYS);
661a9643ea8Slogwang }
662a9643ea8Slogwang
663a9643ea8Slogwang #endif /* !MAC */
664