Subject: per page fingerprinting for verified exec
To: None <tech-kern@netbsd.org>
From: Brett Lymn <blymn@baesystems.com.au>
List: tech-kern
Date: 08/21/2006 22:56:37
Folks,

This is the second attempt at adding per page fingerprints to verified
exec.  The first iteration wrongly assumed that everyone used the
genfs routines to do their paging, this set of patches fixes this
assumption.

As a recap, this set of patches adds the facility to veriexec to mark
a file as being on "untrusted" media.  This is media that is not under
direct and exclusive control of the kernel (for example, a NFS mount
or maybe even disk on a FCAL) and, as such, there is a chance that the
on disk file may be modified without the kernel knowing this has
happened.  If a long running process has the on disk file modified
then the pager may bring in the modified pages and lead to
unauthorised code being run.  To prevent this happening, when a file
is marked as being on untrusted media a set of fingerprints for each
memory page is generated when the file fingerprint is first checked,
these page fingerprints are then used by the pager to ensure that the
page brought back in has not been modified - if a modified page is
detected the running executable is terminated.

Technically, the per page fingerprints are evaluated in parallel with
the overall file fingerprint, if the overall fingerprint matches then
the per page fingerprints are deemed to be usable and are kept in the
verified exec file entry.  An association of vnode pointer addresses
to veriexec file entries is generated in one of 3 instances:

1) when a new vnode is allocated using getnewvnode()
2) when the file is first loaded - this solves a race where the
   veriexec file entry does not exist when the vnode for the file
   being read is first allocated
3) when a nfs getattr is done - at the time a vnode for nfs is
   allocated the fileid is not known.

This association is important during the paging in of a memory page
from disk, at that time we only know the pointer address to the vnode
struct for the file.  Using the above association we can find the
veriexec file entry and gain access to the stored per-page
fingerprints so that we can check them against the pages brought it.
If there are any mismatches the executable is sent a kill signal and
the "bad" pages are released.

I have this code reliably detecting a modified file on a nfs mount and
killing the affected binary.

Just some notes, yes, I am using fileid, no I am not happy about that
and I do want to move away from fileid - it seems like filehandle
would be ideal to use but a) we need the support in all the
filesystems (we didn't when I last looked, that may have changed) and
b) look at the implications of using it within veriexec.

Here are the patches that add per-page verified exec:

Index: sbin/veriexecctl/veriexecctl.8
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl.8,v
retrieving revision 1.24
diff -b -u -r1.24 veriexecctl.8
--- sbin/veriexecctl/veriexecctl.8	22 Jul 2006 10:43:51 -0000	1.24
+++ sbin/veriexecctl/veriexecctl.8	21 Aug 2006 12:42:04 -0000
@@ -83,8 +83,11 @@
 .Em path
 is the full path to the file and
 .Em type
-is the type of fingerprint used, see above for the default list.
-Other fingerprints may be available depending on kernel configuration.
+is the type of fingerprint used.
+The fingerprint types available depends on the kernel configuration.
+A list of supported fingerprint types can by found by querying the
+variable kern.veriexec.algorithms using
+.Xr sysctl 8 .
 The
 .Em fingerprint
 field is a hexadecimal representation of the fingerprint for
@@ -92,7 +95,7 @@
 The field
 .Em options
 contains the associated options for the file.
-Currently there are seven valid options:
+Valid options are:
 .Pp
 .Bl -tag -width INTERPRETER -compact
 .It Dv DIRECT
@@ -131,10 +134,14 @@
 .Dv FILE
 option.
 .It Dv UNTRUSTED
-This option is used to indicate that the file is located on
-untrusted storage, and its fingerprint should not be cached,
-but calculated each time it is accessed and when pages with
-this file as backing store are paged in.
+Indicates that the storage the file is on is not under direct control
+of the kernel and, therefore, the file cannot be guaranteed not to be
+modified.
+Enabling this flag will cause the veriexec kernel subsystem
+to perform fingerprinting at the memory page level and verify these
+fingerprints when paging parts of the file into memory.
+Enabling this flag will cause an increase in executable start up time,
+an increase in kernel memory usage and decrease in paging performance.
 .El
 .Pp
 There must be only one executable/fingerprint pair per line.
Index: sbin/veriexecctl/veriexecctl.c
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl.c,v
retrieving revision 1.23
diff -b -u -r1.23 veriexecctl.c
--- sbin/veriexecctl/veriexecctl.c	14 Jul 2006 23:00:09 -0000	1.23
+++ sbin/veriexecctl/veriexecctl.c	21 Aug 2006 12:42:04 -0000
@@ -146,7 +146,7 @@
 	 * If there's no access type specified, use the default.
 	 */
 	if (!(params.type & (VERIEXEC_DIRECT|VERIEXEC_INDIRECT|VERIEXEC_FILE)))
-		params.type |= VERIEXEC_DIRECT;
+		params.type |= (VERIEXEC_DIRECT | VERIEXEC_INDIRECT);
 	if (ioctl(gfd, VERIEXEC_LOAD, &params) == -1)
 		warn("Cannot load params from `%s'", params.file);
 	free(params.fingerprint);
Index: sys/coda/coda_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/coda/coda_vnops.c,v
retrieving revision 1.50
diff -b -u -r1.50 coda_vnops.c
--- sys/coda/coda_vnops.c	21 Jul 2006 16:48:47 -0000	1.50
+++ sys/coda/coda_vnops.c	21 Aug 2006 12:42:13 -0000
@@ -73,6 +73,9 @@
 
 #include <miscfs/genfs/genfs.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 #include <coda/coda.h>
 #include <coda/cnode.h>
 #include <coda/coda_vnops.h>
@@ -1949,7 +1952,8 @@
 	cp = coda_alloc();
 	cp->c_fid = *fid;
 
-	err = getnewvnode(VT_CODA, vfsp, coda_vnodeop_p, &vp);
+	err = getnewvnode(VT_CODA, vfsp, coda_vnodeop_p, &vp, cp->c_device,
+			  coda_f2i(fid));
 	if (err) {
 	    panic("coda: getnewvnode returned error %d", err);
 	}
