Subject: Getting rid of /dev/veriexec
To: None <tech-kern@netbsd.org>
From: Elad Efrat <elad@NetBSD.org>
List: tech-kern
Date: 12/02/2005 14:24:37
This is a multi-part message in MIME format.
--------------080801030804080008050308
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Hi,

The attached patch does the following:

  - Veriexec loading is done via sysctl() and not ioctl().
  - Adds ability to delete entries from a Veriexec table.

This will allow us to remove /dev/veriexec.

Please have a look; if no one object I'll commit this next
week.

-e.

-- 
Elad Efrat

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

Index: sbin/veriexecctl/veriexecctl.8
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl.8,v
retrieving revision 1.19
diff -u -p -r1.19 veriexecctl.8
--- sbin/veriexecctl/veriexecctl.8	5 Oct 2005 13:58:49 -0000	1.19
+++ sbin/veriexecctl/veriexecctl.8	2 Dec 2005 11:27:53 -0000
@@ -31,7 +31,7 @@
 .\"
 .\"	$Id: veriexecctl.8,v 1.19 2005/10/05 13:58:49 wiz Exp $
 .\"
-.Dd October 4, 2005
+.Dd December 1, 2005
 .Dt VERIEXECCTL 8
 .Os
 .Sh NAME
@@ -134,13 +134,10 @@ If no options are specified, both direct
 are implied.
 .Sh FILES
 .Bl -tag -width /etc/signatures -compact
-.It Pa /dev/veriexec
-veriexec device node
 .It Pa /etc/signatures
 default signatures file
 .El
 .Sh SEE ALSO
-.Xr veriexec 4 ,
 .Pa /usr/share/examples/veriexecctl/fpgen.sh ,
 .Pa /usr/share/examples/veriexecctl/gen_md5 ,
 .Pa /usr/share/examples/veriexecctl/gen_rmd160 ,
@@ -153,6 +150,6 @@ first appeared in
 .Nm
 requires the kernel to have been configured with the
 .Dv VERIFIED_EXEC
-option and the veriexec pseudo-device.
+option.
 .Sh BUGS
 There must be no whitespace in the path field of a fingerprint entry.
Index: sbin/veriexecctl/veriexecctl.c
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl.c,v
retrieving revision 1.17
diff -u -p -r1.17 veriexecctl.c
--- sbin/veriexecctl/veriexecctl.c	5 Oct 2005 13:48:48 -0000	1.17
+++ sbin/veriexecctl/veriexecctl.c	2 Dec 2005 11:27:53 -0000
@@ -30,9 +30,9 @@
  *
  */
 
-#include <sys/ioctl.h>
 #include <sys/param.h>
 #include <sys/queue.h>
+#include <sys/sysctl.h>
 #include <sys/verified_exec.h>
 
 #include <stdio.h>
@@ -45,12 +45,10 @@
 
 #include "veriexecctl.h"
 
-#define	VERIEXEC_DEVICE	"/dev/veriexec"
-
-extern struct veriexec_params params; /* in veriexecctl_parse.y */
+extern struct veriexec_load_params params; /* in veriexecctl_parse.y */
 extern char *filename; /* in veriexecctl_conf.l */
 extern int yynerrs;
