audit: simplify path resolving logic

This commit is contained in:
Mateusz Guzik 2020-02-21 01:40:20 +00:00
parent a1197bde68
commit 9e826d32e8

View File

@ -423,50 +423,34 @@ auditon_command_event(int cmd)
void void
audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath) audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
{ {
struct vnode *cvnp, *rvnp; struct vnode *vp;
char *rbuf, *fbuf, *copy; char *rbuf, *fbuf, *copy;
struct filedesc *fdp; struct filedesc *fdp;
struct sbuf sbf; struct sbuf sbf;
cap_rights_t rights; cap_rights_t rights;
int error, needslash; int error;
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d", WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
__func__, __FILE__, __LINE__); __func__, __FILE__, __LINE__);
copy = path; copy = path;
rvnp = cvnp = NULL;
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
FILEDESC_SLOCK(fdp); FILEDESC_SLOCK(fdp);
/* if (*path == '/') {
* Make sure that we handle the chroot(2) case. If there is an vp = fdp->fd_rdir;
* alternate root directory, prepend it to the audited pathname. vrefact(vp);
*/ } else {
if (fdp->fd_rdir != NULL && fdp->fd_rdir != rootvnode) {
rvnp = fdp->fd_rdir;
vrefact(rvnp);
}
/*
* If the supplied path is relative, make sure we capture the current
* working directory so we can prepend it to the supplied relative
* path.
*/
if (*path != '/') {
if (dirfd == AT_FDCWD) { if (dirfd == AT_FDCWD) {
cvnp = fdp->fd_cdir; vp = fdp->fd_cdir;
vrefact(cvnp); vrefact(vp);
} else { } else {
error = fgetvp(td, dirfd, cap_rights_init(&rights), &cvnp); error = fgetvp(td, dirfd, cap_rights_init(&rights), &vp);
if (error) { if (error != 0) {
FILEDESC_SUNLOCK(fdp); FILEDESC_SUNLOCK(fdp);
cpath[0] = '\0'; cpath[0] = '\0';
if (rvnp != NULL)
vrele(rvnp);
return; return;
} }
} }
needslash = (fdp->fd_rdir != cvnp);
} else {
needslash = 1;
} }
FILEDESC_SUNLOCK(fdp); FILEDESC_SUNLOCK(fdp);
/* /*
@ -476,6 +460,8 @@ audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
(void) sbuf_new(&sbf, cpath, MAXPATHLEN, SBUF_FIXEDLEN); (void) sbuf_new(&sbf, cpath, MAXPATHLEN, SBUF_FIXEDLEN);
/* /*
* Strip leading forward slashes. * Strip leading forward slashes.
*
* Note this does nothing to fully canonicalize the path.
*/ */
while (*copy == '/') while (*copy == '/')
copy++; copy++;
@ -487,35 +473,26 @@ audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
* on Darwin. As a result, this may need some additional attention * on Darwin. As a result, this may need some additional attention
* in the future. * in the future.
*/ */
if (rvnp != NULL) { error = vn_fullpath_global(td, vp, &rbuf, &fbuf);
error = vn_fullpath_global(td, rvnp, &rbuf, &fbuf); vrele(vp);
vrele(rvnp); if (error) {
if (error) { cpath[0] = '\0';
cpath[0] = '\0'; return;
if (cvnp != NULL)
vrele(cvnp);
return;
}
(void) sbuf_cat(&sbf, rbuf);
free(fbuf, M_TEMP);
} }
if (cvnp != NULL) { (void) sbuf_cat(&sbf, rbuf);
error = vn_fullpath(td, cvnp, &rbuf, &fbuf); /*
vrele(cvnp); * We are going to concatenate the resolved path with the passed path
if (error) { * with all slashes removed and we want them glued with a single slash.
cpath[0] = '\0'; * However, if the directory is /, the slash is already there.
return; */
} if (rbuf[1] != '\0')
(void) sbuf_cat(&sbf, rbuf);
free(fbuf, M_TEMP);
}
if (needslash)
(void) sbuf_putc(&sbf, '/'); (void) sbuf_putc(&sbf, '/');
free(fbuf, M_TEMP);
/* /*
* Now that we have processed any alternate root and relative path * Now that we have processed any alternate root and relative path
* names, add the supplied pathname. * names, add the supplied pathname.
*/ */
(void) sbuf_cat(&sbf, copy); (void) sbuf_cat(&sbf, copy);
/* /*
* One or more of the previous sbuf operations could have resulted in * One or more of the previous sbuf operations could have resulted in
* the supplied buffer being overflowed. Check to see if this is the * the supplied buffer being overflowed. Check to see if this is the