From e0c161b89c868d8917efdc1af877ef50da7b8c0d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 21 Jun 2009 13:41:32 +0000 Subject: [PATCH] Add another flags argument to vn_open_cred. Use it to specify that some vn_open_cred invocations shall not audit namei path. In particular, specify VN_OPEN_NOAUDIT for dotdot lookup performed by default implementation of vop_vptocnp, and for the open done for core file. vn_fullpath is called from the audit code, and vn_open there need to disable audit to avoid infinite recursion. Core file is created on return to user mode, that, in particular, happens during syscall return. The creation of the core file is audited by direct calls, and we do not want to overwrite audit information for syscall. Reported, reviewed and tested by: rwatson --- .../compat/opensolaris/kern/opensolaris_kobj.c | 3 ++- sys/cddl/compat/opensolaris/sys/vnode.h | 2 +- .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 4 ++-- sys/kern/kern_alq.c | 2 +- sys/kern/kern_sig.c | 3 ++- sys/kern/vfs_default.c | 2 +- sys/kern/vfs_vnops.c | 17 +++++++++-------- sys/sys/vnode.h | 5 ++++- 8 files changed, 22 insertions(+), 16 deletions(-) diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c index 21b2f233e0d..328bba117f7 100644 --- a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c +++ b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c @@ -85,7 +85,8 @@ kobj_open_file_vnode(const char *file) flags = FREAD; NDINIT(&nd, LOOKUP, MPSAFE, UIO_SYSSPACE, file, td); - error = vn_open_cred(&nd, &flags, O_NOFOLLOW, curthread->td_ucred, NULL); + error = vn_open_cred(&nd, &flags, O_NOFOLLOW, 0, curthread->td_ucred, + NULL); NDFREE(&nd, NDF_ONLY_PNBUF); if (error != 0) return (NULL); diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h index 44741d2250b..bf11e674ea6 100644 --- a/sys/cddl/compat/opensolaris/sys/vnode.h +++ b/sys/cddl/compat/opensolaris/sys/vnode.h @@ -182,7 +182,7 @@ vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode, vref(startvp); NDINIT_ATVP(&nd, operation, MPSAFE, UIO_SYSSPACE, pnamep, startvp, td); filemode |= O_NOFOLLOW; - error = vn_open_cred(&nd, &filemode, createmode, td->td_ucred, NULL); + error = vn_open_cred(&nd, &filemode, createmode, 0, td->td_ucred, NULL); NDFREE(&nd, NDF_ONLY_PNBUF); if (error == 0) { /* We just unlock so we hold a reference. */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index a7f47b2cec4..2cf4304dc81 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -4519,7 +4519,7 @@ vop_getextattr { flags = FREAD; NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, attrname, xvp, td); - error = vn_open_cred(&nd, &flags, 0, ap->a_cred, NULL); + error = vn_open_cred(&nd, &flags, 0, 0, ap->a_cred, NULL); vp = nd.ni_vp; NDFREE(&nd, NDF_ONLY_PNBUF); if (error != 0) { @@ -4640,7 +4640,7 @@ vop_setextattr { flags = FFLAGS(O_WRONLY | O_CREAT); NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, attrname, xvp, td); - error = vn_open_cred(&nd, &flags, 0600, ap->a_cred, NULL); + error = vn_open_cred(&nd, &flags, 0600, 0, ap->a_cred, NULL); vp = nd.ni_vp; NDFREE(&nd, NDF_ONLY_PNBUF); if (error != 0) { diff --git a/sys/kern/kern_alq.c b/sys/kern/kern_alq.c index 5296928ca97..a4ece799a5b 100644 --- a/sys/kern/kern_alq.c +++ b/sys/kern/kern_alq.c @@ -351,7 +351,7 @@ alq_open(struct alq **alqp, const char *file, struct ucred *cred, int cmode, NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, file, td); flags = FWRITE | O_NOFOLLOW | O_CREAT; - error = vn_open_cred(&nd, &flags, cmode, cred, NULL); + error = vn_open_cred(&nd, &flags, cmode, 0, cred, NULL); if (error) return (error); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5c1d5532ac4..57afc232ada 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2940,7 +2940,8 @@ coredump(struct thread *td) restart: NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, name, td); flags = O_CREAT | FWRITE | O_NOFOLLOW; - error = vn_open(&nd, &flags, S_IRUSR | S_IWUSR, NULL); + error = vn_open_cred(&nd, &flags, S_IRUSR | S_IWUSR, VN_OPEN_NOAUDIT, + NULL, NULL); if (error) { #ifdef AUDIT audit_proc_coredump(td, name, error); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 7b82a96f1f0..c98dad094e8 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -723,7 +723,7 @@ vop_stdvptocnp(struct vop_vptocnp_args *ap) NDINIT_ATVP(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "..", vp, td); flags = FREAD; - error = vn_open(&nd, &flags, 0, NULL); + error = vn_open_cred(&nd, &flags, 0, VN_OPEN_NOAUDIT, NULL, NULL); if (error) { vn_lock(vp, locked | LK_RETRY); return (error); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 9ffb6a60d8c..bef2804037b 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -91,7 +91,7 @@ vn_open(ndp, flagp, cmode, fp) { struct thread *td = ndp->ni_cnd.cn_thread; - return (vn_open_cred(ndp, flagp, cmode, td->td_ucred, fp)); + return (vn_open_cred(ndp, flagp, cmode, 0, td->td_ucred, fp)); } /* @@ -102,11 +102,8 @@ vn_open(ndp, flagp, cmode, fp) * due to the NDINIT being done elsewhere. */ int -vn_open_cred(ndp, flagp, cmode, cred, fp) - struct nameidata *ndp; - int *flagp, cmode; - struct ucred *cred; - struct file *fp; +vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags, + struct ucred *cred, struct file *fp) { struct vnode *vp; struct mount *mp; @@ -124,9 +121,11 @@ restart: if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF | - MPSAFE | AUDITVNODE1; + MPSAFE; if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; + if (!(vn_open_flags & VN_OPEN_NOAUDIT)) + ndp->ni_cnd.cn_flags |= AUDITVNODE1; bwillwrite(); if ((error = namei(ndp)) != 0) return (error); @@ -181,9 +180,11 @@ restart: ndp->ni_cnd.cn_nameiop = LOOKUP; ndp->ni_cnd.cn_flags = ISOPEN | ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | - LOCKLEAF | MPSAFE | AUDITVNODE1; + LOCKLEAF | MPSAFE; if (!(fmode & FWRITE)) ndp->ni_cnd.cn_flags |= LOCKSHARED; + if (!(vn_open_flags & VN_OPEN_NOAUDIT)) + ndp->ni_cnd.cn_flags |= AUDITVNODE1; if ((error = namei(ndp)) != 0) return (error); if (!mpsafe) diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 1e19bb6cb70..7bd1aba1dad 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -562,6 +562,9 @@ vn_canvmio(struct vnode *vp) */ #include "vnode_if.h" +/* vn_open_flags */ +#define VN_OPEN_NOAUDIT 0x00000001 + /* * Public vnode manipulation functions. */ @@ -637,7 +640,7 @@ int _vn_lock(struct vnode *vp, int flags, char *file, int line); #define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__) int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp); int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, - struct ucred *cred, struct file *fp); + u_int vn_open_flags, struct ucred *cred, struct file *fp); int vn_pollrecord(struct vnode *vp, struct thread *p, int events); int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, enum uio_seg segflg, int ioflg,