-int gfd, verbose = 0, phase;
+int verbose = 0, phase;
 size_t line;
 
 /*
@@ -104,19 +102,25 @@ dev_add(dev_t d)
 static void
 phase1_preload(void)
 {
+	int mib[3];
+	size_t len;
+
 	if (verbose)
 		printf("Phase 1: Calculating hash table sizes:\n");
 
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_VERIEXEC;
+	mib[2] = VERIEXEC_TABLESIZE;
+	len = sizeof(struct veriexec_tablesize_params);
+
 	while (!CIRCLEQ_EMPTY(&params_list)) {
 		struct veriexec_up *vup;
 
 		vup = CIRCLEQ_FIRST(&params_list);
 
-		if (ioctl(gfd, VERIEXEC_TABLESIZE, &(vup->vu_param)) == -1) {
-			if (errno != EEXIST)
-				err(1, "Error in phase 1: Can't "
-				    "set hash table size for device %d",
-				    vup->vu_param.dev);
+		if (sysctl(mib, 3, NULL, NULL, &vup->vu_param, len) == -1) {
+			err(1, "Error in phase 1: Can't set hash table size "
+			    "for device %d", vup->vu_param.dev);
 		}
 
 		if (verbose) {
@@ -131,19 +135,28 @@ phase1_preload(void)
 }
 
 /*
- * Load the fingerprint. Assumes that the fingerprint pseudo-device is
- * opened and the file handle is in gfd.
+ * Load the fingerprint.
  */
 void
 phase2_load(void)
 {
+	int mib[3];
+	size_t len;
+
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_VERIEXEC;
+	mib[2] = VERIEXEC_LOAD;
+	len = sizeof(struct veriexec_load_params);
+
 	/*
 	 * If there's no access type specified, use the default.
 	 */
 	if (!(params.type & (VERIEXEC_DIRECT|VERIEXEC_INDIRECT|VERIEXEC_FILE)))
 		params.type |= VERIEXEC_DIRECT;
-	if (ioctl(gfd, VERIEXEC_LOAD, &params) == -1)
+
+	if (sysctl(mib, 3, NULL, NULL, &params, len) == -1)
 		warn("Cannot load params from `%s'", params.file);
+
 	free(params.fingerprint);
 }
 
@@ -227,18 +240,44 @@ main(int argc, char **argv)
 	argc -= optind;
 	argv += optind;
 
-	if ((gfd = open(VERIEXEC_DEVICE, O_RDWR, 0)) == -1)
-		err(1, "Cannot open `%s'", VERIEXEC_DEVICE);
-
 	/*
 	 * Handle the different commands we can do.
 	 */
 	if (argc == 2 && strcasecmp(argv[0], "load") == 0) {
 		filename = argv[1];
 		fingerprint_load(argv[1]);
+	} else if (argc == 2 && strcasecmp(argv[0], "delete") == 0) {
+		struct veriexec_delete_params dp;
+		struct stat sb;
+		size_t len;
+		int mib[3];
+
+		/* Stat the file to get its inode, device. */
+		if (stat(argv[1], &sb) == -1)
+			err(1, "Can't stat `%s'", argv[1]);
+
+		/*
+		 * If it's a regular file, remove it. If it's a directory,
+		 * remove the entire table. If it's neither, abort.
+		 */
+		if (S_ISDIR(sb.st_mode))
+			dp.ino = 0;
+		else if (S_ISREG(sb.st_mode))
+			dp.ino = sb.st_ino;
+		else
+			errx(1, "`%s' is not a regular file or directory.", argv[1]);
+
+		dp.dev = sb.st_dev;
+
+		mib[0] = CTL_KERN;
+		mib[1] = KERN_VERIEXEC;
+		mib[2] = VERIEXEC_DELETE;
+		len = sizeof(struct veriexec_delete_params);
+
+		if (sysctl(mib, 3, NULL, NULL, &dp, len) == -1)
+			err(1, "Can't delete for `%s'", argv[1]);
 	} else
 		usage();
 
-	(void)close(gfd);
 	return 0;
 }
Index: sbin/veriexecctl/veriexecctl.h
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl.h,v
retrieving revision 1.4
diff -u -p -r1.4 veriexecctl.h
--- sbin/veriexecctl/veriexecctl.h	20 May 2005 20:06:34 -0000	1.4
+++ sbin/veriexecctl/veriexecctl.h	2 Dec 2005 11:27:53 -0000
@@ -35,11 +35,11 @@
 
 CIRCLEQ_HEAD(veriexec_ups, veriexec_up) params_list;
 struct veriexec_up {
-        struct veriexec_sizing_params vu_param;
+        struct veriexec_tablesize_params vu_param;
         CIRCLEQ_ENTRY(veriexec_up) vu_list;
 };
 
-extern int gfd, verbose, phase;
+extern int verbose, phase;
 extern size_t line;
 extern char *infile;
 extern FILE *yyin;
Index: sbin/veriexecctl/veriexecctl_conf.l
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl_conf.l,v
retrieving revision 1.6
diff -u -p -r1.6 veriexecctl_conf.l
--- sbin/veriexecctl/veriexecctl_conf.l	13 Jun 2005 15:18:44 -0000	1.6
+++ sbin/veriexecctl/veriexecctl_conf.l	2 Dec 2005 11:27:53 -0000
@@ -74,7 +74,7 @@ STRING		[0-9a-zA-Z]+
 #.*\n		|
 ^\n		{ line++; }
 