Index: sys/dev/verified_exec.c
===================================================================
RCS file: /cvsroot/src/sys/dev/verified_exec.c,v
retrieving revision 1.41
diff -b -u -r1.41 verified_exec.c
--- sys/dev/verified_exec.c	24 Jul 2006 21:32:39 -0000	1.41
+++ sys/dev/verified_exec.c	21 Aug 2006 12:42:13 -0000
@@ -167,7 +167,6 @@
 	if (veriexec_strict > VERIEXEC_LEARNING) {
 		log(LOG_WARNING, "Veriexec: Strict mode, modifying tables not "
 		    "permitted.\n");
-
 		return (EPERM);
 	}
 
@@ -187,7 +186,8 @@
 		break;
 
 	case VERIEXEC_QUERY:
-		error = veriexec_query((struct veriexec_query_params *)data, l);
+		error = veriexec_query((struct veriexec_query_params *)data,
+				       l);
 		break;
 
 	default:
@@ -296,18 +296,13 @@
 		     (memcmp(hh->fp, params->fingerprint,
 		      min(hh->ops->hash_len, params->size))
 		      != 0)) ? "different" : "same"));
-
 			error = 0;
-			goto out;
+			goto out2;
 	}
 
-	e = malloc(sizeof(*e), M_TEMP, M_WAITOK);
+	e = malloc(sizeof(*e), M_TEMP, M_WAITOK | M_ZERO);
 	e->type = params->type;
-	e->status = FINGERPRINT_NOTEVAL;
-	e->page_fp = NULL;
-	e->page_fp_status = PAGE_FP_NONE;
-	e->npages = 0;
-	e->last_page_size = 0;
+	veriexec_purge(e);
 	if ((e->ops = veriexec_find_ops(params->fp_type)) == NULL) {
 		free(e, M_TEMP);
 		log(LOG_ERR, "Veriexec: Invalid or unknown fingerprint type "
@@ -343,6 +338,17 @@
 	error = veriexec_hashadd(nid.ni_vp, e);
 
  out:
+	/*
+	 * Associate the vnode with the veriexec entry in the vnode ->
+	 * vhe hash tables.  Normally, this would be done by
+	 * getnewvnode() but in this case the veriexec table entry
+	 * lookup will fail so no hash will be inserted.  Fix this up
+	 * here.
+	 */
+	if (error == 0)
+		veriexec_vn_hashadd(nid.ni_vp, 0);
+
+ out2:
 	vrele(nid.ni_vp);
 	return (error);
 }
Index: sys/fs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.34
diff -b -u -r1.34 cd9660_vfsops.c
--- sys/fs/cd9660/cd9660_vfsops.c	23 Jul 2006 22:06:10 -0000	1.34
+++ sys/fs/cd9660/cd9660_vfsops.c	21 Aug 2006 12:42:15 -0000
@@ -66,6 +66,9 @@
 #include <sys/dirent.h>
 #include <sys/kauth.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 #include <fs/cd9660/iso.h>
 #include <fs/cd9660/cd9660_extern.h>
 #include <fs/cd9660/iso_rrip.h>
@@ -737,7 +740,8 @@
 		return (0);
 
 	/* Allocate a new vnode/iso_node. */
-	if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp, dev,
+				 ino)) != 0) {
 		*vpp = NULLVP;
 		return (error);
 	}
Index: sys/fs/msdosfs/msdosfs_denode.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_denode.c,v
retrieving revision 1.14
diff -b -u -r1.14 msdosfs_denode.c
--- sys/fs/msdosfs/msdosfs_denode.c	14 May 2006 21:31:52 -0000	1.14
+++ sys/fs/msdosfs/msdosfs_denode.c	21 Aug 2006 12:42:15 -0000
@@ -266,9 +266,14 @@
 	 * Directory entry was not in cache, have to create a vnode and
 	 * copy it from the passed disk buffer.
 	 */
-	/* getnewvnode() does a VREF() on the vnode */
+	/* getnewvnode() does a VREF() on the vnode.
+	   The fs does not have an inode concept, so we mangle one out
+	   of the dir cluster number plus the offset into the dir */
+
 	error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp,
-			    msdosfs_vnodeop_p, &nvp);
+			    msdosfs_vnodeop_p, &nvp, pmp->pm_dev,
+			    (ino_t) ((((ino_t) dirclust) << 32) + diroffset));
+
 	if (error) {
 		*depp = 0;
 		return (error);
Index: sys/fs/ntfs/ntfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/fs/ntfs/ntfs_subr.c,v
retrieving revision 1.25
diff -b -u -r1.25 ntfs_subr.c
--- sys/fs/ntfs/ntfs_subr.c	14 May 2006 21:31:52 -0000	1.25
+++ sys/fs/ntfs/ntfs_subr.c	21 Aug 2006 12:42:15 -0000
@@ -49,6 +49,9 @@
 
 #include <miscfs/specfs/specdev.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 #include <fs/ntfs/ntfs.h>
 #include <fs/ntfs/ntfsmount.h>
 #include <fs/ntfs/ntfs_inode.h>
Index: sys/fs/ntfs/ntfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/ntfs/ntfs_vfsops.c,v
retrieving revision 1.43
diff -b -u -r1.43 ntfs_vfsops.c
--- sys/fs/ntfs/ntfs_vfsops.c	23 Jul 2006 22:06:10 -0000	1.43
+++ sys/fs/ntfs/ntfs_vfsops.c	21 Aug 2006 12:42:16 -0000
@@ -54,6 +54,9 @@
 
 #include <miscfs/specfs/specdev.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 #include <fs/ntfs/ntfs.h>
 #include <fs/ntfs/ntfs_inode.h>
 #include <fs/ntfs/ntfs_subr.h>
@@ -935,7 +938,8 @@
 		}
 	}
 
