diff options
-rw-r--r-- | sys/kern/vfs_lookup.c | 19 | ||||
-rw-r--r-- | sys/security/audit/audit.c | 2 | ||||
-rw-r--r-- | sys/security/audit/audit.h | 16 | ||||
-rw-r--r-- | sys/security/audit/audit_arg.c | 15 | ||||
-rw-r--r-- | sys/security/audit/audit_bsm_klib.c | 29 | ||||
-rw-r--r-- | sys/security/audit/audit_private.h | 3 |
6 files changed, 50 insertions, 34 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 54140ad..c65a247 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -160,17 +160,6 @@ namei(struct nameidata *ndp) error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, (size_t *)&ndp->ni_pathlen); - if (error == 0) { - /* - * If we are auditing the kernel pathname, save the user - * pathname. - */ - if (cnp->cn_flags & AUDITVNODE1) - AUDIT_ARG_UPATH1(td, cnp->cn_pnbuf); - if (cnp->cn_flags & AUDITVNODE2) - AUDIT_ARG_UPATH2(td, cnp->cn_pnbuf); - } - /* * Don't allow empty pathnames. */ @@ -218,6 +207,14 @@ namei(struct nameidata *ndp) ndp->ni_rootdir = fdp->fd_rdir; ndp->ni_topdir = fdp->fd_jdir; + /* + * If we are auditing the kernel pathname, save the user pathname. + */ + if (cnp->cn_flags & AUDITVNODE1) + AUDIT_ARG_UPATH1(td, ndp->ni_dirfd, , cnp->cn_pnbuf); + if (cnp->cn_flags & AUDITVNODE2) + AUDIT_ARG_UPATH2(td, ndp->ni_dirfd, , cnp->cn_pnbuf); + dp = NULL; if (cnp->cn_pnbuf[0] != '/') { if (ndp->ni_startdir != NULL) { diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c index 74bfde7..2063c9d 100644 --- a/sys/security/audit/audit.c +++ b/sys/security/audit/audit.c @@ -691,7 +691,7 @@ audit_proc_coredump(struct thread *td, char *path, int errcode) if (path != NULL) { pathp = &ar->k_ar.ar_arg_upath1; *pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK); - audit_canon_path(td, path, *pathp); + audit_canon_path(td, AT_FDCWD, path, *pathp); ARG_SET_VALID(ar, ARG_UPATH1); } ar->k_ar.ar_arg_signum = td->td_proc->p_sig; diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h index dfcd193..69f6c32 100644 --- a/sys/security/audit/audit.h +++ b/sys/security/audit/audit.h @@ -99,8 +99,8 @@ void audit_arg_sockaddr(struct thread *td, struct sockaddr *sa); void audit_arg_auid(uid_t auid); void audit_arg_auditinfo(struct auditinfo *au_info); void audit_arg_auditinfo_addr(struct auditinfo_addr *au_info); -void audit_arg_upath1(struct thread *td, char *upath); -void audit_arg_upath2(struct thread *td, char *upath); +void audit_arg_upath1(struct thread *td, int dirfd, char *upath); +void audit_arg_upath2(struct thread *td, int dirfd, char *upath); void audit_arg_vnode1(struct vnode *vp); void audit_arg_vnode2(struct vnode *vp); void audit_arg_text(char *text); @@ -276,14 +276,14 @@ void audit_thread_free(struct thread *td); audit_arg_uid((uid)); \ } while (0) -#define AUDIT_ARG_UPATH1(td, upath) do { \ +#define AUDIT_ARG_UPATH1(td, dirfd, upath) do { \ if (AUDITING_TD(curthread)) \ - audit_arg_upath1((td), (upath)); \ + audit_arg_upath1((td), (dirfd), (upath)); \ } while (0) -#define AUDIT_ARG_UPATH2(td, upath) do { \ +#define AUDIT_ARG_UPATH2(td, dirfd, upath) do { \ if (AUDITING_TD(curthread)) \ - audit_arg_upath2((td), (upath)); \ + audit_arg_upath2((td), (dirfd), (upath)); \ } while (0) #define AUDIT_ARG_VALUE(value) do { \ @@ -356,8 +356,8 @@ void audit_thread_free(struct thread *td); #define AUDIT_ARG_SUID(suid) #define AUDIT_ARG_TEXT(text) #define AUDIT_ARG_UID(uid) -#define AUDIT_ARG_UPATH1(td, upath) -#define AUDIT_ARG_UPATH2(td, upath) +#define AUDIT_ARG_UPATH1(td, dirfd, upath) +#define AUDIT_ARG_UPATH2(td, dirfd, upath) #define AUDIT_ARG_VALUE(value) #define AUDIT_ARG_VNODE1(vp) #define AUDIT_ARG_VNODE2(vp) diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c index f19375d..41d6b42 100644 --- a/sys/security/audit/audit_arg.c +++ b/sys/security/audit/audit_arg.c @@ -463,7 +463,8 @@ audit_arg_sockaddr(struct thread *td, struct sockaddr *sa) break; case AF_UNIX: - audit_arg_upath1(td, ((struct sockaddr_un *)sa)->sun_path); + audit_arg_upath1(td, AT_FDCWD, + ((struct sockaddr_un *)sa)->sun_path); ARG_SET_VALID(ar, ARG_SADDRUNIX); break; /* XXXAUDIT: default:? */ @@ -707,16 +708,16 @@ audit_arg_file(struct proc *p, struct file *fp) * freed when the audit record is freed. */ static void -audit_arg_upath(struct thread *td, char *upath, char **pathp) +audit_arg_upath(struct thread *td, int dirfd, char *upath, char **pathp) { if (*pathp == NULL) *pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK); - audit_canon_path(td, upath, *pathp); + audit_canon_path(td, dirfd, upath, *pathp); } void -audit_arg_upath1(struct thread *td, char *upath) +audit_arg_upath1(struct thread *td, int dirfd, char *upath) { struct kaudit_record *ar; @@ -724,12 +725,12 @@ audit_arg_upath1(struct thread *td, char *upath) if (ar == NULL) return; - audit_arg_upath(td, upath, &ar->k_ar.ar_arg_upath1); + audit_arg_upath(td, dirfd, upath, &ar->k_ar.ar_arg_upath1); ARG_SET_VALID(ar, ARG_UPATH1); } void -audit_arg_upath2(struct thread *td, char *upath) +audit_arg_upath2(struct thread *td, int dirfd, char *upath) { struct kaudit_record *ar; @@ -737,7 +738,7 @@ audit_arg_upath2(struct thread *td, char *upath) if (ar == NULL) return; - audit_arg_upath(td, upath, &ar->k_ar.ar_arg_upath2); + audit_arg_upath(td, dirfd, upath, &ar->k_ar.ar_arg_upath2); ARG_SET_VALID(ar, ARG_UPATH2); } diff --git a/sys/security/audit/audit_bsm_klib.c b/sys/security/audit/audit_bsm_klib.c index f26f86c..45cc56a 100644 --- a/sys/security/audit/audit_bsm_klib.c +++ b/sys/security/audit/audit_bsm_klib.c @@ -462,13 +462,13 @@ auditon_command_event(int cmd) * leave the filename starting with '/' in the audit log in this case. */ void -audit_canon_path(struct thread *td, char *path, char *cpath) +audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath) { struct vnode *cvnp, *rvnp; char *rbuf, *fbuf, *copy; struct filedesc *fdp; struct sbuf sbf; - int error, cwir; + int error, needslash, vfslocked; WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d", __func__, __FILE__, __LINE__); @@ -491,10 +491,27 @@ audit_canon_path(struct thread *td, char *path, char *cpath) * path. */ if (*path != '/') { - cvnp = fdp->fd_cdir; - vhold(cvnp); + if (dirfd == AT_FDCWD) { + cvnp = fdp->fd_cdir; + vhold(cvnp); + } else { + /* XXX: fgetvp() that vhold()s vnode instead of vref()ing it would be better */ + error = fgetvp(td, dirfd, 0, &cvnp); + if (error) { + cpath[0] = '\0'; + if (rvnp != NULL) + vdrop(rvnp); + return; + } + vhold(cvnp); + vfslocked = VFS_LOCK_GIANT(cvnp->v_mount); + vrele(cvnp); + VFS_UNLOCK_GIANT(vfslocked); + } + needslash = (fdp->fd_rdir != cvnp); + } else { + needslash = 1; } - cwir = (fdp->fd_rdir == fdp->fd_cdir); FILEDESC_SUNLOCK(fdp); /* * NB: We require that the supplied array be at least MAXPATHLEN bytes @@ -536,7 +553,7 @@ audit_canon_path(struct thread *td, char *path, char *cpath) (void) sbuf_cat(&sbf, rbuf); free(fbuf, M_TEMP); } - if (cwir == 0 || (cwir != 0 && cvnp == NULL)) + if (needslash) (void) sbuf_putc(&sbf, '/'); /* * Now that we have processed any alternate root and relative path diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h index 92a0729..ad931c0 100644 --- a/sys/security/audit/audit_private.h +++ b/sys/security/audit/audit_private.h @@ -388,7 +388,8 @@ au_event_t audit_flags_and_error_to_openevent(int oflags, int error); au_event_t audit_flags_and_error_to_openatevent(int oflags, int error); au_event_t audit_msgctl_to_event(int cmd); au_event_t audit_semctl_to_event(int cmr); -void audit_canon_path(struct thread *td, char *path, char *cpath); +void audit_canon_path(struct thread *td, int dirfd, char *path, + char *cpath); au_event_t auditon_command_event(int cmd); /* |