Deleted Added
full compact
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}