-	error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
+	error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp,
+			    ntmp->ntm_dev, ino);
 	if(error) {
 		ntfs_frele(fp);
 		ntfs_ntput(ip);
Index: sys/fs/ptyfs/ptyfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/fs/ptyfs/ptyfs_subr.c,v
retrieving revision 1.7
diff -b -u -r1.7 ptyfs_subr.c
--- sys/fs/ptyfs/ptyfs_subr.c	14 May 2006 21:31:52 -0000	1.7
+++ sys/fs/ptyfs/ptyfs_subr.c	21 Aug 2006 12:42:16 -0000
@@ -211,7 +211,10 @@
 			return 0;
 	} while (lockmgr(&ptyfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
 
-	if ((error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, &vp)) != 0) {
+	vp->v_data = ptyfs = ptyfs_free_get(type, pty, l);
+
+	if ((error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, &vp,
+				 (dev_t) NULL, (ino_t) NULL)) != 0) {
 		*vpp = NULL;
 		lockmgr(&ptyfs_hashlock, LK_RELEASE, NULL);
 		return error;
Index: sys/fs/smbfs/smbfs_node.c
===================================================================
RCS file: /cvsroot/src/sys/fs/smbfs/smbfs_node.c,v
retrieving revision 1.29
diff -b -u -r1.29 smbfs_node.c
--- sys/fs/smbfs/smbfs_node.c	23 Jul 2006 22:06:10 -0000	1.29
+++ sys/fs/smbfs/smbfs_node.c	21 Aug 2006 12:42:16 -0000
@@ -153,7 +153,8 @@
 	np = pool_get(&smbfs_node_pool, PR_WAITOK);
 	memset(np, 0, sizeof(*np));
 
-	error = getnewvnode(VT_SMBFS, mp, smbfs_vnodeop_p, &vp);
+	error = getnewvnode(VT_SMBFS, mp, smbfs_vnodeop_p, &vp,
+			    mp->mnt_stat.f_fsidx.__fsid_val[0], fap->fa_ino);
 	if (error) {
 		pool_put(&smbfs_node_pool, np);
 		return error;
Index: sys/fs/union/union_subr.c
===================================================================
RCS file: /cvsroot/src/sys/fs/union/union_subr.c,v
retrieving revision 1.19
diff -b -u -r1.19 union_subr.c
--- sys/fs/union/union_subr.c	23 Jul 2006 22:06:10 -0000	1.19
+++ sys/fs/union/union_subr.c	21 Aug 2006 12:42:16 -0000
@@ -342,8 +342,11 @@
 {
 	int error;
 	struct union_node *un = NULL;
-	struct vnode *xlowervp = NULLVP;
+	struct vnode *xlowervp = NULLVP, *avp;
 	struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
+	struct vattr va;
+	long dev;
+	ino_t fileid;
 	int hash = 0;
 	int vflag;
 	int try;
@@ -514,7 +517,29 @@
 			goto loop;
 	}
 
-	error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp);
+	dev = mp->mnt_stat.f_fsidx.__fsid_val[0];
+	if (uppervp != NULLVP)
+		avp = uppervp;
+	else if (lowervp != NULLVP)
+		avp = lowervp;
+	else
+		avp = NULLVP;
+
+	error = 0;
+	if (avp != NULLVP) {
+		error = VOP_GETATTR(avp, &va, curlwp->l_proc->p_cred,
+				    curlwp);
+		fileid = va.va_fileid;
+	} else {
+		fileid = 0;
+		dev = 0;
+	}
+
+
+	if (!error)
+		error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp,
+				    dev, fileid);
+
 	if (error) {
 		if (uppervp) {
 			if (dvp == uppervp)
Index: sys/kern/kern_verifiedexec.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_verifiedexec.c,v
retrieving revision 1.66
diff -b -u -r1.66 kern_verifiedexec.c
--- sys/kern/kern_verifiedexec.c	11 Aug 2006 19:17:47 -0000	1.66
+++ sys/kern/kern_verifiedexec.c	21 Aug 2006 12:42:16 -0000
@@ -56,6 +56,7 @@
 #include <crypto/sha2/sha2.h>
 #include <crypto/ripemd160/rmd160.h>
 #include <sys/md5.h>
+#include <uvm/uvm.h>
 #include <uvm/uvm_extern.h>
 #include <sys/fileassoc.h>
 #include <sys/kauth.h>
@@ -68,7 +69,14 @@
 
 const struct sysctlnode *veriexec_count_node;
 
+struct veriexec_vn_hashhead *vn_hash_tbl; /* vnode pointer hashes */
+
+static void
+veriexec_release_pages(int npages, int error, struct vm_page **pps,
+		       struct vnode *vp);
 int veriexec_hook;
+int veriexec_vn_hook;
+u_long vn_hash_mask;
 
 /* Veriexecs table of hash types and their associated information. */
 LIST_HEAD(veriexec_ops_head, veriexec_fp_ops) veriexec_ops_list;
@@ -139,9 +147,15 @@
 
 	/* Register a fileassoc for Veriexec. */
 	veriexec_hook = fileassoc_register("veriexec", veriexec_clear);
+	/* and register another one for our vnode associations, used
+	   for per-page fingerprinting.
+	*/
+	veriexec_vn_hook = fileassoc_register("veriexec_vn", NULL);
+
 #ifdef DIAGNOSTIC
-	if (veriexec_hook == FILEASSOC_INVAL)
-		panic("Veriexec: Can't register meta-hook");
+	if ((veriexec_hook == FILEASSOC_INVAL) ||
+	    (veriexec_vn_hook == FILEASSOC_INVAL))
+		panic("Veriexec: Can't register fileassoc");
 #endif /* DIAGNOSTIC */
 
 	LIST_INIT(&veriexec_ops_list);
@@ -236,12 +250,10 @@
 	if (error)
 		return (error);
 
-#if 0 /* XXX - for now */
 	if ((vfe->type & VERIEXEC_UNTRUSTED) &&
 	    (vfe->page_fp_status == PAGE_FP_NONE))
 		do_perpage = 1;
 	else
-#endif
 		do_perpage = 0;
 
 	ctx = (void *) malloc(vfe->ops->context_size, M_TEMP, M_WAITOK);
@@ -281,6 +293,9 @@
 			if (do_perpage) {
 				free(vfe->page_fp, M_TEMP);
 				vfe->page_fp = NULL;
+				vfe->page_fp_status = PAGE_FP_NONE;
+				/* XXX: make NOMATCH */
+				vfe->status = FINGERPRINT_NOTEVAL;
 			}
 
 			goto bad;
@@ -361,6 +376,20 @@
 	return (fileassoc_lookup(vp, veriexec_hook));
 }
 
+struct veriexec_file_entry *
+veriexec_lookup_hint(struct vnode *vp, uint64_t hint)
+{
+	return (fileassoc_lookup_hint(vp, veriexec_hook, hint));
+}
+
+/* Perform a lookup on the vnode hash table. */
+struct veriexec_vn_hash_entry *
+veriexec_vn_lookup(struct vnode *vnode)
+{
+	return (fileassoc_lookup_hint(vnode, veriexec_vn_hook,
+				      (uint64_t)(intptr_t)vnode));
+}
+
 /*
  * Add an entry to a hash table. If a collision is found, handle it.
  * The passed entry is allocated in kernel memory.
@@ -387,6 +416,86 @@
 }
 
 /*
+ * Add an entry to the vp to veriexec file entry hash table.  If
+ * fileid is 0 then use the unhinted interface to find the entry
+ * otherwise use the fileid as a hint.
+ */
+int
+veriexec_vn_hashadd(struct vnode *vp, ino_t fileid)
+{
+	struct veriexec_file_entry *e;
+	struct veriexec_vn_hash_entry *vn_hash;
+
+	if (fileid == 0)
+		e = veriexec_lookup(vp);
+	else {
+		/*
+		 * XXXXX note that we really want to do a veriexec_lookup() but
+		 * that currently will perform a VOP_GETATTR() which will not
+		 * work.
+		 */
+		e = veriexec_lookup_hint(vp, fileid);
+	}
+
+	if (e == NULL)
+		return 0;
+
+	if ((vn_hash = veriexec_vn_lookup(vp)) != NULL) {
+		vn_hash->vnode = vp;
+		vn_hash->vfe = e;
+		vn_hash->active = 1;
+		return 0;
+	} else {
+		vn_hash = (struct veriexec_vn_hash_entry *)
+			malloc(sizeof(struct veriexec_vn_hash_entry),
+			       M_TEMP, M_WAITOK);
+		vn_hash->vnode = vp;
+		vn_hash->vfe = e;
+		vn_hash->active = 1;
+		return (fileassoc_add_hint(vp, veriexec_vn_hook, vn_hash,
+					   (uint64_t)(intptr_t) vp));
+	}
+}
+
+/*
+ * Deactivate the association between the given vnode pointer and a
+ * veriexec hash entry, if one exists.  We don't free the memory because
+ * it is likely the vnode will be reassociated with a veriexec hash
+ * entry in the future.
+ */
+void
+veriexec_vn_hashremove(struct vnode *vp)
+{
+	struct veriexec_vn_hash_entry *veriexec_vn_entry;
+
+	if ((veriexec_vn_entry = veriexec_vn_lookup(vp)) == NULL)
+		return;
+
+	veriexec_vn_entry->active = 0;
+	veriexec_vn_entry->vfe = NULL;
+}
+
+/*
+ * Perform a vnode get, this is a wrapper call to the real get vnode op
+ * so that we can correctly associate the new vnode pointer with a
+ * veriexec entry, if one exists.
+ */
+
+int
+veriexec_vget(struct mount *mp, ino_t inode, struct vnode **vp)
+{
+	int error;
+
+	error = (*(mp)->mnt_op->vfs_vget)(mp, inode, vp);
+	if (error != 0)
+		return error;
+
+	veriexec_vn_hashadd(*vp, inode);
+
+	return 0;
+}
+
+/*
  * Verify the fingerprint of the given file. If we're called directly from
  * sys_execve(), 'flag' will be VERIEXEC_DIRECT. If we're called from
  * exec_script(), 'flag' will be VERIEXEC_INDIRECT.  If we are called from
@@ -413,8 +522,7 @@
 	/* Evaluate fingerprint if needed. */
 	error = 0;
 	digest = NULL;
-	if ((vfe->status == FINGERPRINT_NOTEVAL) ||
-	    (vfe->type & VERIEXEC_UNTRUSTED)) {
+	if (vfe->status == FINGERPRINT_NOTEVAL) {
 		/* Calculate fingerprint for on-disk file. */
 		digest = (u_char *) malloc(vfe->ops->hash_len, M_TEMP,
 					   M_WAITOK);
@@ -566,6 +674,97 @@
 	return (error);
 }
 
+int
+veriexec_block_verify(struct vnode *vp, struct vm_page **pps,
+    voff_t offset, int *npages)
+{
+	struct veriexec_file_entry *vfe = NULL;
+	struct veriexec_vn_hash_entry *vne;
+	voff_t offidx, i;
+	int error;
+
+	error = 0;
+
+	vne = veriexec_vn_lookup(vp);
+	if (vne == NULL) {
+		return 0;
+	}
+
+	if (vne->active == 0) {
+		/* XXX can we see this in normal operation? */
+		printf("block_verify: vn cache entry inactive\n");
+		return 0;
+	}
+
+	vfe = vne->vfe;
+	if ((vfe == NULL) || (vfe->page_fp == NULL)
+	    || ((vfe->type & VERIEXEC_UNTRUSTED) == 0)
+	    || ((vfe->type & VERIEXEC_UNTRUSTED) &&
+		(vfe->page_fp_status == PAGE_FP_NONE))) {
+		return (0);
+	}
+
+	offidx = (offset >> PAGE_SHIFT);
+	for (i = 0; i < *npages; i++) {
+		if ((pps[i] == NULL) || (pps[i] == PGO_DONTCARE)) {
+			continue;
+		}
+
+		error = veriexec_page_verify(vfe, pps[i], i + offidx, curlwp);
+
+		if (error) {
+			veriexec_release_pages(*npages, error, pps, vp);
+			*npages = 0;
+			return (error);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Release uvm pages - called if an error occurs during page verification.
+ */
+static void
+veriexec_release_pages(int npages, int error, struct vm_page **pps,
+		       struct vnode *vp)
+{
+	struct uvm_object *uobj = &vp->v_uobj;
+	int i;
+	UVMHIST_FUNC("veriexec_release_pages"); UVMHIST_CALLED(ubchist);
+
+	/*
+	 * On error, release all the pages requested,
+	 * the page in may have worked but we are not
+	 * interested if the fingerprinting fails.
+	 */
+	simple_lock(&uobj->vmobjlock);
+	for (i = 0; i < npages; i++) {
+		if ((pps[i] == NULL) || (pps[i] == PGO_DONTCARE)) {
+			continue;
+		}
+		UVMHIST_LOG(ubchist, "veriexec examining pg %p flags 0x%x",
+			    pps[i], pps[i]->flags, 0,0);
+		pps[i]->flags |= PG_RELEASED;
+	}
+	uvm_lock_pageq();
+	for (i = 0; i < npages; i++) {
+		if ((pps[i] == NULL) || (pps[i] == PGO_DONTCARE))
+			continue;
+		pmap_clear_reference(pps[i]);
+		uvm_pagedeactivate(pps[i]);
+		if (pps[i]->flags & PG_WANTED) {
+			wakeup(pps[i]);
+			pps[i]->flags &= ~(PG_WANTED);
+		}
+	}
+	uvm_page_unbusy(pps, npages);
+	uvm_unlock_pageq();
+	simple_unlock(&uobj->vmobjlock);
+	UVMHIST_LOG(ubchist, "veriexec returning",
+		    0,0,0,0);
+}
+
 /*
  * Veriexec remove policy code.
  */
@@ -595,7 +794,7 @@
 	vte = veriexec_tblfind(vp);
 #ifdef DIAGNOSTIC
 	if (vte == NULL)
-		panic("Fileassoc: Inconsistency during entry removel");
+		panic("Fileassoc: Inconsistency during entry removal");
 #endif /* DIAGNOSTIC */
 
 	vte->vte_count--;
@@ -696,6 +895,13 @@
 veriexec_purge(struct veriexec_file_entry *vfe)
 {
 	vfe->status = FINGERPRINT_NOTEVAL;
+	vfe->page_fp_status = PAGE_FP_NONE;
+	vfe->npages = 0;
+	vfe->last_page_size = 0;
+
+	if (vfe->page_fp != NULL)
+		free(vfe->page_fp, M_TEMP);
+	vfe->page_fp = NULL;
 }
 
 /*
Index: sys/kern/vfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_subr.c,v
retrieving revision 1.268
diff -b -u -r1.268 vfs_subr.c
--- sys/kern/vfs_subr.c	23 Jul 2006 22:06:12 -0000	1.268
+++ sys/kern/vfs_subr.c	21 Aug 2006 12:42:17 -0000
@@ -86,6 +86,7 @@
 #include "opt_ddb.h"
 #include "opt_compat_netbsd.h"
 #include "opt_compat_43.h"
+#include "veriexec.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -118,6 +119,10 @@
 
 #include <sys/sysctl.h>
 
+#if NVERIEXEC > 0
+#include <sys/verified_exec.h>
+#endif
+
 const enum vtype iftovt_tab[16] = {
 	VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
 	VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
@@ -487,7 +492,7 @@
  */
 int
 getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *),
-    struct vnode **vpp)
+    struct vnode **vpp, dev_t fsid, ino_t fileid)
 {
 	extern struct uvm_pagerops uvm_vnodeops;
 	struct uvm_object *uobj;
@@ -599,6 +604,19 @@
 
 	if (mp && error != EDEADLK)
 		vfs_unbusy(mp);
+
+#if NVERIEXEC > 0
+	/*
+	 * If both fsid and fileid are 0 then it means that the we are
+	 * never going to get a valid lookup in the veriexec tables normally
+	 * because it is not meaningful on the fs requesting the vnode.
+	 */
+	if ((fsid == 0) && (fileid == 0))
+		return 0;
+
+	veriexec_vn_hashadd(vp, fileid);
+#endif /* NVERIEXEC > 0 */
+
 	return (0);
 }
 
@@ -618,6 +636,11 @@
 	insmntque(vp, NULL);
 	vp->v_type = VBAD;
 
+#if NVERIEXEC > 0
+	/* remove veriexec hash association, if one exists */
+	veriexec_vn_hashremove(vp);
+#endif /* NVERIEXEC > 0 */
+
 	simple_lock(&vp->v_interlock);
 	/*
 	 * Insert at head of LRU list
@@ -1051,7 +1074,8 @@
 		*vpp = NULLVP;
 		return (0);
 	}
-	error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, &nvp);
+	error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, &nvp,
+			    (dev_t) NULL, (ino_t) NULL);
 	if (error) {
 		*vpp = NULLVP;
 		return (error);
@@ -1658,6 +1682,12 @@
 		wakeup((caddr_t)vp);
 	} else
 		simple_unlock(&vp->v_interlock);
+
+#if NVERIEXEC > 0
+	/* remove veriexec hash association, if one exists */
+	veriexec_vn_hashremove(vp);
+#endif /* NVERIEXEC > 0 */
+
 }
 
 /*
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.267
diff -b -u -r1.267 vfs_syscalls.c
Index: sys/kern/vfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.122
diff -b -u -r1.122 vfs_vnops.c
--- sys/kern/vfs_vnops.c	26 Jul 2006 09:33:57 -0000	1.122
+++ sys/kern/vfs_vnops.c	21 Aug 2006 12:42:18 -0000
@@ -230,7 +230,7 @@
 					error = EPERM;
 					goto bad;
 				} else {
-					vfe->status = FINGERPRINT_NOTEVAL;
+					veriexec_purge(vfe);
 				}
 			}
 #endif /* NVERIEXEC > 0 */
@@ -238,7 +238,30 @@
 	}
 
 	if (fmode & O_TRUNC) {
+#ifdef VERIFIED_EXEC
+		if ((error = veriexec_verify(l, vp, pathbuf, VERIEXEC_FILE,
+					     &vfe)) != 0) {
+			/*VOP_UNLOCK(vp, 0);*/
+			goto bad;
+		}
+
+		if (vfe != NULL) {
+			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(vfe);
+			}
+		}
+#endif
+
 		VOP_UNLOCK(vp, 0);			/* XXX */
+
 		if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) {
 			vrele(vp);
 			return (error);
Index: sys/miscfs/fdesc/fdesc_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/fdesc/fdesc_vnops.c,v
retrieving revision 1.92
diff -b -u -r1.92 fdesc_vnops.c
--- sys/miscfs/fdesc/fdesc_vnops.c	14 May 2006 21:31:52 -0000	1.92
+++ sys/miscfs/fdesc/fdesc_vnops.c	21 Aug 2006 12:42:19 -0000
@@ -236,7 +236,8 @@
 	}
 	fdcache_lock |= FDL_LOCKED;
 