-	/* eol on a line with data. need a call to ioctl, return eol */
+	/* eol on a line with data. need a call to sysctl, return eol */
 \n		{
 			line++;
 			return EOL;
Index: sbin/veriexecctl/veriexecctl_parse.y
===================================================================
RCS file: /cvsroot/src/sbin/veriexecctl/veriexecctl_parse.y,v
retrieving revision 1.13
diff -u -p -r1.13 veriexecctl_parse.y
--- sbin/veriexecctl/veriexecctl_parse.y	5 Oct 2005 13:48:48 -0000	1.13
+++ sbin/veriexecctl/veriexecctl_parse.y	2 Dec 2005 11:27:55 -0000
@@ -32,7 +32,6 @@
  */
 
 #include <sys/param.h>
-#include <sys/ioctl.h>
 #include <sys/statvfs.h>
 #include <sys/mount.h>
 
@@ -45,7 +44,7 @@
 
 #include "veriexecctl.h"
 
-struct veriexec_params params;
+struct veriexec_load_params params;
 static int convert(u_char *, u_char *);
 
 %}
Index: sys/arch/i386/conf/GENERIC_VERIEXEC
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC_VERIEXEC,v
retrieving revision 1.3
diff -u -p -r1.3 GENERIC_VERIEXEC
--- sys/arch/i386/conf/GENERIC_VERIEXEC	29 Jul 2005 14:57:30 -0000	1.3
+++ sys/arch/i386/conf/GENERIC_VERIEXEC	2 Dec 2005 11:27:55 -0000
@@ -13,5 +13,3 @@ options VERIFIED_EXEC_FP_SHA384
 options VERIFIED_EXEC_FP_SHA512
 options VERIFIED_EXEC_FP_SHA1
 options VERIFIED_EXEC_FP_MD5
-#
-pseudo-device veriexec        1
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.745
diff -u -p -r1.745 files
--- sys/conf/files	27 Nov 2005 22:44:35 -0000	1.745
+++ sys/conf/files	2 Dec 2005 11:27:56 -0000
@@ -1113,10 +1113,8 @@ defpseudo ippp:		isdndev, sppp, ifnet
 defpseudo kttcp
 file	dev/kttcp.c			kttcp		needs-flag
 
-# Verified exec fingerprint loader pseudo-device
-defpseudo veriexec
-file	kern/kern_verifiedexec.c	veriexec		needs-flag
-file	dev/verified_exec.c		veriexec		needs-flag
+# Veriexec
+file	kern/kern_verifiedexec.c	verified_exec
 
 # isochronous pseudo device for IEEE 1394, i.LINK or FireWire
 defpseudo fwiso:	ieee1394
Index: sys/conf/majors
===================================================================
RCS file: /cvsroot/src/sys/conf/majors,v
retrieving revision 1.17
diff -u -p -r1.17 majors
--- sys/conf/majors	27 Sep 2005 02:41:10 -0000	1.17
+++ sys/conf/majors	2 Dec 2005 11:27:56 -0000
@@ -19,7 +19,7 @@ device-major	atabus		char 166		atabus
 device-major	drvctl		char 167		drvctl
 device-major	dk		char 168 block 168
 device-major	tap		char 169		tap
-device-major	veriexec	char 170		veriexec
+# 170 - unused (was veriexec)
 device-major	fw		char 171		ieee1394if
 device-major	ucycom		char 172		ucycom
 device-major	gpio		char 173		gpio
