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
|
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 */
|