-	error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
+	error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp,
+			    mp->mnt_stat.f_fsidx.__fsid_val[0], ix);
 	if (error)
 		goto out;
 	MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
Index: sys/miscfs/genfs/layer_subr.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/genfs/layer_subr.c,v
retrieving revision 1.18
diff -b -u -r1.18 layer_subr.c
--- sys/miscfs/genfs/layer_subr.c	11 Dec 2005 12:24:50 -0000	1.18
+++ sys/miscfs/genfs/layer_subr.c	21 Aug 2006 12:42:19 -0000
@@ -192,10 +192,15 @@
 	struct layer_node *xp;
 	struct vnode *vp, *nvp;
 	int error;
+	struct vattr lva;
 	extern int (**dead_vnodeop_p)(void *);
 
+	if ((error = VOP_GETATTR(lowervp, &lva, curlwp->l_proc->p_cred,
+				 curlwp)) != 0)
+		return error;
+
 	if ((error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p,
-			&vp)) != 0)
+			&vp, lva.va_fsid, lva.va_fileid)) != 0)
 		return (error);
 	vp->v_type = lowervp->v_type;
 	vp->v_flag |= VLAYER;
Index: sys/miscfs/kernfs/kernfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/kernfs/kernfs_subr.c,v
retrieving revision 1.9
diff -b -u -r1.9 kernfs_subr.c
--- sys/miscfs/kernfs/kernfs_subr.c	11 Dec 2005 12:24:51 -0000	1.9
+++ sys/miscfs/kernfs/kernfs_subr.c	21 Aug 2006 12:42:19 -0000
@@ -184,7 +184,8 @@
 		return (0);
 	}
 
