Subject: eliminating veriexec #ifdefs in vfs_vnops.c
To: None <tech-kern@NetBSD.org>
From: Elad Efrat <elad@NetBSD.org>
List: tech-kern
Date: 12/29/2006 14:46:19
This is a multi-part message in MIME format.
--------------010908070505040806050404
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

hi,

attached diff does, well, what the subject line says.

it works here, but I'd like some more eyes on it (locking issues? I
dunno), so please review.

if no one objects, I'll just go ahead and commit it.

-e.

--------------010908070505040806050404
Content-Type: text/plain;
 name="openchk.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="openchk.diff"

Index: sys/verified_exec.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/verified_exec.h,v
retrieving revision 1.47
diff -u -p -r1.47 verified_exec.h
--- sys/verified_exec.h	26 Dec 2006 07:50:40 -0000	1.47
+++ sys/verified_exec.h	27 Dec 2006 22:38:43 -0000
@@ -122,6 +122,7 @@ int veriexec_removechk(struct vnode *, c
 int veriexec_renamechk(struct vnode *, const char *, struct vnode *,
     const char *, struct lwp *);
 int veriexec_unmountchk(struct mount *);
+int veriexec_openchk(struct lwp *, struct nameidata *, int);
 #endif /* _KERNEL */
 
 #endif /* !_SYS_VERIFIED_EXEC_H_ */
Index: kern/vfs_vnops.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.129
diff -u -p -r1.129 vfs_vnops.c
--- kern/vfs_vnops.c	30 Nov 2006 01:09:47 -0000	1.129
+++ kern/vfs_vnops.c	27 Dec 2006 22:38:19 -0000
@@ -104,28 +104,11 @@ vn_open(struct nameidata *ndp, int fmode
 	kauth_cred_t cred = l->l_cred;
 	struct vattr va;
 	int error;
-#if NVERIEXEC > 0
-	const char *pathbuf;
-	char *tmppathbuf;
-	boolean_t veriexec_monitored = FALSE;
-#endif /* NVERIEXEC > 0 */
 
 #if NVERIEXEC > 0
-	if (ndp->ni_segflg == UIO_USERSPACE) {	
-		tmppathbuf = PNBUF_GET();
-		error = copyinstr(ndp->ni_dirp, tmppathbuf, MAXPATHLEN,
-		    NULL);
-		if (error) {
-			if (veriexec_verbose >= 1)
-				log(LOG_NOTICE, "Veriexec: Can't copy path."
-				    " (error=%d)\n", error);
-			goto bad2;
-		}
-		pathbuf = tmppathbuf;
-	} else {
-		tmppathbuf = NULL;
-		pathbuf = ndp->ni_dirp;
-	}
+	error = veriexec_openchk(l, ndp, fmode);
+	if (error)
+		return (error);
 #endif /* NVERIEXEC > 0 */
 
 restart:
@@ -138,20 +121,6 @@ restart:
 		if ((error = namei(ndp)) != 0)
 			goto bad2;
 		if (ndp->ni_vp == NULL) {
-#if NVERIEXEC > 0
-			/* Lockdown mode: Prevent creation of new files. */
-			if (veriexec_strict >= VERIEXEC_LOCKDOWN) {
-				VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
-
-				log(LOG_ALERT, "Veriexec: Preventing "
-				    "new file creation in %s.\n", pathbuf);
-
-				vp = ndp->ni_dvp;
-				error = EPERM;
-				goto bad;
-			}
-#endif /* NVERIEXEC > 0 */
-
 			VATTR_NULL(&va);
 			va.va_type = VREG;
 			va.va_mode = cmode;
@@ -206,12 +175,6 @@ restart:
 	}
 
 	if ((fmode & O_CREAT) == 0) {
-#if NVERIEXEC > 0
-		if ((error = veriexec_verify(l, vp, pathbuf, VERIEXEC_FILE,
-		    &veriexec_monitored)) != 0)
-			goto bad;
-#endif /* NVERIEXEC > 0 */
-
 		if (fmode & FREAD) {
 			if ((error = VOP_ACCESS(vp, VREAD, cred, l)) != 0)
 				goto bad;
@@ -225,45 +188,10 @@ restart:
 			if ((error = vn_writechk(vp)) != 0 ||
 			    (error = VOP_ACCESS(vp, VWRITE, cred, l)) != 0)
 				goto bad;
-#if NVERIEXEC > 0
-			if (veriexec_monitored) {
-				veriexec_report("Write access request.",
-				    pathbuf, l, REPORT_ALWAYS|REPORT_ALARM);
-
-				/* IPS mode: Deny writing to monitored files. */
-				if (veriexec_strict >= VERIEXEC_IPS) {
-					error = EPERM;
-					goto bad;
-				} else {
-					veriexec_purge(vp);
-				}
-			}
-#endif /* NVERIEXEC > 0 */
 		}
 	}
 
 	if (fmode & O_TRUNC) {
-#if NVERIEXEC > 0 
-		if ((error = veriexec_verify(l, vp, pathbuf, VERIEXEC_FILE,
-		    &veriexec_monitored)) != 0) {
-			/*VOP_UNLOCK(vp, 0);*/
-			goto bad;
-		}
-
-		if (veriexec_monitored) {
-			veriexec_report("Truncate access request.", pathbuf, l,
-			    REPORT_VERBOSE | REPORT_ALARM);
-
-			/* IPS mode: Deny truncating monitored files. */
-			if (veriexec_strict >= 2) {
-				error = EPERM;
-				goto bad;
-			} else {
-				veriexec_purge(vp);
-			}
-		}
-#endif /* NVERIEXEC > 0 */
-
 		VOP_UNLOCK(vp, 0);			/* XXX */
 
 		if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) {
@@ -294,11 +222,6 @@ bad:
 		vput(vp);
 
 bad2:
-#if NVERIEXEC > 0
-	if (tmppathbuf != NULL)
-		PNBUF_PUT(tmppathbuf);
-#endif /* NVERIEXEC > 0 */
-
 	return (error);
 }
 
Index: kern/kern_verifiedexec.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/kern_verifiedexec.c,v
retrieving revision 1.87
diff -u -p -r1.87 kern_verifiedexec.c
--- kern/kern_verifiedexec.c	29 Dec 2006 11:34:14 -0000	1.87
+++ kern/kern_verifiedexec.c	28 Dec 2006 02:13:41 -0000
@@ -64,6 +64,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_verifie
 #include <sys/conf.h>
 #include <miscfs/specfs/specdev.h>
 #include <prop/proplib.h>
+#include <sys/fcntl.h>
 
 MALLOC_DEFINE(M_VERIEXEC, "Veriexec", "Veriexec data-structures");
 
@@ -1229,3 +1230,70 @@ veriexec_unmountchk(struct mount *mp)
 
 	return (error);
 }
+
+int
+veriexec_openchk(struct lwp *l, struct nameidata *ndp, int fmode)
+{
+	struct vnode *vp;
+	pathname_t pn = NULL;
+	boolean_t monitored = FALSE;
+	int error;
+
+	ndp->ni_cnd.cn_nameiop = LOOKUP;
+	ndp->ni_cnd.cn_flags = LOCKLEAF;
+	if (!(fmode & O_EXCL) && !(fmode & O_NOFOLLOW))
+		ndp->ni_cnd.cn_flags |= FOLLOW;
+	error = namei(ndp);
+	vp = error ? NULL : ndp->ni_vp;
+	if (error && (error != ENOENT))
+		goto out;
+
+	error = pathname_get(ndp->ni_dirp, ndp->ni_segflg, &pn);
+	if (error) {
+		if (veriexec_verbose >= 1)
+			log(LOG_NOTICE, "Veriexec: Can't copy path. "
+			    "(error=%d)\n", error);
+		goto out;
+	}
+
+	if (vp == NULL) {
+		/* If no creation requested, let this fail normally. */
+		if (!(fmode & O_CREAT)) {
+			error = 0;
+			goto out;
+		}
+
+		/* Lockdown mode: Prevent creation of new files. */
+		if (veriexec_strict >= VERIEXEC_LOCKDOWN) {
+			log(LOG_ALERT, "Veriexec: Preventing new file "
+			    "creation in `%s'.\n", pathname_path(pn));
+			error = EPERM;
+		}
+
+		goto out;
+	}
+
+	error = veriexec_verify(l, vp, pathname_path(pn), VERIEXEC_FILE,
+	    &monitored);
+	if (error)
+		goto out;
+
+	if (monitored && ((fmode & FWRITE) || (fmode & O_TRUNC))) {
+		veriexec_report("Write access request.", pathname_path(pn), l,
+		    REPORT_ALWAYS | REPORT_ALARM);
+
+		/* IPS mode: Deny writing to/truncating monitored files. */
+		if (veriexec_strict >= VERIEXEC_IPS)
+			error = EPERM;
+		else
+			veriexec_purge(vp);
+	}
+
+ out:
+	if (vp != NULL)
+		vput(vp);
+
+	pathname_put(pn);
+
+	return (error);
+}

--------------010908070505040806050404--