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