-	if ((error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &vp,
+				 0, 0)) != 0) {
 		*vpp = NULL;
 		lockmgr(&kfs_hashlock, LK_RELEASE, NULL);
 		return (error);
Index: sys/miscfs/procfs/procfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_subr.c,v
retrieving revision 1.68
diff -b -u -r1.68 procfs_subr.c
--- sys/miscfs/procfs/procfs_subr.c	1 Mar 2006 12:38:32 -0000	1.68
+++ sys/miscfs/procfs/procfs_subr.c	21 Aug 2006 12:42:19 -0000
@@ -144,7 +144,8 @@
 			return (0);
 	} while (lockmgr(&pfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
 
-	if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, &vp,
+				 0, 0)) != 0) {
 		*vpp = NULL;
 		lockmgr(&pfs_hashlock, LK_RELEASE, NULL);
 		return (error);
Index: sys/miscfs/syncfs/sync_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/syncfs/sync_vnops.c,v
retrieving revision 1.14
diff -b -u -r1.14 sync_vnops.c
--- sys/miscfs/syncfs/sync_vnops.c	14 May 2006 21:32:21 -0000	1.14
+++ sys/miscfs/syncfs/sync_vnops.c	21 Aug 2006 12:42:19 -0000
@@ -74,7 +74,7 @@
 	int error;
 
 	/* Allocate a new vnode */
-	if ((error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, &vp)) != 0)
+	if ((error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, &vp, 0, 0)) != 0)
 		return (error);
 
 	vp->v_writecount = 1;
