audit_bsm_klib.c (181053) | audit_bsm_klib.c (181060) |
---|---|
1/* 2 * Copyright (c) 1999-2005 Apple Inc. 3 * Copyright (c) 2005 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 15 unchanged lines hidden (view full) --- 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 1999-2005 Apple Inc. 3 * Copyright (c) 2005 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 15 unchanged lines hidden (view full) --- 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: head/sys/security/audit/audit_bsm_klib.c 181053 2008-07-31 09:54:35Z rwatson $"); | 32__FBSDID("$FreeBSD: head/sys/security/audit/audit_bsm_klib.c 181060 2008-07-31 16:57:41Z csjp $"); |
33 34#include <sys/param.h> 35#include <sys/fcntl.h> 36#include <sys/filedesc.h> 37#include <sys/libkern.h> 38#include <sys/malloc.h> 39#include <sys/mount.h> 40#include <sys/proc.h> 41#include <sys/sem.h> | 33 34#include <sys/param.h> 35#include <sys/fcntl.h> 36#include <sys/filedesc.h> 37#include <sys/libkern.h> 38#include <sys/malloc.h> 39#include <sys/mount.h> 40#include <sys/proc.h> 41#include <sys/sem.h> |
42#include <sys/sbuf.h> |
|
42#include <sys/syscall.h> 43#include <sys/sysctl.h> 44#include <sys/sysent.h> 45#include <sys/vnode.h> 46 47#include <bsm/audit.h> 48#include <bsm/audit_kevents.h> 49#include <security/audit/audit.h> --- 421 unchanged lines hidden (view full) --- 471} 472 473/* 474 * Create a canonical path from given path by prefixing either the root 475 * directory, or the current working directory. If the process working 476 * directory is NULL, we could use 'rootvnode' to obtain the root directory, 477 * but this results in a volfs name written to the audit log. So we will 478 * leave the filename starting with '/' in the audit log in this case. | 43#include <sys/syscall.h> 44#include <sys/sysctl.h> 45#include <sys/sysent.h> 46#include <sys/vnode.h> 47 48#include <bsm/audit.h> 49#include <bsm/audit_kevents.h> 50#include <security/audit/audit.h> --- 421 unchanged lines hidden (view full) --- 472} 473 474/* 475 * Create a canonical path from given path by prefixing either the root 476 * directory, or the current working directory. If the process working 477 * directory is NULL, we could use 'rootvnode' to obtain the root directory, 478 * but this results in a volfs name written to the audit log. So we will 479 * leave the filename starting with '/' in the audit log in this case. |
479 * 480 * XXXRW: Since we combine two paths here, ideally a buffer of size 481 * MAXPATHLEN * 2 would be passed in. | |
482 */ 483void 484audit_canon_path(struct thread *td, char *path, char *cpath) 485{ | 480 */ 481void 482audit_canon_path(struct thread *td, char *path, char *cpath) 483{ |
486 char *bufp; 487 char *retbuf, *freebuf; 488 struct vnode *vnp; | 484 struct vnode *cvnp, *rvnp; 485 char *rbuf, *fbuf, *copy; |
489 struct filedesc *fdp; | 486 struct filedesc *fdp; |
490 int cisr, error, vfslocked; | 487 struct sbuf sbf; 488 int error, cwir, locked; |
491 | 489 |
492 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 493 "audit_canon_path() at %s:%d", __FILE__, __LINE__); | 490 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d", 491 __func__, __FILE__, __LINE__); |
494 | 492 |
493 copy = path; 494 rvnp = cvnp = NULL; |
|
495 fdp = td->td_proc->p_fd; | 495 fdp = td->td_proc->p_fd; |
496 bufp = path; 497 cisr = 0; | |
498 FILEDESC_SLOCK(fdp); | 496 FILEDESC_SLOCK(fdp); |
499 if (*(path) == '/') { 500 while (*(bufp) == '/') 501 bufp++; /* Skip leading '/'s. */ 502 /* 503 * If no process root, or it is the same as the system root, 504 * audit the path as passed in with a single '/'. 505 */ 506 if ((fdp->fd_rdir == NULL) || 507 (fdp->fd_rdir == rootvnode)) { 508 vnp = NULL; 509 bufp--; /* Restore one '/'. */ 510 } else { 511 vnp = fdp->fd_rdir; /* Use process root. */ 512 vref(vnp); 513 } 514 } else { 515 vnp = fdp->fd_cdir; /* Prepend the current dir. */ 516 cisr = (fdp->fd_rdir == fdp->fd_cdir); 517 vref(vnp); 518 bufp = path; | 497 /* 498 * Make sure that we handle the chroot(2) case. If there is an 499 * alternate root directory, prepend it to the audited pathname. 500 */ 501 if (fdp->fd_rdir != NULL && fdp->fd_rdir != rootvnode) { 502 rvnp = fdp->fd_rdir; 503 vhold(rvnp); |
519 } | 504 } |
505 /* 506 * If the supplied path is relative, make sure we capture the current 507 * working directory so we can prepend it to the supplied relative 508 * path. 509 */ 510 if (*path != '/') { 511 cvnp = fdp->fd_cdir; 512 vhold(cvnp); 513 } 514 cwir = (fdp->fd_rdir == fdp->fd_cdir); |
|
520 FILEDESC_SUNLOCK(fdp); | 515 FILEDESC_SUNLOCK(fdp); |
521 if (vnp != NULL) { | 516 /* 517 * NB: We require that the supplied array be at least MAXPATHLEN bytes 518 * long. If this is not the case, then we can run into serious trouble. 519 */ 520 (void) sbuf_new(&sbf, cpath, MAXPATHLEN, SBUF_FIXEDLEN); 521 /* 522 * Strip leading forward slashes. 523 */ 524 while (*copy == '/') 525 copy++; 526 /* 527 * Make sure we handle chroot(2) and prepend the global path to these 528 * environments. 529 * 530 * NB: vn_fullpath(9) on FreeBSD is less reliable than vn_getpath(9) 531 * on Darwin. As a result, this may need some additional attention 532 * in the future. 533 */ 534 if (rvnp != NULL) { |
522 /* | 535 /* |
523 * XXX: vn_fullpath() on FreeBSD is "less reliable" than 524 * vn_getpath() on Darwin, so this will need more attention 525 * in the future. Also, the question and string bounding 526 * here seems a bit questionable and will also require 527 * attention. | 536 * Although unlikely, it is possible for filesystems to define 537 * their own VOP_LOCK, so strictly speaking, we need to 538 * conditionally pickup Giant around calls to vn_lock(9) |
528 */ | 539 */ |
529 vfslocked = VFS_LOCK_GIANT(vnp->v_mount); 530 vn_lock(vnp, LK_EXCLUSIVE | LK_RETRY); 531 error = vn_fullpath(td, vnp, &retbuf, &freebuf); 532 if (error == 0) { 533 /* Copy and free buffer allocated by vn_fullpath(). 534 * If the current working directory was the same as 535 * the root directory, and the path was a relative 536 * pathname, do not separate the two components with 537 * the '/' character. 538 */ 539 snprintf(cpath, MAXPATHLEN, "%s%s%s", retbuf, 540 cisr ? "" : "/", bufp); 541 free(freebuf, M_TEMP); 542 } else | 540 locked = VFS_LOCK_GIANT(rvnp->v_mount); 541 vn_lock(rvnp, LK_EXCLUSIVE | LK_RETRY); 542 vdrop(rvnp); 543 error = vn_fullpath_global(td, rvnp, &rbuf, &fbuf); 544 VOP_UNLOCK(rvnp, 0); 545 VFS_UNLOCK_GIANT(locked); 546 if (error) { |
543 cpath[0] = '\0'; | 547 cpath[0] = '\0'; |
544 vput(vnp); 545 VFS_UNLOCK_GIANT(vfslocked); 546 } else 547 strlcpy(cpath, bufp, MAXPATHLEN); | 548 if (cvnp != NULL) 549 vdrop(cvnp); 550 return; 551 } 552 (void) sbuf_cat(&sbf, rbuf); 553 free(fbuf, M_TEMP); 554 } 555 if (cvnp != NULL) { 556 locked = VFS_LOCK_GIANT(cvnp->v_mount); 557 vn_lock(cvnp, LK_EXCLUSIVE | LK_RETRY); 558 vdrop(cvnp); 559 error = vn_fullpath(td, cvnp, &rbuf, &fbuf); 560 VOP_UNLOCK(cvnp, 0); 561 VFS_UNLOCK_GIANT(locked); 562 if (error) { 563 cpath[0] = '\0'; 564 return; 565 } 566 (void) sbuf_cat(&sbf, rbuf); 567 free(fbuf, M_TEMP); 568 } 569 if (cwir == 0 || (cwir != 0 && cvnp == NULL)) 570 (void) sbuf_cat(&sbf, "/"); 571 /* 572 * Now that we have processed any alternate root and relative path 573 * names, add the supplied pathname. 574 */ 575 (void) sbuf_cat(&sbf, copy); 576 /* 577 * One or more of the previous sbuf operations could have resulted in 578 * the supplied buffer being overflowed. Check to see if this is the 579 * case. 580 */ 581 if (sbuf_overflowed(&sbf) != 0) { 582 cpath[0] = '\0'; 583 return; 584 } 585 sbuf_finish(&sbf); |
548} | 586} |