Index: sys/kern/init_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v
retrieving revision 1.56
diff -u -p -r1.56 init_sysctl.c
--- sys/kern/init_sysctl.c	8 Oct 2005 06:35:56 -0000	1.56
+++ sys/kern/init_sysctl.c	2 Dec 2005 11:28:00 -0000
@@ -784,6 +784,24 @@ SYSCTL_SETUP(sysctl_kern_setup, "sysctl 
 		       SYSCTL_DESCR("Number of fingerprints on device(s)"),
 		       NULL, 0, NULL, 0,
 		       CTL_KERN, KERN_VERIEXEC, VERIEXEC_COUNT, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_INT, "tablesize",
+		       SYSCTL_DESCR("Initialize a Veriexec hash table"),
+		       sysctl_kern_veriexec, 0, NULL, 0,
+		       CTL_KERN, KERN_VERIEXEC, VERIEXEC_TABLESIZE, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_INT, "load",
+		       SYSCTL_DESCR("Load an entry to the table"),
+		       sysctl_kern_veriexec, 0, NULL, 0,
+		       CTL_KERN, KERN_VERIEXEC, VERIEXEC_LOAD, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_INT, "delete",
+		       SYSCTL_DESCR("Delete an entry from the table"),
+		       sysctl_kern_veriexec, 0, NULL, 0,
+		       CTL_KERN, KERN_VERIEXEC, VERIEXEC_DELETE, CTL_EOL);
 #endif /* VERIFIED_EXEC */
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT,
@@ -2481,36 +2499,94 @@ static int
 sysctl_kern_veriexec(SYSCTLFN_ARGS)
 {
 	int newval, error;
-	int *var = NULL, raise_only = 0;
+	int *var, raise_only;
 	struct sysctlnode node;
 
+	var = NULL;
+	raise_only = 0;
 	node = *rnode;
+	error = 0;
+
+	switch (rnode->sysctl_num) {
+	case VERIEXEC_TABLESIZE:
+	case VERIEXEC_LOAD:
+	case VERIEXEC_DELETE:
+		if (newp == NULL || newlen == 0)
+			return (EOPNOTSUPP);
+
+		if (veriexec_strict > 0) {
+			printf("Veriexec: sysctl_kern_veriexec: Strict mode, "
+			       "modifying tables is not permitted.\n");
+
+	                return (EPERM);
+		}
+	}
 
 	switch (rnode->sysctl_num) {
 	case VERIEXEC_STRICT:
 		raise_only = 1;
 		var = &veriexec_strict;
 		break;
+
 	case VERIEXEC_ALGORITHMS:
 		node.sysctl_data = veriexec_fp_names;
 		node.sysctl_size = strlen(veriexec_fp_names) + 1;
 		return (sysctl_lookup(SYSCTLFN_CALL(&node)));
+
+	case VERIEXEC_TABLESIZE: {
+		struct veriexec_tablesize_params pr;
+
+		error = copyin(newp, &pr, sizeof(pr));
+		if (error)
+			return (error);
+
+		error = veriexec_newtable(&pr, 1);
+
+		break;
+		}
+
+	case VERIEXEC_LOAD: {
+		struct veriexec_load_params pr;
+
+		error = copyin(newp, &pr, sizeof(pr));
+		if (error)
+			return (error);
+
+		error = veriexec_load(&pr);
+
+		break;
+		}
+
+	case VERIEXEC_DELETE: {
+		struct veriexec_delete_params pr;
+
+		error = copyin(newp, &pr, sizeof(pr));
+		if (error)
+			return (error);
+
+		error = veriexec_delete(&pr, 1);
+
+		break;
+		}
+
 	default:
 		return (EINVAL);
 	}
 
-	newval = *var;
+	if (var != NULL) {
+		newval = *var;
 
-	node.sysctl_data = &newval;
-	error = sysctl_lookup(SYSCTLFN_CALL(&node));
-	if (error || newp == NULL) {
-		return (error);
-	}
+		node.sysctl_data = &newval;
+		error = sysctl_lookup(SYSCTLFN_CALL(&node));
+		if (error || newp == NULL) {
+			return (error);
+		}
 
-	if (raise_only && (newval < *var))
-		return (EPERM);
+		if (raise_only && (newval < *var))
+			return (EPERM);
 
-	*var = newval;
+		*var = newval;
+	}
 
 	return (error);
 }
Index: sys/kern/kern_verifiedexec.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_verifiedexec.c,v
retrieving revision 1.46
diff -u -p -r1.46 kern_verifiedexec.c
--- sys/kern/kern_verifiedexec.c	25 Nov 2005 12:02:09 -0000	1.46
+++ sys/kern/kern_verifiedexec.c	2 Dec 2005 11:28:02 -0000
@@ -723,3 +723,218 @@ veriexec_report(const u_char *msg, const
 			    p->p_cred->p_rgid, die ? "]" : "]\n");
 	}
 }