Index: sys/nfs/nfs_node.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_node.c,v
retrieving revision 1.85
diff -b -u -r1.85 nfs_node.c
--- sys/nfs/nfs_node.c	23 Jul 2006 22:06:14 -0000	1.85
+++ sys/nfs/nfs_node.c	21 Aug 2006 12:42:20 -0000
@@ -59,6 +59,7 @@
 #include <nfs/nfsmount.h>
 #include <nfs/nqnfs.h>
 #include <nfs/nfs_var.h>
+#include <nfs/xdr_subs.h>
 
 struct nfsnodehashhead *nfsnodehashtbl;
 u_long nfsnodehash;
@@ -148,12 +149,8 @@
  * nfsnode structure is returned.
  */
 int
-nfs_nget1(mntp, fhp, fhsize, npp, lkflags)
-	struct mount *mntp;
-	nfsfh_t *fhp;
-	int fhsize;
-	struct nfsnode **npp;
-	int lkflags;
+nfs_nget1(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp,
+	  int lkflags)
 {
 	struct nfsnode *np;
 	struct nfsnodehashhead *nhpp;
@@ -177,7 +174,9 @@
 	}
 	if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
 		goto loop;
-	error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &vp);
+
+	error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &vp,
+			    0, 0);
 	if (error) {
 		*npp = 0;
 		lockmgr(&nfs_hashlock, LK_RELEASE, 0);
Index: sys/nfs/nfs_nqlease.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_nqlease.c,v
retrieving revision 1.67
diff -b -u -r1.67 nfs_nqlease.c
--- sys/nfs/nfs_nqlease.c	13 Jul 2006 12:00:26 -0000	1.67
+++ sys/nfs/nfs_nqlease.c	21 Aug 2006 12:42:20 -0000
@@ -984,7 +984,9 @@
 	fhp = &nfh.fh_generic;
 	nfsm_srvmtofh(fhp);
 	m_freem(mrep);
+
 	error = nfs_nget(nmp->nm_mountp, (nfsfh_t *)fhp, NFSX_V3FH, &np);
+
 	if (error)
 		return (error);
 	vp = NFSTOV(np);
Index: sys/nfs/nfs_subs.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_subs.c,v
retrieving revision 1.166
diff -b -u -r1.166 nfs_subs.c
--- sys/nfs/nfs_subs.c	13 Jul 2006 12:00:26 -0000	1.166
+++ sys/nfs/nfs_subs.c	21 Aug 2006 12:42:22 -0000
@@ -77,6 +77,7 @@
 #include "opt_nfsserver.h"
 #include "opt_iso.h"
 #include "opt_inet.h"
+#include "veriexec.h"
 
 /*
  * These functions support the macros and help fiddle mbuf chains for
@@ -97,6 +98,7 @@
 #include <sys/filedesc.h>
 #include <sys/time.h>
 #include <sys/dirent.h>
+#include <sys/verified_exec.h>
 #include <sys/once.h>
 #include <sys/kauth.h>
 
@@ -1852,6 +1854,12 @@
 				vaper->va_mtime = np->n_mtim;
 		}
 	}
+
+
+#if NVERIEXEC > 0
+	veriexec_vn_hashadd(vp, vap->va_fileid);
+#endif
+
 	return (0);
 }
 
Index: sys/nfs/nfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.241
diff -b -u -r1.241 nfs_vnops.c
--- sys/nfs/nfs_vnops.c	23 Jul 2006 22:06:14 -0000	1.241
+++ sys/nfs/nfs_vnops.c	21 Aug 2006 12:42:23 -0000
@@ -971,6 +971,7 @@
 			m_freem(mrep);
 			return (EISDIR);
 		}
+
 		error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
 		if (error) {
 			m_freem(mrep);
Index: sys/sys/mount.h
===================================================================
RCS file: /cvsroot/src/sys/sys/mount.h,v
retrieving revision 1.148
diff -b -u -r1.148 mount.h
--- sys/sys/mount.h	4 Aug 2006 16:29:51 -0000	1.148
+++ sys/sys/mount.h	21 Aug 2006 12:42:23 -0000
@@ -34,6 +34,8 @@
 #ifndef _SYS_MOUNT_H_
 #define _SYS_MOUNT_H_
 
+#include "opt_veriexec.h"
+
 #ifndef _KERNEL
 #include <sys/featuretest.h>
 #include <sys/ucred.h>
@@ -224,7 +226,11 @@
 #define VFS_QUOTACTL(MP,C,U,A,L)  (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, L)
 #define VFS_STATVFS(MP, SBP, L)	  (*(MP)->mnt_op->vfs_statvfs)(MP, SBP, L)
 #define VFS_SYNC(MP, WAIT, C, L)  (*(MP)->mnt_op->vfs_sync)(MP, WAIT, C, L)
+#if NVERIEXEC > 0
+#define VFS_VGET(MP, INO, VPP)	  (veriexec_vget(MP, INO, VPP))
+#else
 #define VFS_VGET(MP, INO, VPP)    (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP)
+#endif /* NVERIEXEC > 0 */
 #define VFS_FHTOVP(MP, FIDP, VPP) (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP)
 #define	VFS_VPTOFH(VP, FIDP, FIDSZP)  (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP, FIDSZP)
 #define VFS_SNAPSHOT(MP, VP, TS)  (*(MP)->mnt_op->vfs_snapshot)(MP, VP, TS)
Index: sys/sys/verified_exec.h
===================================================================
RCS file: /cvsroot/src/sys/sys/verified_exec.h,v
retrieving revision 1.39
diff -b -u -r1.39 verified_exec.h
--- sys/sys/verified_exec.h	11 Aug 2006 19:17:47 -0000	1.39
+++ sys/sys/verified_exec.h	21 Aug 2006 12:42:23 -0000
@@ -145,6 +145,12 @@
 	struct veriexec_fp_ops *ops;		/* Fingerprint ops vector*/
 };
 
