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