1 /*- 2 * Copyright (c) 1999-2002, 2006, 2009 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 * This software was developed at the University of Cambridge Computer 21 * Laboratory with support from a grant from Google, Inc. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 */ 44 45 #include <sys/cdefs.h> 46 #include "opt_mac.h" 47 48 #include <sys/param.h> 49 #include <sys/abi_compat.h> 50 #include <sys/capsicum.h> 51 #include <sys/fcntl.h> 52 #include <sys/kernel.h> 53 #include <sys/lock.h> 54 #include <sys/malloc.h> 55 #include <sys/mutex.h> 56 #include <sys/mac.h> 57 #include <sys/proc.h> 58 #include <sys/systm.h> 59 #include <sys/sysctl.h> 60 #include <sys/sysproto.h> 61 #include <sys/vnode.h> 62 #include <sys/mount.h> 63 #include <sys/file.h> 64 #include <sys/namei.h> 65 #include <sys/socket.h> 66 #include <sys/pipe.h> 67 #include <sys/socketvar.h> 68 69 #include <security/mac/mac_framework.h> 70 #include <security/mac/mac_internal.h> 71 #include <security/mac/mac_policy.h> 72 #include <security/mac/mac_syscalls.h> 73 74 #ifdef MAC 75 76 FEATURE(security_mac, "Mandatory Access Control Framework support"); 77 78 static int kern___mac_get_path(struct thread *td, const char *path_p, 79 struct mac *mac_p, int follow); 80 static int kern___mac_set_path(struct thread *td, const char *path_p, 81 struct mac *mac_p, int follow); 82 83 #ifdef COMPAT_FREEBSD32 84 struct mac32 { 85 uint32_t m_buflen; /* size_t */ 86 uint32_t m_string; /* char * */ 87 }; 88 #endif 89 90 /* 91 * Copyin a 'struct mac', including the string pointed to by 'm_string'. 92 * 93 * On success (0 returned), fills '*mac', whose associated storage must be freed 94 * after use by calling free_copied_label() (which see). On success, 'u_string' 95 * if not NULL is filled with the userspace address for 'u_mac->m_string'. 96 */ 97 static int 98 mac_label_copyin_impl(const void *const u_mac, struct mac *const mac, 99 char **const u_string, bool is_32bit) 100 { 101 char *buffer; 102 int error; 103 104 #ifdef COMPAT_FREEBSD32 105 if (is_32bit) { 106 struct mac32 mac32; 107 108 error = copyin(u_mac, &mac32, sizeof(mac32)); 109 if (error != 0) 110 return (error); 111 112 CP(mac32, *mac, m_buflen); 113 PTRIN_CP(mac32, *mac, m_string); 114 } else 115 #endif 116 { 117 error = copyin(u_mac, mac, sizeof(*mac)); 118 if (error != 0) 119 return (error); 120 } 121 122 error = mac_check_structmac_consistent(mac); 123 if (error != 0) 124 return (error); 125 126 /* 'm_buflen' not too big checked by function call above. */ 127 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 128 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 129 if (error != 0) { 130 free(buffer, M_MACTEMP); 131 return (error); 132 } 133 134 MPASS(error == 0); 135 if (u_string != NULL) 136 *u_string = mac->m_string; 137 mac->m_string = buffer; 138 return (0); 139 } 140 141 int 142 mac_label_copyin(const struct mac *const u_mac, struct mac *const mac, 143 char **const u_string) 144 { 145 return (mac_label_copyin_impl(u_mac, mac, u_string, false)); 146 } 147 148 void 149 free_copied_label(const struct mac *const mac) 150 { 151 free(mac->m_string, M_MACTEMP); 152 } 153 154 #ifdef COMPAT_FREEBSD32 155 int 156 mac_label_copyin32(const struct mac32 *const u_mac, 157 struct mac *const mac, char **const u_string) 158 { 159 return (mac_label_copyin_impl(u_mac, mac, u_string, true)); 160 } 161 #endif 162 163 int 164 sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 165 { 166 char *buffer, *u_buffer; 167 struct mac mac; 168 struct proc *tproc; 169 struct ucred *tcred; 170 int error; 171 172 error = mac_label_copyin(uap->mac_p, &mac, &u_buffer); 173 if (error) 174 return (error); 175 176 tproc = pfind(uap->pid); 177 if (tproc == NULL) { 178 error = ESRCH; 179 goto free_mac_and_exit; 180 } 181 182 tcred = NULL; /* Satisfy gcc. */ 183 error = p_cansee(td, tproc); 184 if (error == 0) 185 tcred = crhold(tproc->p_ucred); 186 PROC_UNLOCK(tproc); 187 if (error) 188 goto free_mac_and_exit; 189 190 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 191 error = mac_cred_externalize_label(tcred->cr_label, mac.m_string, 192 buffer, mac.m_buflen); 193 if (error == 0) 194 error = copyout(buffer, u_buffer, strlen(buffer)+1); 195 free(buffer, M_MACTEMP); 196 crfree(tcred); 197 198 free_mac_and_exit: 199 free_copied_label(&mac); 200 return (error); 201 } 202 203 int 204 sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 205 { 206 char *buffer, *u_buffer; 207 struct mac mac; 208 int error; 209 210 error = mac_label_copyin(uap->mac_p, &mac, &u_buffer); 211 if (error) 212 return (error); 213 214 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 215 error = mac_cred_externalize_label(td->td_ucred->cr_label, 216 mac.m_string, buffer, mac.m_buflen); 217 if (error == 0) 218 error = copyout(buffer, u_buffer, strlen(buffer)+1); 219 220 free(buffer, M_MACTEMP); 221 free_copied_label(&mac); 222 return (error); 223 } 224 225 /* 226 * Performs preparation (including allocations) for mac_set_proc(). 227 * 228 * No lock should be held while calling this function. On success, 229 * mac_set_proc_finish() must be called to free the data associated to 230 * 'mac_set_proc_data', even if mac_set_proc_core() fails. 'mac_set_proc_data' 231 * is not set in case of error, and is set to a non-NULL value on success. 232 */ 233 int 234 mac_set_proc_prepare(struct thread *const td, const struct mac *const mac, 235 void **const mac_set_proc_data) 236 { 237 struct label *intlabel; 238 int error; 239 240 PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED); 241 242 if (!(mac_labeled & MPC_OBJECT_CRED)) 243 return (EINVAL); 244 245 intlabel = mac_cred_label_alloc(); 246 error = mac_cred_internalize_label(intlabel, mac->m_string); 247 if (error) { 248 mac_cred_label_free(intlabel); 249 return (error); 250 } 251 252 *mac_set_proc_data = intlabel; 253 return (0); 254 } 255 256 /* 257 * Actually sets the MAC label on 'newcred'. 258 * 259 * The current process' lock *must* be held. This function only sets the label 260 * on 'newcred', but does not put 'newcred' in place on the current process' 261 * (consequently, it also does not call setsugid()). 'mac_set_proc_data' must 262 * be the pointer returned by mac_set_proc_prepare(). If called, this function 263 * must be so between a successful call to mac_set_proc_prepare() and 264 * mac_set_proc_finish(), but calling it is not mandatory (e.g., if some other 265 * error occured under the process lock that obsoletes setting the MAC label). 266 */ 267 int 268 mac_set_proc_core(struct thread *const td, struct ucred *const newcred, 269 void *const mac_set_proc_data) 270 { 271 struct label *const intlabel = mac_set_proc_data; 272 struct proc *const p = td->td_proc; 273 int error; 274 275 MPASS(td == curthread); 276 PROC_LOCK_ASSERT(p, MA_OWNED); 277 278 error = mac_cred_check_relabel(p->p_ucred, intlabel); 279 if (error) 280 return (error); 281 282 mac_cred_relabel(newcred, intlabel); 283 return (0); 284 } 285 286 /* 287 * Performs mac_set_proc() last operations, without the process lock. 288 * 289 * 'proc_label_set' indicates whether the label was actually set by a call to 290 * mac_set_proc_core() that succeeded. 'mac_set_proc_data' must be the pointer 291 * returned by mac_set_proc_prepare(), and its associated data will be freed. 292 */ 293 void 294 mac_set_proc_finish(struct thread *const td, bool proc_label_set, 295 void *const mac_set_proc_data) 296 { 297 struct label *const intlabel = mac_set_proc_data; 298 299 PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED); 300 301 if (proc_label_set) 302 mac_proc_vm_revoke(td); 303 mac_cred_label_free(intlabel); 304 } 305 306 int 307 sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 308 { 309 struct ucred *newcred, *oldcred; 310 void *intlabel; 311 struct proc *const p = td->td_proc; 312 struct mac mac; 313 int error; 314 315 error = mac_label_copyin(uap->mac_p, &mac, NULL); 316 if (error) 317 return (error); 318 319 error = mac_set_proc_prepare(td, &mac, &intlabel); 320 if (error) 321 goto free_label; 322 323 newcred = crget(); 324 325 PROC_LOCK(p); 326 oldcred = p->p_ucred; 327 crcopy(newcred, oldcred); 328 329 error = mac_set_proc_core(td, newcred, intlabel); 330 if (error) { 331 PROC_UNLOCK(p); 332 crfree(newcred); 333 goto finish; 334 } 335 336 setsugid(p); 337 proc_set_cred(p, newcred); 338 PROC_UNLOCK(p); 339 340 crfree(oldcred); 341 finish: 342 mac_set_proc_finish(td, error == 0, intlabel); 343 free_label: 344 free_copied_label(&mac); 345 return (error); 346 } 347 348 int 349 sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 350 { 351 char *u_buffer, *buffer; 352 struct label *intlabel; 353 struct file *fp; 354 struct mac mac; 355 struct vnode *vp; 356 struct pipe *pipe; 357 struct socket *so; 358 cap_rights_t rights; 359 int error; 360 361 error = mac_label_copyin(uap->mac_p, &mac, &u_buffer); 362 if (error) 363 return (error); 364 365 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 366 error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_GET), 367 &fp); 368 if (error) 369 goto out; 370 371 switch (fp->f_type) { 372 case DTYPE_FIFO: 373 case DTYPE_VNODE: 374 if (!(mac_labeled & MPC_OBJECT_VNODE)) { 375 error = EINVAL; 376 goto out_fdrop; 377 } 378 vp = fp->f_vnode; 379 intlabel = mac_vnode_label_alloc(); 380 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 381 mac_vnode_copy_label(vp->v_label, intlabel); 382 VOP_UNLOCK(vp); 383 error = mac_vnode_externalize_label(intlabel, mac.m_string, 384 buffer, mac.m_buflen); 385 mac_vnode_label_free(intlabel); 386 break; 387 388 case DTYPE_PIPE: 389 if (!(mac_labeled & MPC_OBJECT_PIPE)) { 390 error = EINVAL; 391 goto out_fdrop; 392 } 393 pipe = fp->f_data; 394 intlabel = mac_pipe_label_alloc(); 395 PIPE_LOCK(pipe); 396 mac_pipe_copy_label(pipe->pipe_pair->pp_label, intlabel); 397 PIPE_UNLOCK(pipe); 398 error = mac_pipe_externalize_label(intlabel, mac.m_string, 399 buffer, mac.m_buflen); 400 mac_pipe_label_free(intlabel); 401 break; 402 403 case DTYPE_SOCKET: 404 if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 405 error = EINVAL; 406 goto out_fdrop; 407 } 408 so = fp->f_data; 409 intlabel = mac_socket_label_alloc(M_WAITOK); 410 SOCK_LOCK(so); 411 mac_socket_copy_label(so->so_label, intlabel); 412 SOCK_UNLOCK(so); 413 error = mac_socket_externalize_label(intlabel, mac.m_string, 414 buffer, mac.m_buflen); 415 mac_socket_label_free(intlabel); 416 break; 417 418 default: 419 error = EINVAL; 420 } 421 if (error == 0) 422 error = copyout(buffer, u_buffer, strlen(buffer)+1); 423 out_fdrop: 424 fdrop(fp, td); 425 out: 426 free(buffer, M_MACTEMP); 427 free_copied_label(&mac); 428 return (error); 429 } 430 431 int 432 sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 433 { 434 435 return (kern___mac_get_path(td, uap->path_p, uap->mac_p, FOLLOW)); 436 } 437 438 int 439 sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 440 { 441 442 return (kern___mac_get_path(td, uap->path_p, uap->mac_p, NOFOLLOW)); 443 } 444 445 static int 446 kern___mac_get_path(struct thread *td, const char *path_p, struct mac *mac_p, 447 int follow) 448 { 449 char *u_buffer, *buffer; 450 struct nameidata nd; 451 struct label *intlabel; 452 struct mac mac; 453 int error; 454 455 if (!(mac_labeled & MPC_OBJECT_VNODE)) 456 return (EINVAL); 457 458 error = mac_label_copyin(mac_p, &mac, &u_buffer); 459 if (error) 460 return (error); 461 462 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 463 NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p); 464 error = namei(&nd); 465 if (error) 466 goto out; 467 468 intlabel = mac_vnode_label_alloc(); 469 mac_vnode_copy_label(nd.ni_vp->v_label, intlabel); 470 error = mac_vnode_externalize_label(intlabel, mac.m_string, buffer, 471 mac.m_buflen); 472 vput(nd.ni_vp); 473 NDFREE_PNBUF(&nd); 474 mac_vnode_label_free(intlabel); 475 476 if (error == 0) 477 error = copyout(buffer, u_buffer, strlen(buffer)+1); 478 479 out: 480 free(buffer, M_MACTEMP); 481 free_copied_label(&mac); 482 483 return (error); 484 } 485 486 int 487 sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 488 { 489 struct label *intlabel; 490 struct pipe *pipe; 491 struct socket *so; 492 struct file *fp; 493 struct mount *mp; 494 struct vnode *vp; 495 struct mac mac; 496 cap_rights_t rights; 497 int error; 498 499 error = mac_label_copyin(uap->mac_p, &mac, NULL); 500 if (error) 501 return (error); 502 503 error = fget(td, uap->fd, cap_rights_init_one(&rights, CAP_MAC_SET), 504 &fp); 505 if (error) 506 goto out; 507 508 switch (fp->f_type) { 509 case DTYPE_FIFO: 510 case DTYPE_VNODE: 511 if (!(mac_labeled & MPC_OBJECT_VNODE)) { 512 error = EINVAL; 513 goto out_fdrop; 514 } 515 intlabel = mac_vnode_label_alloc(); 516 error = mac_vnode_internalize_label(intlabel, mac.m_string); 517 if (error) { 518 mac_vnode_label_free(intlabel); 519 break; 520 } 521 vp = fp->f_vnode; 522 error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH); 523 if (error != 0) { 524 mac_vnode_label_free(intlabel); 525 break; 526 } 527 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 528 error = vn_setlabel(vp, intlabel, td->td_ucred); 529 VOP_UNLOCK(vp); 530 vn_finished_write(mp); 531 mac_vnode_label_free(intlabel); 532 break; 533 534 case DTYPE_PIPE: 535 if (!(mac_labeled & MPC_OBJECT_PIPE)) { 536 error = EINVAL; 537 goto out_fdrop; 538 } 539 intlabel = mac_pipe_label_alloc(); 540 error = mac_pipe_internalize_label(intlabel, mac.m_string); 541 if (error == 0) { 542 pipe = fp->f_data; 543 PIPE_LOCK(pipe); 544 error = mac_pipe_label_set(td->td_ucred, 545 pipe->pipe_pair, intlabel); 546 PIPE_UNLOCK(pipe); 547 } 548 mac_pipe_label_free(intlabel); 549 break; 550 551 case DTYPE_SOCKET: 552 if (!(mac_labeled & MPC_OBJECT_SOCKET)) { 553 error = EINVAL; 554 goto out_fdrop; 555 } 556 intlabel = mac_socket_label_alloc(M_WAITOK); 557 error = mac_socket_internalize_label(intlabel, mac.m_string); 558 if (error == 0) { 559 so = fp->f_data; 560 error = mac_socket_label_set(td->td_ucred, so, 561 intlabel); 562 } 563 mac_socket_label_free(intlabel); 564 break; 565 566 default: 567 error = EINVAL; 568 } 569 out_fdrop: 570 fdrop(fp, td); 571 out: 572 free_copied_label(&mac); 573 return (error); 574 } 575 576 int 577 sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 578 { 579 580 return (kern___mac_set_path(td, uap->path_p, uap->mac_p, FOLLOW)); 581 } 582 583 int 584 sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 585 { 586 587 return (kern___mac_set_path(td, uap->path_p, uap->mac_p, NOFOLLOW)); 588 } 589 590 static int 591 kern___mac_set_path(struct thread *td, const char *path_p, struct mac *mac_p, 592 int follow) 593 { 594 struct label *intlabel; 595 struct nameidata nd; 596 struct mount *mp; 597 struct mac mac; 598 int error; 599 600 if (!(mac_labeled & MPC_OBJECT_VNODE)) 601 return (EINVAL); 602 603 error = mac_label_copyin(mac_p, &mac, NULL); 604 if (error) 605 return (error); 606 607 intlabel = mac_vnode_label_alloc(); 608 error = mac_vnode_internalize_label(intlabel, mac.m_string); 609 free_copied_label(&mac); 610 if (error) 611 goto out; 612 613 NDINIT(&nd, LOOKUP, LOCKLEAF | follow, UIO_USERSPACE, path_p); 614 error = namei(&nd); 615 if (error == 0) { 616 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | V_PCATCH); 617 if (error == 0) { 618 error = vn_setlabel(nd.ni_vp, intlabel, 619 td->td_ucred); 620 vn_finished_write(mp); 621 } 622 vput(nd.ni_vp); 623 NDFREE_PNBUF(&nd); 624 } 625 out: 626 mac_vnode_label_free(intlabel); 627 return (error); 628 } 629 630 int 631 sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 632 { 633 struct mac_policy_conf *mpc; 634 char target[MAC_MAX_POLICY_NAME]; 635 int error; 636 637 error = copyinstr(uap->policy, target, sizeof(target), NULL); 638 if (error) 639 return (error); 640 641 error = ENOSYS; 642 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 643 if (strcmp(mpc->mpc_name, target) == 0 && 644 mpc->mpc_ops->mpo_syscall != NULL) { 645 error = mpc->mpc_ops->mpo_syscall(td, 646 uap->call, uap->arg); 647 goto out; 648 } 649 } 650 651 if (!LIST_EMPTY(&mac_policy_list)) { 652 mac_policy_slock_sleep(); 653 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 654 if (strcmp(mpc->mpc_name, target) == 0 && 655 mpc->mpc_ops->mpo_syscall != NULL) { 656 error = mpc->mpc_ops->mpo_syscall(td, 657 uap->call, uap->arg); 658 break; 659 } 660 } 661 mac_policy_sunlock_sleep(); 662 } 663 out: 664 return (error); 665 } 666 667 #else /* !MAC */ 668 669 int 670 sys___mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 671 { 672 673 return (ENOSYS); 674 } 675 676 int 677 sys___mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 678 { 679 680 return (ENOSYS); 681 } 682 683 int 684 sys___mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 685 { 686 687 return (ENOSYS); 688 } 689 690 int 691 sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 692 { 693 694 return (ENOSYS); 695 } 696 697 int 698 sys___mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 699 { 700 701 return (ENOSYS); 702 } 703 704 int 705 sys___mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 706 { 707 708 return (ENOSYS); 709 } 710 711 int 712 sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 713 { 714 715 return (ENOSYS); 716 } 717 718 int 719 sys___mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 720 { 721 722 return (ENOSYS); 723 } 724 725 int 726 sys___mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 727 { 728 729 return (ENOSYS); 730 } 731 732 int 733 sys_mac_syscall(struct thread *td, struct mac_syscall_args *uap) 734 { 735 736 return (ENOSYS); 737 } 738 739 #endif /* !MAC */ 740