+struct veriexec_vn_hash_entry {
+	unsigned active;
+	struct vnode *vnode;
+	struct veriexec_file_entry *vfe;
+};
+
 /* Veriexec per-table data. */
 struct veriexec_table_entry {
 	uint64_t vte_count;			/* Number of Veriexec entries. */
@@ -180,17 +186,18 @@
 int veriexec_add_fp_ops(struct veriexec_fp_ops *);
 void veriexec_init_fp_ops(void);
 struct veriexec_fp_ops *veriexec_find_ops(u_char *name);
-int veriexec_fp_calc(struct lwp *, struct vnode *, struct veriexec_file_entry *,
-    u_char *);
+int veriexec_fp_calc(struct lwp *, struct vnode *,
+		     struct veriexec_file_entry *, u_char *);
 int veriexec_fp_cmp(struct veriexec_fp_ops *, u_char *, u_char *);
 struct veriexec_table_entry *veriexec_tblfind(struct vnode *);
 struct veriexec_file_entry *veriexec_lookup(struct vnode *);
+struct veriexec_file_entry *veriexec_lookup_hint(struct vnode *, uint64_t);
 int veriexec_hashadd(struct vnode *, struct veriexec_file_entry *);
 int veriexec_verify(struct lwp *, struct vnode *,
     const u_char *, int, struct veriexec_file_entry **);
-int veriexec_page_verify(struct veriexec_file_entry *, struct vm_page *, size_t,
-    struct lwp *);
-int veriexec_removechk(struct vnode *, const char *, struct lwp *l);
+int veriexec_page_verify(struct veriexec_file_entry *, struct vm_page *,
+			 size_t, struct lwp *);
+int veriexec_removechk(struct vnode *, const char *, struct lwp *);
 int veriexec_renamechk(struct vnode *, const char *, struct vnode *,
     const char *, struct lwp *);
 void veriexec_report(const u_char *, const u_char *, struct lwp *, int);
@@ -202,6 +209,12 @@
 void veriexec_purge(struct veriexec_file_entry *);
 int veriexec_rawchk(struct vnode *vp);
 
+struct veriexec_vn_hash_entry *veriexec_vn_lookup(struct vnode *);
+int veriexec_vn_hashadd(struct vnode *, ino_t);
+void veriexec_vn_hashremove(struct vnode *);
+int veriexec_vget(struct mount *, ino_t, struct vnode **);
+int veriexec_block_verify(struct vnode *vp, struct vm_page **pps,
+			  voff_t offset, int *npages);
 #endif /* _KERNEL */
 
 #endif /* !_SYS_VERIFIED_EXEC_H_ */
Index: sys/sys/vnode.h
===================================================================
RCS file: /cvsroot/src/sys/sys/vnode.h,v
retrieving revision 1.155
diff -b -u -r1.155 vnode.h
--- sys/sys/vnode.h	23 Jun 2006 14:13:02 -0000	1.155
+++ sys/sys/vnode.h	21 Aug 2006 12:42:23 -0000
@@ -525,7 +525,7 @@
 struct vnode *
 	checkalias(struct vnode *, dev_t, struct mount *);
 int 	getnewvnode(enum vtagtype, struct mount *, int (**)(void *),
-	    struct vnode **);
+	    struct vnode **, dev_t fsid, ino_t fileid);
 void	ungetnewvnode(struct vnode *);
 int	vaccess(enum vtype, mode_t, uid_t, gid_t, mode_t, kauth_cred_t);
 void 	vattr_null(struct vattr *);
Index: sys/ufs/ext2fs/ext2fs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v
retrieving revision 1.100
diff -b -u -r1.100 ext2fs_vfsops.c
--- sys/ufs/ext2fs/ext2fs_vfsops.c	23 Jul 2006 22:06:14 -0000	1.100
+++ sys/ufs/ext2fs/ext2fs_vfsops.c	21 Aug 2006 12:42:24 -0000
@@ -105,6 +105,9 @@
 #include <ufs/ext2fs/ext2fs_dir.h>
 #include <ufs/ext2fs/ext2fs_extern.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 extern struct lock ufs_hashlock;
 
 int ext2fs_sbupdate(struct ufsmount *, int);