+
+int veriexec_newtable(struct veriexec_tablesize_params *pr, int sysctl_locked)
+{
+	struct lwp *l = curlwp;
+	struct veriexec_hashtbl *tbl;
+	u_char node_name[16];
+	u_long hashmask;
+
+	/* Check for existing table for device. */
+	if (veriexec_tblfind(pr->dev) != NULL)
+		return (EEXIST);
+
+	/* Allocate and initialize a Veriexec hash table. */
+	tbl = malloc(sizeof(*tbl), M_TEMP, M_WAITOK);
+	tbl->hash_size = pr->hash_size;
+	tbl->hash_dev = pr->dev;
+	tbl->hash_count = 0;
+	tbl->hash_tbl = hashinit(pr->hash_size, HASH_LIST, M_TEMP,
+				 M_WAITOK, &hashmask);
+
+	LIST_INSERT_HEAD(&veriexec_tables, tbl, hash_list);
+
+	/*
+	 * We're called after a sysctl_lock(), so we can't just
+	 * call sysctl_createv() and have it working. We unlock
+	 * and then create the node, and to satisfy our caller,
+	 * we sysctl_lock() again.
+	 */
+	snprintf(node_name, sizeof(node_name), "dev_%u",
+		 tbl->hash_dev);
+	if (sysctl_locked)
+		sysctl_unlock(l);
+	sysctl_createv(NULL, 0, &veriexec_count_node, NULL,
+		       CTLFLAG_READONLY, CTLTYPE_QUAD, node_name,
+		       NULL, NULL, 0, &tbl->hash_count, 0,
+		       tbl->hash_dev, CTL_EOL);
+	if (sysctl_locked)
+		sysctl_lock(l, NULL, 0);
+
+	return (0);
+}
+
+int veriexec_load(struct veriexec_load_params *pr)
+{
+	struct proc *p = curlwp->l_proc;
+	struct veriexec_hashtbl *tbl;
+	struct veriexec_hash_entry *e;
+	struct nameidata nid;
+	struct vattr va;
+	int error;
+
+	NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, pr->file, p);
+	error = namei(&nid);
+	if (error)
+		return (error);
+
+	/* Add only regular files. */
+	if (nid.ni_vp->v_type != VREG) {
+		printf("Veriexec: sysctl_kern_veriexec: Not adding \"%s\": "
+		       "Not a regular file.\n", pr->file);
+		vrele(nid.ni_vp);
+		return (EINVAL);
+	}
+
+	/* Get attributes (for the device and inode). */
+	error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
+	if (error)
+		return (error);
+
+	/* Release our reference to the vnode. (namei) */
+	vrele(nid.ni_vp);
+
+	/* Get table for the device. */
+	tbl = veriexec_tblfind(va.va_fsid);
+	if (tbl == NULL)
+		return (EINVAL); /* XXX - better errno? */
+
+	e = veriexec_lookup(va.va_fsid, va.va_fileid);
+	if (e != NULL) {
+		/*
+		 * Duplicate entry means something is wrong in
+		 * the signature file. Just give collision info
+		 * and return.
+		 */
+		printf("veriexec: Duplicate entry. [%s, %ld:%llu] "
+		       "old[type=0x%02x, algorithm=%s], "
+		       "new[type=0x%02x, algorithm=%s] "
+		       "(%s fingerprint)\n",
+		       pr->file, va.va_fsid,
+		       (unsigned long long)va.va_fileid,
+		       e->type, e->ops->type,
+		       pr->type, pr->fp_type,
+		       (((e->ops->hash_len != pr->size) ||
+		        (memcmp(e->fp, pr->fingerprint,
+				min(e->ops->hash_len, pr->size))
+				!= 0)) ? "different" : "same"));
+
+		return (0);
+	}
+
+	e = malloc(sizeof(*e), M_TEMP, M_WAITOK);
+	e->inode = va.va_fileid;
+	e->type = pr->type;
+	e->status = FINGERPRINT_NOTEVAL;
+	e->page_fp = NULL;
+	e->page_fp_status = PAGE_FP_NONE;
+	e->npages = 0;
+	e->last_page_size = 0;
+	if ((e->ops = veriexec_find_ops(pr->fp_type)) == NULL) {
+		free(e, M_TEMP);
+		printf("Veriexec: sysctl_kern_veriexec: Invalid or "
+		       "unknown fingerprint type \"%s\" for file "
+		       "\"%s\" (dev=%ld, inode=%llu)\n",
+		       pr->fp_type, pr->file, va.va_fsid,
+		       (unsigned long long)va.va_fileid);
+		return(EINVAL);
+	}
+
+	/*
+	 * Just a bit of a sanity check - require the size of 
+	 * the fp to be passed in, check this against the expected
+	 * size.  Of course userland could lie deliberately, this
+	 * really only protects against the obvious fumble of
+	 * changing the fp type but not updating the fingerprint
+	 * string.
+	 */   
+	if (e->ops->hash_len != pr->size) {
+		printf("Veriexec: veriexec_load: Inconsistent "
+		       "fingerprint size for type \"%s\" for file "
+		       "\"%s\" (dev=%ld, inode=%llu), size was %u "
+		       "was expecting %zu\n", pr->fp_type,
+		       pr->file, va.va_fsid,
+		       (unsigned long long)va.va_fileid,
+		       pr->size, e->ops->hash_len);
+		free(e, M_TEMP);
+		return(EINVAL);
+	}
+
+	e->fp = malloc(e->ops->hash_len, M_TEMP, M_WAITOK);
+	memcpy(e->fp, pr->fingerprint, e->ops->hash_len);
+	veriexec_report("New entry.", pr->file, &va, NULL,
+			REPORT_VERBOSE_HIGH, REPORT_NOALARM,
+			REPORT_NOPANIC);
+       
+	error = veriexec_hashadd(tbl, e);
+
+	return (0);
+}
+
+int veriexec_delete(struct veriexec_delete_params *pr, int sysctl_locked)
+{
+	/*
+	 * If the inode is zero, we need to remove the entire table.
+	 * Otherwise just remove a single entry.
+	 */
+	if (pr->dev == 0) {
+		if (pr->ino != 0) {
+			struct veriexec_hashtbl *tbl;
+			struct veriexec_hash_entry *vhe;
+
+			tbl = veriexec_tblfind(pr->dev);
+			if (tbl == NULL)
+				return (0);
+
+			vhe = veriexec_lookup(pr->dev, pr->ino);
+			if (vhe != NULL) {
+				if (vhe->fp != NULL)
+					free(vhe->fp, M_TEMP);
+				if (vhe->page_fp != NULL)
+					free(vhe->page_fp, M_TEMP);
+				LIST_REMOVE(vhe, entries);
+				free(vhe, M_TEMP);
+
+				tbl->hash_count--;
+			}
+		}
+	} else {
+		struct lwp *l = curlwp;
+		struct veriexec_hashtbl *tbl;
+		struct veriexec_hashhead *tbl_list;
+		u_long i;
+
+		tbl = veriexec_tblfind(pr->dev);
+		if (tbl == NULL)
+			return (ENOENT);
+
+		tbl_list = tbl->hash_tbl;
+		for (i = 0; i < tbl->hash_size; i++) {
+			while (LIST_FIRST(&tbl_list[i]) != NULL) {
+				struct veriexec_hash_entry *vhe;
+
+				vhe = LIST_FIRST(&tbl_list[i]);
+				if (vhe->fp != NULL)
+					free(vhe->fp, M_TEMP);
+				if (vhe->page_fp != NULL)
+					free(vhe->page_fp, M_TEMP);
+				LIST_REMOVE(vhe, entries);
+				memset(vhe, 0, sizeof(*vhe));
+				free(vhe, M_TEMP);
+			}
+		}
+
+		hashdone(tbl->hash_tbl, M_TEMP);
+		LIST_REMOVE(tbl, hash_list);
+
+		if (sysctl_locked)
+			sysctl_unlock(l);
+		sysctl_destroyv(__UNCONST(veriexec_count_node),
+				pr->dev, CTL_EOL);
+		if (sysctl_locked)
+			sysctl_lock(l, NULL, 0);
+	}
+
+	return (0);
+}
Index: sys/sys/verified_exec.h
===================================================================
RCS file: /cvsroot/src/sys/sys/verified_exec.h,v
retrieving revision 1.21
diff -u -p -r1.21 verified_exec.h
--- sys/sys/verified_exec.h	7 Oct 2005 18:07:46 -0000	1.21
+++ sys/sys/verified_exec.h	2 Dec 2005 11:28:02 -0000
@@ -47,7 +47,7 @@
 /* Max length of the fingerprint type string, including terminating \0 char */
 #define VERIEXEC_TYPE_MAXLEN 9
 
