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