@@ -929,7 +932,8 @@
 		return (0);
 
 	/* Allocate a new vnode/inode. */
-	if ((error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, &vp,
+				 dev, ino)) != 0) {
 		*vpp = NULL;
 		return (error);
 	}
Index: sys/ufs/ext2fs/ext2fs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vnops.c,v
retrieving revision 1.67
diff -b -u -r1.67 ext2fs_vnops.c
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.184
diff -b -u -r1.184 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c	23 Jul 2006 22:06:15 -0000	1.184
+++ sys/ufs/ffs/ffs_vfsops.c	21 Aug 2006 12:42:28 -0000
@@ -1406,7 +1406,8 @@
 		return (0);
 
 	/* Allocate a new vnode/inode. */
-	if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp, dev,
+				 ino)) != 0) {
 		*vpp = NULL;
 		return (error);
 	}
Index: sys/ufs/lfs/lfs_alloc.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_alloc.c,v
retrieving revision 1.96
diff -b -u -r1.96 lfs_alloc.c
Index: sys/ufs/lfs/lfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_syscalls.c,v
retrieving revision 1.115
diff -b -u -r1.115 lfs_syscalls.c
--- sys/ufs/lfs/lfs_syscalls.c	23 Jul 2006 22:06:15 -0000	1.115
+++ sys/ufs/lfs/lfs_syscalls.c	21 Aug 2006 12:42:28 -0000
@@ -92,6 +92,9 @@
 #include <ufs/lfs/lfs.h>
 #include <ufs/lfs/lfs_extern.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 struct buf *lfs_fakebuf(struct lfs *, struct vnode *, int, size_t, caddr_t);
 int lfs_fasthashget(dev_t, ino_t, struct vnode **);
 
@@ -1068,7 +1071,8 @@
 		*vpp = NULL;
 		return EDEADLK;
 	}
-	if ((error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, &vp, dev,
+				 ino)) != 0) {
 		*vpp = NULL;
 		return (error);
 	}
Index: sys/ufs/lfs/lfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vfsops.c,v
retrieving revision 1.218
diff -b -u -r1.218 lfs_vfsops.c
--- sys/ufs/lfs/lfs_vfsops.c	23 Jul 2006 22:06:15 -0000	1.218
+++ sys/ufs/lfs/lfs_vfsops.c	21 Aug 2006 12:42:29 -0000
@@ -115,6 +115,9 @@
 #include <miscfs/genfs/genfs.h>
 #include <miscfs/genfs/genfs_node.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 static int lfs_gop_write(struct vnode *, struct vm_page **, int, int);
 static boolean_t lfs_issequential_hole(const struct ufsmount *,
     daddr_t, daddr_t);
@@ -1098,7 +1101,8 @@
 	if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
 		return (0);
 
-	if ((error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, &vp)) != 0) {
+	if ((error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, &vp,
+				 dev, ino)) != 0) {
 		*vpp = NULL;
 		 return (error);
 	}
Index: sys/ufs/lfs/lfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vnops.c,v
retrieving revision 1.187
diff -b -u -r1.187 lfs_vnops.c
--- sys/ufs/lfs/lfs_vnops.c	6 Aug 2006 12:34:12 -0000	1.187
+++ sys/ufs/lfs/lfs_vnops.c	21 Aug 2006 12:42:29 -0000
@@ -106,6 +106,9 @@
 #include <ufs/lfs/lfs.h>
 #include <ufs/lfs/lfs_extern.h>
 
+#include <sys/vnode.h>
+#include <sys/verified_exec.h>
+
 extern pid_t lfs_writer_daemon;
 
 /* Global vfs data structures for lfs. */
@@ -459,7 +462,8 @@
 	ASSERT_NO_SEGLOCK(fs);
 	if (fs->lfs_ronly)
 		return EROFS;
-	if (vpp && (error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, vpp))) {
+	if (vpp && (error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p,
+					vpp, (dev_t) NULL, (ino_t) NULL))) {
 		DLOG((DLOG_ALLOC, "lfs_set_dirop_create: dvp %p error %d\n",
 		      dvp, error));
 		return error;
Index: sys/ufs/mfs/mfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/mfs/mfs_vfsops.c,v
retrieving revision 1.72
diff -b -u -r1.72 mfs_vfsops.c
--- sys/ufs/mfs/mfs_vfsops.c	15 Apr 2006 01:16:40 -0000	1.72
+++ sys/ufs/mfs/mfs_vfsops.c	21 Aug 2006 12:42:29 -0000
@@ -308,7 +308,8 @@
 			return EINVAL;
 		return (0);
 	}
-	error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
+	error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp,
+			    (dev_t) NULL, (ino_t) NULL);
 	if (error)
 		return (error);
 	devvp->v_type = VBLK;
Index: sys/uvm/uvm_vnode.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_vnode.c,v
retrieving revision 1.72
diff -b -u -r1.72 uvm_vnode.c
--- sys/uvm/uvm_vnode.c	22 Jul 2006 08:47:56 -0000	1.72
+++ sys/uvm/uvm_vnode.c	21 Aug 2006 12:42:30 -0000
@@ -56,6 +56,7 @@
 #include "opt_uvmhist.h"
 #include "opt_readahead.h"
 #include "opt_ddb.h"
+#include "veriexec.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -69,6 +70,9 @@
 #include <sys/conf.h>
 #include <sys/pool.h>
 #include <sys/mount.h>
+#if NVERIEXEC > 0
+#include <sys/verified_exec.h>
+#endif
 
 #include <miscfs/specfs/specdev.h>
 
@@ -315,6 +319,11 @@
 	error = VOP_GETPAGES(vp, offset, pps, npagesp, centeridx,
 			     access_type, advice, flags);
 
+#if NVERIEXEC > 0
+	if (*npagesp > 0)
+		error = veriexec_block_verify(vp, pps, offset, npagesp);
+#endif /* NVERIEXEC > 0 */
+
 #if defined(READAHEAD_STATS)
 	if (((flags & PGO_LOCKED) != 0 && *npagesp > 0) ||
 	    ((flags & (PGO_LOCKED|PGO_SYNCIO)) == PGO_SYNCIO && error == 0)) {

-- 
Brett Lymn