-struct veriexec_params  {
+struct veriexec_load_params  {
 	unsigned char type;
 	unsigned char fp_type[VERIEXEC_TYPE_MAXLEN];
 	char file[MAXPATHLEN];
@@ -55,11 +55,16 @@ struct veriexec_params  {
 	unsigned char *fingerprint;
 };
 
-struct veriexec_sizing_params {
+struct veriexec_tablesize_params {
 	dev_t dev;
 	size_t hash_size;
 };
 
+struct veriexec_delete_params {
+	dev_t dev;
+	ino_t ino;
+};
+
 /*
  * Types of veriexec inodes we can have. Ordered from less strict to
  * most strict -- this is enforced if a duplicate entry is loaded.
@@ -69,14 +74,14 @@ struct veriexec_sizing_params {
 #define VERIEXEC_FILE		0x04 /* Plain file (open) */
 #define	VERIEXEC_UNTRUSTED	0x10 /* Untrusted storage */
 
-#define VERIEXEC_LOAD _IOW('S', 0x1, struct veriexec_params)
-#define VERIEXEC_TABLESIZE _IOW('S', 0x2, struct veriexec_sizing_params)
-
 /* Verified exec sysctl objects. */
 #define	VERIEXEC_VERBOSE	1 /* Verbosity level. */
 #define	VERIEXEC_STRICT		2 /* Strict mode level. */
 #define	VERIEXEC_ALGORITHMS	3 /* Supported hashing algorithms. */
 #define	VERIEXEC_COUNT		4 /* # of fingerprinted files on device. */
+#define	VERIEXEC_LOAD		5 /* Load an entry. */
+#define	VERIEXEC_TABLESIZE	6 /* Initialize a hash table. */
+#define	VERIEXEC_DELETE		7 /* Delete an entry or a table. */
 
 #ifdef _KERNEL
 void	veriexecattach(struct device *, struct device *, void *);
@@ -113,10 +118,6 @@ struct veriexec_fp_ops {
 	LIST_ENTRY(veriexec_fp_ops) entries;
 };
 
-/*
- * list structure definitions - needed in kern_exec.c
- */
-
 /* An entry in the per-device hash table. */
 struct veriexec_hash_entry {
         ino_t         inode;                        /* Inode number. */
@@ -145,11 +146,11 @@ LIST_HEAD(veriexec_hashhead, veriexec_ha
 
 /* Veriexec hash table information. */
 struct veriexec_hashtbl {
-        struct veriexec_hashhead *hash_tbl;
-        size_t hash_size;       /* Number of slots in the table. */
-        dev_t hash_dev;         /* Device ID the hash table refers to. */
+	struct veriexec_hashhead *hash_tbl;
+	size_t hash_size;       /* Number of slots in the table. */
+	dev_t hash_dev;         /* Device ID the hash table refers to. */
 	uint64_t hash_count;	/* # of fingerprinted files in table. */
-        LIST_ENTRY(veriexec_hashtbl) hash_list;
+	LIST_ENTRY(veriexec_hashtbl) hash_list;
 };
 
 /* Global list of hash tables. */
@@ -205,6 +206,9 @@ int veriexec_renamechk(struct vnode *, c
 void veriexec_init_fp_ops(void);
 void veriexec_report(const u_char *, const u_char *, struct vattr *,
 		     struct proc *, int, int, int);
+int veriexec_newtable(struct veriexec_tablesize_params *, int);
+int veriexec_load(struct veriexec_load_params *);
+int veriexec_delete(struct veriexec_delete_params *, int);
 
 #endif /* _KERNEL */
 

--------------080801030804080008050308--