summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_lookup.c19
-rw-r--r--sys/security/audit/audit.c2
-rw-r--r--sys/security/audit/audit.h16
-rw-r--r--sys/security/audit/audit_arg.c15
-rw-r--r--sys/security/audit/audit_bsm_klib.c29
-rw-r--r--sys/security/audit/audit_private.h3
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);
/*
OpenPOWER on IntegriCloud