Module Name:    src
Committed By:   mbalmer
Date:           Fri Aug 14 21:17:22 UTC 2009

Modified Files:
        src/distrib/sets/lists/man: mi
        src/share/man/man4: Makefile
        src/sys/conf: files
        src/sys/dev/gpio: files.gpio
        src/sys/secmodel: files.secmodel
        src/sys/sys: Makefile
Added Files:
        src/share/man/man4: gpiolock.4
        src/sys/dev: keylock.c
        src/sys/dev/gpio: gpiolock.c
        src/sys/secmodel/keylock: files.keylock keylock.h secmodel_keylock.c
        src/sys/sys: keylock.h

Log Message:
Add support for multi-position electro-mechanical keylocks.  An example
driver, gpiolock(4), is provided as an example how to interface real hardware.
A new securemodel, securemodel_keylock, is provided to show how this can
be used to tie keylocks to overall system security.  This is experimental
code.  The diff has been on tech-kern for several weeks.

Reviewed by many, kauth(9) integration reviewed by Elad Efrat; approved by
tonnerre@ and t...@.  Thanks to everyone who provided feedback.


To generate a diff of this commit:
cvs rdiff -u -r1.1152 -r1.1153 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.496 -r1.497 src/share/man/man4/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man4/gpiolock.4
cvs rdiff -u -r1.952 -r1.953 src/sys/conf/files
cvs rdiff -u -r0 -r1.1 src/sys/dev/keylock.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/gpio/files.gpio
cvs rdiff -u -r0 -r1.1 src/sys/dev/gpio/gpiolock.c
cvs rdiff -u -r1.2 -r1.3 src/sys/secmodel/files.secmodel
cvs rdiff -u -r0 -r1.1 src/sys/secmodel/keylock/files.keylock \
    src/sys/secmodel/keylock/keylock.h \
    src/sys/secmodel/keylock/secmodel_keylock.c
cvs rdiff -u -r1.118 -r1.119 src/sys/sys/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/sys/keylock.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1152 src/distrib/sets/lists/man/mi:1.1153
--- src/distrib/sets/lists/man/mi:1.1152	Sun Aug  9 08:20:53 2009
+++ src/distrib/sets/lists/man/mi	Fri Aug 14 21:17:21 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1152 2009/08/09 08:20:53 mbalmer Exp $
+# $NetBSD: mi,v 1.1153 2009/08/14 21:17:21 mbalmer Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -939,6 +939,7 @@
 ./usr/share/man/cat4/gpib.0			man-sys-catman		.cat
 ./usr/share/man/cat4/gpio.0			man-sys-catman		.cat
 ./usr/share/man/cat4/gpioiic.0			man-sys-catman		.cat
+./usr/share/man/cat4/gpiolock.0			man-sys-catman		.cat
 ./usr/share/man/cat4/gpioow.0			man-sys-catman		.cat
 ./usr/share/man/cat4/gpiosim.0			man-sys-catman		.cat
 ./usr/share/man/cat4/gre.0			man-sys-catman		.cat
@@ -3548,6 +3549,7 @@
 ./usr/share/man/html4/gpib.html			man-sys-htmlman		html
 ./usr/share/man/html4/gpio.html			man-sys-htmlman		html
 ./usr/share/man/html4/gpioiic.html		man-sys-htmlman		html
+./usr/share/man/html4/gpiolock.html		man-sys-htmlman		html
 ./usr/share/man/html4/gpioow.html		man-sys-htmlman		html
 ./usr/share/man/html4/gpiosim.html		man-sys-htmlman		html
 ./usr/share/man/html4/gre.html			man-sys-htmlman		html
@@ -5937,6 +5939,7 @@
 ./usr/share/man/man4/gpib.4			man-sys-man		.man
 ./usr/share/man/man4/gpio.4			man-sys-man		.man
 ./usr/share/man/man4/gpioiic.4			man-sys-man		.man
+./usr/share/man/man4/gpiolock.4			man-sys-man		.man
 ./usr/share/man/man4/gpioow.4			man-sys-man		.man
 ./usr/share/man/man4/gpiosim.4			man-sys-man		.man
 ./usr/share/man/man4/gre.4			man-sys-man		.man

Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.496 src/share/man/man4/Makefile:1.497
--- src/share/man/man4/Makefile:1.496	Sun Aug  9 08:20:53 2009
+++ src/share/man/man4/Makefile	Fri Aug 14 21:17:21 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.496 2009/08/09 08:20:53 mbalmer Exp $
+#	$NetBSD: Makefile,v 1.497 2009/08/14 21:17:21 mbalmer Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/18/93
 
 MAN=	aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \
@@ -25,8 +25,8 @@
 	esa.4 esiop.4 esm.4 eso.4 etherip.4 exphy.4 \
 	fast_ipsec.4 fd.4 finsio.4 fpa.4 fms.4 fss.4 fxp.4 \
 	gcscaudio.4 gem.4 genfb.4 gentbi.4 geodeide.4 \
-	glxtphy.4 gpib.4 gpio.4 gpiosim.4 gre.4 gphyter.4 gsip.4 hifn.4 hme.4 \
-	hpqlb.4 hptide.4 \
+	glxtphy.4 gpib.4 gpio.4 gpiolock.4 gpiosim.4 gre.4 gphyter.4 gsip.4 \
+	hifn.4 hme.4 hpqlb.4 hptide.4 \
 	ichlpcib.4 ichsmb.4 icmp.4 icp.4 icsphy.4 iee.4 ieee80211.4 \
 	ifmedia.4 igsfb.4 iha.4 iic.4 inet.4 ikphy.4 inphy.4 intersil7170.4 \
 	ioasic.4 ioat.4 iop.4 iophy.4 iopsp.4 ip.4 ipkdb.4 ipmi.4 ipw.4 \

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.952 src/sys/conf/files:1.953
--- src/sys/conf/files:1.952	Sun Aug  9 06:40:10 2009
+++ src/sys/conf/files	Fri Aug 14 21:17:21 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.952 2009/08/09 06:40:10 kiyohara Exp $
+#	$NetBSD: files,v 1.953 2009/08/14 21:17:21 mbalmer Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20090313
@@ -24,6 +24,7 @@
 defflag				PTRACE
 defflag				COREDUMP
 defflag				MODULAR
+defflag				KEYLOCK
 
 defparam			DEFCORENAME
 defparam			HZ
@@ -1371,6 +1372,7 @@
 file	dev/dkwedge/dkwedge_mbr.c	dkwedge_method_mbr
 file	dev/firmload.c			firmload
 file	dev/fss.c			fss			needs-count
+file	dev/keylock.c			keylock
 file	dev/lockstat.c			lockstat		needs-flag
 file	dev/md.c			md			needs-count
 file	dev/midi.c			midi | midibus		needs-flag

Index: src/sys/dev/gpio/files.gpio
diff -u src/sys/dev/gpio/files.gpio:1.7 src/sys/dev/gpio/files.gpio:1.8
--- src/sys/dev/gpio/files.gpio:1.7	Sun Aug  9 08:18:00 2009
+++ src/sys/dev/gpio/files.gpio	Fri Aug 14 21:17:22 2009
@@ -1,4 +1,4 @@
-# $NetBSD: files.gpio,v 1.7 2009/08/09 08:18:00 mbalmer Exp $
+# $NetBSD: files.gpio,v 1.8 2009/08/14 21:17:22 mbalmer Exp $
 
 define	gpio {[offset = -1], [mask = 0]}
 
@@ -19,3 +19,8 @@
 device	gpioow: onewirebus, onewire_bitbang
 attach	gpioow at gpio
 file	dev/gpio/gpioow.c			gpioow
+
+# Keylock
+device	gpiolock: gpiobus
+attach	gpiolock at gpio
+file	dev/gpio/gpiolock.c			gpiolock

Index: src/sys/secmodel/files.secmodel
diff -u src/sys/secmodel/files.secmodel:1.2 src/sys/secmodel/files.secmodel:1.3
--- src/sys/secmodel/files.secmodel:1.2	Wed Nov 21 22:49:07 2007
+++ src/sys/secmodel/files.secmodel	Fri Aug 14 21:17:22 2009
@@ -1,4 +1,4 @@
-# $NetBSD: files.secmodel,v 1.2 2007/11/21 22:49:07 elad Exp $
+# $NetBSD: files.secmodel,v 1.3 2009/08/14 21:17:22 mbalmer Exp $
 
 #
 # Traditional 4.4BSD - Securelevel
@@ -14,3 +14,8 @@
 # Sample overlay model on-top of the traditional one
 #
 include "secmodel/overlay/files.overlay"
+
+#
+# Multi-position keylock
+#
+include "secmodel/keylock/files.keylock"

Index: src/sys/sys/Makefile
diff -u src/sys/sys/Makefile:1.118 src/sys/sys/Makefile:1.119
--- src/sys/sys/Makefile:1.118	Mon Nov 24 16:05:21 2008
+++ src/sys/sys/Makefile	Fri Aug 14 21:17:22 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.118 2008/11/24 16:05:21 joerg Exp $
+#	$NetBSD: Makefile,v 1.119 2009/08/14 21:17:22 mbalmer Exp $
 
 .include <bsd.sys.mk>
 
@@ -17,7 +17,7 @@
 	float_ieee754.h fstypes.h gcq.h gmon.h gpio.h hash.h \
 	ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
 	joystick.h \
-	kcore.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \
+	kcore.h keylock.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \
 	localedef.h lock.h lockf.h lwp.h lwpctl.h \
 	malloc.h mallocvar.h mbuf.h md4.h md5.h midiio.h \
 	mman.h module.h mount.h mqueue.h msg.h msgbuf.h mtio.h mutex.h \

Added files:

Index: src/share/man/man4/gpiolock.4
diff -u /dev/null src/share/man/man4/gpiolock.4:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/share/man/man4/gpiolock.4	Fri Aug 14 21:17:21 2009
@@ -0,0 +1,67 @@
+.\"	$NetBSD: gpiolock.4,v 1.1 2009/08/14 21:17:21 mbalmer Exp $
+.\"
+.\" Copyright (c) 2009 Marc Balmer <m...@msys.ch>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd August 10, 2009
+.Dt GPIOLOCK 4
+.Os
+.Sh NAME
+.Nm gpiolock
+.Nd support for multi-position keylocks attached to GPIO pins
+.Sh SYNOPSIS
+.Cd "gpiolock* at gpio? offset ? mask ?"
+.Cd "gpiolock* at gpio?"
+.Sh DESCRIPTION
+The
+.Nm
+driver allows connecting of multi-position keylocks over GPIO pins.
+The keylock driver registers with a in-kernel keylock supporting system
+and provides
+.Xr kauth 9
+support through an experimental security model.
+The keylock state can be queried using the hw.keylock sysctl variables.
+Only locks with 2-4 positions are currently supported.
+The pin number is specified in the kernel configuration with the
+.Ar offset
+locator.
+The
+.Ar mask
+locator denotes the pins used for the lock (minimum 2, maximum 4 pins are used).
+The
+.Ar offset
+and
+.Ar mask
+can also be specified when
+.Nm
+is attached at runtime using the
+.Dv GPIOATTACH
+.Xr ioctl 2
+on the
+.Xr gpio 4
+device.
+.Sh SEE ALSO
+.Xr gpio 4 ,
+.Xr intro 4 ,
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Nx 5.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Marc Balmer Aq m...@msys.ch .

Index: src/sys/dev/keylock.c
diff -u /dev/null src/sys/dev/keylock.c:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/sys/dev/keylock.c	Fri Aug 14 21:17:22 2009
@@ -0,0 +1,210 @@
+/* $NetBSD: keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
+
+/*
+ * Copyright (c) 2009 Marc Balmer <m...@msys.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_secmodel_keylock.h"
+
+/* Support for multi-position electro-mechanical keylocks */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/keylock.h>
+#include <sys/sysctl.h>
+
+#ifdef secmodel_keylock
+#include <sys/kauth.h>
+#include <secmodel/keylock/keylock.h>
+#endif
+
+static int (*keylock_pos_cb)(void *) = NULL;
+static void *keylock_pos_cb_arg = NULL;
+static int keylock_npos = 0;
+static int keylock_order = 0;
+
+int keylock_pos_sysctl(SYSCTLFN_PROTO);
+int keylock_state_sysctl(SYSCTLFN_PROTO);
+int keylock_order_sysctl(SYSCTLFN_PROTO);
+
+SYSCTL_SETUP(sysctl_keylock_setup, "sysctl keylock setup")
+{
+	const struct sysctlnode *node = NULL;
+
+	sysctl_createv(clog, 0, NULL, NULL,
+	    CTLFLAG_PERMANENT,
+	    CTLTYPE_NODE, "hw", NULL,
+	    NULL, 0, NULL, 0,
+	    CTL_HW, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, &node,
+	    CTLFLAG_PERMANENT,
+	    CTLTYPE_NODE, "keylock",
+	    SYSCTL_DESCR("Keylock state"),
+	    NULL, 0, NULL, 0,
+	    CTL_HW, CTL_CREATE, CTL_EOL);
+
+	if (node == NULL)
+		return;
+
+	sysctl_createv(clog, 0, &node, NULL,
+	    CTLFLAG_PERMANENT | CTLFLAG_READONLY,
+	    CTLTYPE_INT, "pos",
+	    SYSCTL_DESCR("Current keylock position"),
+	    keylock_pos_sysctl, 0, NULL, 0,
+	    CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &node, NULL,
+	    CTLFLAG_PERMANENT | CTLFLAG_READONLY,
+	    CTLTYPE_INT, "npos",
+	    SYSCTL_DESCR("Number of keylock positions"),
+	    NULL, 0, &keylock_npos, 0,
+	    CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &node, NULL,
+	    CTLFLAG_PERMANENT | CTLFLAG_READONLY,
+	    CTLTYPE_INT, "state",
+	    SYSCTL_DESCR("Keylock state"),
+	    keylock_state_sysctl, 0, NULL, 0,
+	    CTL_CREATE, CTL_EOL);
+       sysctl_createv(clog, 0, &node, NULL,
+	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 
+	    CTLTYPE_INT, "order", 
+	    SYSCTL_DESCR("Keylock closedness order"),
+	    keylock_order_sysctl, 0, NULL, 0,
+	    CTL_CREATE, CTL_EOL);
+}
+
+int
+keylock_register(void *cb_arg, int npos, int (*cb)(void *))
+{
+	if (keylock_pos_cb != NULL)
+		return -1;
+
+	keylock_pos_cb = cb;
+	keylock_pos_cb_arg = cb_arg;
+	keylock_npos = npos;
+#ifdef secmodel_keylock
+	secmodel_keylock_start();
+#endif
+	return 0;
+}
+
+void
+keylock_unregister(void *cb_arg, int (*cb)(void *))
+{
+	if (keylock_pos_cb != cb || keylock_pos_cb_arg != cb_arg)
+		return;
+
+#ifdef secmodel_keylock
+	secmodel_keylock_stop();
+#endif
+	keylock_pos_cb = NULL;
+	keylock_pos_cb_arg = NULL;
+	keylock_npos = 0;
+}
+
+int
+keylock_position(void)
+{
+	if (keylock_pos_cb == NULL)
+		return 0;
+
+	return (*keylock_pos_cb)(keylock_pos_cb_arg);
+}
+
+int
+keylock_num_positions(void)
+{
+	return keylock_npos;
+}
+
+int
+keylock_state(void)
+{
+        int pos;
+
+        if (keylock_npos == 0)
+                return KEYLOCK_ABSENT;
+
+        pos = keylock_position();
+        if (pos == 0)
+                return KEYLOCK_TAMPER;
+
+        /*
+	 * XXX How should the intermediate positions be handled?
+	 * At the moment only the ultimate positions are properly handled,
+	 * we need to think about what we do with the intermediate positions.
+	 * For now we return KEYLOCK_SEMIOPEN for them.
+	 */
+        if (pos == 1)
+                return keylock_order == 0 ? KEYLOCK_CLOSE : KEYLOCK_OPEN;
+        else if (pos == keylock_npos)
+                return keylock_order == 0 ? KEYLOCK_OPEN : KEYLOCK_CLOSE;
+        return KEYLOCK_SEMIOPEN;
+}
+
+int
+keylock_pos_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int val;
+
+	node = *rnode;
+	node.sysctl_data = &val;
+
+	val = keylock_position();
+	return sysctl_lookup(SYSCTLFN_CALL(&node));
+}
+
+int
+keylock_state_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int val;
+
+	node = *rnode;
+	node.sysctl_data = &val;
+
+	val = keylock_state();
+	return sysctl_lookup(SYSCTLFN_CALL(&node));
+}
+
+int
+keylock_order_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int val, error;
+
+	node = *rnode;
+	node.sysctl_data = &val;
+
+	val = keylock_order;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+	if (keylock_state() != KEYLOCK_OPEN)
+		return -1;
+
+	keylock_order = val;
+	return 0;
+}
+

Index: src/sys/dev/gpio/gpiolock.c
diff -u /dev/null src/sys/dev/gpio/gpiolock.c:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/sys/dev/gpio/gpiolock.c	Fri Aug 14 21:17:22 2009
@@ -0,0 +1,178 @@
+/* $NetBSD: gpiolock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
+
+/*
+ * Copyright (c) 2009 Marc Balmer <m...@msys.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Driver for multi-position keylocks on GPIO pins
+ */
+
+#include "opt_keylock.h"
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/gpio.h>
+#include <sys/keylock.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#define GPIOLOCK_MAXPINS	4
+#define GPIOLOCK_MINPINS	2
+
+struct gpiolock_softc {
+	void *			sc_gpio;
+	struct gpio_pinmap	sc_map;
+	int			_map[GPIOLOCK_MAXPINS];
+
+	int			sc_npins;
+	int			sc_data;
+	int			sc_dying;
+};
+
+int gpiolock_match(device_t, cfdata_t, void *);
+void gpiolock_attach(device_t, device_t, void *);
+int gpiolock_detach(device_t, int);
+int gpiolock_activate(device_t, enum devact);
+int gpiolock_position(void *);
+
+CFATTACH_DECL_NEW(gpiolock, sizeof(struct gpiolock_softc),
+	gpiolock_match, gpiolock_attach, gpiolock_detach, gpiolock_activate);
+
+extern struct cfdriver gpiolock_cd;
+
+int
+gpiolock_match(device_t parent, cfdata_t cf,
+    void *aux)
+{
+	struct gpio_attach_args *ga = aux;
+	int npins;
+
+	if (strcmp(ga->ga_dvname, cf->cf_name))
+		return 0;
+
+	if (ga->ga_offset == -1)
+		return 0;
+
+	/* Check number of pins */
+	npins = gpio_npins(ga->ga_mask);
+	if (npins < GPIOLOCK_MINPINS || npins > GPIOLOCK_MAXPINS) {
+		aprint_debug("%s: invalid pin mask 0x%02x\n", cf->cf_name,
+		    ga->ga_mask);
+		return 0;
+	}
+
+	return 1;
+}
+
+void
+gpiolock_attach(device_t parent, device_t self, void *aux)
+{
+	struct gpiolock_softc *sc = device_private(self);
+	struct gpio_attach_args *ga = aux;
+	int pin, caps;
+
+	sc->sc_npins = gpio_npins(ga->ga_mask);
+
+	/* Map pins */
+	sc->sc_gpio = ga->ga_gpio;
+	sc->sc_map.pm_map = sc->_map;
+	if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
+	    &sc->sc_map)) {
+		aprint_error(": can't map pins\n");
+		return;
+	}
+
+	/* Configure data pins */
+	for (pin = 0; pin < sc->sc_npins; pin++) {
+		caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, pin);
+		if (!(caps & GPIO_PIN_INPUT)) {
+			aprint_error(": data pin is unable to read input\n");
+			goto fail;
+		}
+		aprint_normal(" [%d]", sc->sc_map.pm_map[pin]);
+		sc->sc_data = GPIO_PIN_INPUT;
+		gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, pin, sc->sc_data);
+	}
+
+#ifdef KEYLOCK
+	/* Register keylock */
+	if (keylock_register(self, sc->sc_npins, gpiolock_position)) {
+		aprint_error(": can't register keylock\n");
+		goto fail;
+	}
+#endif
+	pmf_device_register(self, NULL, NULL);
+
+	aprint_normal("\n");
+	return;
+
+fail:
+	gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+}
+
+int
+gpiolock_detach(device_t self, int flags)
+{
+	struct gpiolock_softc *sc = device_private(self);
+
+	pmf_device_deregister(self);
+#ifdef KEYLOCK
+	keylock_unregister(self, gpiolock_position);
+#endif
+	gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+
+	return 0;
+}
+
+int
+gpiolock_activate(device_t self, enum devact act)
+{
+	struct gpiolock_softc *sc = device_private(self);
+
+	switch (act) {
+	case DVACT_ACTIVATE:
+		return EOPNOTSUPP;
+	case DVACT_DEACTIVATE:
+		sc->sc_dying = 1;
+		break;
+	}
+
+	return 0;
+}
+
+int
+gpiolock_position(void *arg)
+{
+	struct gpiolock_softc *sc = device_private((device_t)arg);
+	int pos, pin;
+
+	for (pos = pin = 0; pin < sc->sc_npins; pin++) {
+		if (gpio_pin_read(sc->sc_gpio, &sc->sc_map, pin) ==
+		    GPIO_PIN_HIGH)
+			pos = pin + 1;
+	}
+	return pos;
+}
+

Index: src/sys/secmodel/keylock/files.keylock
diff -u /dev/null src/sys/secmodel/keylock/files.keylock:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/sys/secmodel/keylock/files.keylock	Fri Aug 14 21:17:22 2009
@@ -0,0 +1,5 @@
+# $NetBSD: files.keylock,v 1.1 2009/08/14 21:17:22 mbalmer Exp $
+
+defflag secmodel_keylock
+
+file	secmodel/keylock/secmodel_keylock.c	secmodel_keylock
Index: src/sys/secmodel/keylock/keylock.h
diff -u /dev/null src/sys/secmodel/keylock/keylock.h:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/sys/secmodel/keylock/keylock.h	Fri Aug 14 21:17:22 2009
@@ -0,0 +1,51 @@
+/* $NetBSD: keylock.h,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
+/*-
+ * Copyright (c) 2009 Marc Balmer <m...@msys.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SECMODEL_KEYLOCK_KEYLOCK_H_
+#define	_SECMODEL_KEYLOCK_KEYLOCK_H_
+
+int secmodel_keylock_sysctl(SYSCTLFN_PROTO);
+
+void secmodel_keylock_init(void);
+void secmodel_keylock_start(void);
+void secmodel_keylock_stop(void);
+
+#if defined(_LKM)
+SYSCTL_SETUP_PROTO(sysctl_security_keylock_setup);
+#endif /* _LKM */
+
+int secmodel_keylock_system_cb(kauth_cred_t, kauth_action_t, void *,
+    void *, void *, void *, void *);
+int secmodel_keylock_process_cb(kauth_cred_t, kauth_action_t, void *,
+    void *, void *, void *, void *);
+int secmodel_keylock_network_cb(kauth_cred_t, kauth_action_t, void *,
+    void *, void *, void *, void *);
+int secmodel_keylock_machdep_cb(kauth_cred_t, kauth_action_t, void *,
+    void *, void *, void *, void *);
+int secmodel_keylock_device_cb(kauth_cred_t, kauth_action_t, void *,
+    void *, void *, void *, void *);
+
+#endif /* !_SECMODEL_KEYLOCK_KEYLOCK_H_ */
Index: src/sys/secmodel/keylock/secmodel_keylock.c
diff -u /dev/null src/sys/secmodel/keylock/secmodel_keylock.c:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/sys/secmodel/keylock/secmodel_keylock.c	Fri Aug 14 21:17:22 2009
@@ -0,0 +1,548 @@
+/* $NetBSD: secmodel_keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
+/*-
+ * Copyright (c) 2009 Marc Balmer <m...@msys.ch>
+ * Copyright (c) 2006 Elad Efrat <e...@netbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains kauth(9) listeners needed to implement an experimental
+ * keylock based security scheme.
+ *
+ * The position of the keylock is a system-global indication on what
+ * operations are allowed or not. It affects all users, including root.
+ *
+ * Rules:
+ *
+ * - If the number of possible keylock positions is 0, assume there is no
+ *   keylock present, do not dissallow any action, i.e. do nothing
+ *
+ * - If the number of possible keylock positions is greater than 0, but the
+ *   current lock position is 0, assume tampering with the lock and forbid
+ *   all actions.
+ *
+ * - If the lock is in the lowest position, assume the system is locked and
+ *   forbid most actions.
+ *
+ * - If the lock is in the highest position, assume the system to be open and
+ *   forbid nothing.
+ *
+ * - If the security.models.keylock.order sysctl is set to a value != 0,
+ *   reverse this order.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/kauth.h>
+
+#include <sys/conf.h>
+#include <sys/keylock.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <sys/vnode.h>
+
+#include <miscfs/specfs/specdev.h>
+
+#include <secmodel/keylock/keylock.h>
+
+static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device;
+
+SYSCTL_SETUP(sysctl_security_keylock_setup,
+    "sysctl security keylock setup")
+{
+	const struct sysctlnode *rnode;
+
+	sysctl_createv(clog, 0, NULL, &rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "security", NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_SECURITY, CTL_EOL);
+
+	sysctl_createv(clog, 0, &rnode, &rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "models", NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &rnode, &rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "keylock",
+		       SYSCTL_DESCR("Keylock security model"),
+		       NULL, 0, NULL, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_STRING, "name", NULL,
+		       NULL, 0, __UNCONST("Keylock"), 0,
+		       CTL_CREATE, CTL_EOL);
+}
+
+void
+secmodel_keylock_init(void)
+{
+}
+
+void
+secmodel_keylock_start(void)
+{
+	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
+	    secmodel_keylock_system_cb, NULL);
+	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
+	    secmodel_keylock_process_cb, NULL);
+	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
+	    secmodel_keylock_network_cb, NULL);
+	l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
+	    secmodel_keylock_machdep_cb, NULL);
+	l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
+	    secmodel_keylock_device_cb, NULL);
+}
+
+void
+secmodel_keylock_stop(void)
+{
+	kauth_unlisten_scope(l_system);
+	kauth_unlisten_scope(l_process);
+	kauth_unlisten_scope(l_network);
+	kauth_unlisten_scope(l_machdep);
+	kauth_unlisten_scope(l_device);
+}
+
+/*
+ * kauth(9) listener
+ *
+ * Security model: Multi-position keylock
+ * Scope: System
+ * Responsibility: Keylock
+ */
+int
+secmodel_keylock_system_cb(kauth_cred_t cred,
+    kauth_action_t action, void *cookie, void *arg0, void *arg1,
+    void *arg2, void *arg3)
+{
+	int result;
+	enum kauth_system_req req;
+	int kstate;
+
+	kstate = keylock_state();
+	if (kstate == KEYLOCK_ABSENT)
+		return KAUTH_RESULT_DEFER;
+	else if (kstate == KEYLOCK_TAMPER)
+		return KAUTH_RESULT_DENY;
+
+	result = KAUTH_RESULT_DEFER;
+	req = (enum kauth_system_req)arg0;
+
+	switch (action) {
+	case KAUTH_SYSTEM_CHSYSFLAGS:
+		if (kstate == KEYLOCK_CLOSE)
+			result = KAUTH_RESULT_DENY;
+		break;
+
+	case KAUTH_SYSTEM_TIME:
+		switch (req) {
+		case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
+			if (kstate == KEYLOCK_CLOSE)
+				result = KAUTH_RESULT_DENY;
+			break;
+
+		case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
+			struct timespec *ts = arg1;
+			struct timespec *delta = arg2;
+
+			/*
+			 * Don't allow the time to be set forward so far it
+			 * will wrap and become negative, thus allowing an
+			 * attacker to bypass the next check below.  The
+			 * cutoff is 1 year before rollover occurs, so even
+			 * if the attacker uses adjtime(2) to move the time
+			 * past the cutoff, it will take a very long time
+			 * to get to the wrap point.
+			 */
+			if (keylock_position() > 1 &&
+			    ((ts->tv_sec > LLONG_MAX - 365*24*60*60) ||
+			     (delta->tv_sec < 0 || delta->tv_nsec < 0)))
+				result = KAUTH_RESULT_DENY;
+			break;
+		}
+		default:
+			break;
+		}
+		break;
+
+	case KAUTH_SYSTEM_MODULE:
+		if (kstate == KEYLOCK_CLOSE)
+			result = KAUTH_RESULT_DENY;
+		break;
+
+	case KAUTH_SYSTEM_MOUNT:
+		switch (req) {
+		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
+			if (kstate == KEYLOCK_CLOSE)
+				result = KAUTH_RESULT_DENY;
+
+			break;
+
+		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
+			if (kstate == KEYLOCK_CLOSE) {
+				struct mount *mp = arg1;
+				u_long flags = (u_long)arg2;
+
+				/*
+				 * Can only degrade from read/write to
+				 * read-only.
+				 */
+				if (flags != (mp->mnt_flag | MNT_RDONLY |
+				    MNT_RELOAD | MNT_FORCE | MNT_UPDATE))
+					result = KAUTH_RESULT_DENY;
+			}
+			break;
+		default:
+			break;
+		}
+
+		break;
+
+	case KAUTH_SYSTEM_SYSCTL:
+		switch (req) {
+		case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
+		case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
+		case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
+			if (kstate == KEYLOCK_CLOSE)
+				result = KAUTH_RESULT_DENY;
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case KAUTH_SYSTEM_SETIDCORE:
+		if (kstate == KEYLOCK_CLOSE)
+			result = KAUTH_RESULT_DENY;
+		break;
+
+	case KAUTH_SYSTEM_DEBUG:
+		switch (req) {
+		case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
+			if (kstate == KEYLOCK_CLOSE)
+				result = KAUTH_RESULT_DENY;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+
+	return result;
+}
+
+/*
+ * kauth(9) listener
+ *
+ * Security model: Multi-position keylock
+ * Scope: Process
+ * Responsibility: Keylock
+ */
+int
+secmodel_keylock_process_cb(kauth_cred_t cred,
+    kauth_action_t action, void *cookie, void *arg0,
+    void *arg1, void *arg2, void *arg3)
+{
+	struct proc *p;
+	int result, kstate;
+
+	kstate = keylock_state();
+	if (kstate == KEYLOCK_ABSENT)
+		return KAUTH_RESULT_DEFER;
+	else if (kstate == KEYLOCK_TAMPER)
+		return KAUTH_RESULT_DENY;
+
+	result = KAUTH_RESULT_DEFER;
+	p = arg0;
+
+	switch (action) {
+	case KAUTH_PROCESS_PROCFS: {
+		enum kauth_process_req req;
+
+		req = (enum kauth_process_req)arg2;
+		switch (req) {
+		case KAUTH_REQ_PROCESS_PROCFS_READ:
+			break;
+
+		case KAUTH_REQ_PROCESS_PROCFS_RW:
+		case KAUTH_REQ_PROCESS_PROCFS_WRITE:
+			if ((p == initproc) && (kstate != KEYLOCK_OPEN))
+				result = KAUTH_RESULT_DENY;
+
+			break;
+		default:
+			break;
+		}
+
+		break;
+		}
+
+	case KAUTH_PROCESS_PTRACE:
+		if ((p == initproc) && (kstate != KEYLOCK_OPEN))
+			result = KAUTH_RESULT_DENY;
+
+		break;
+
+	case KAUTH_PROCESS_CORENAME:
+		if (kstate == KEYLOCK_CLOSE)
+			result = KAUTH_RESULT_DENY;
+		break;
+	}
+	return result;
+}
+
+/*
+ * kauth(9) listener
+ *
+ * Security model: Multi-position keylock
+ * Scope: Network
+ * Responsibility: Keylock
+ */
+int
+secmodel_keylock_network_cb(kauth_cred_t cred,
+    kauth_action_t action, void *cookie, void *arg0,
+    void *arg1, void *arg2, void *arg3)
+{
+	int result, kstate;
+	enum kauth_network_req req;
+
+	kstate = keylock_state();
+	if (kstate == KEYLOCK_ABSENT)
+		return KAUTH_RESULT_DEFER;
+	else if (kstate == KEYLOCK_TAMPER)
+		return KAUTH_RESULT_DENY;
+
+	result = KAUTH_RESULT_DEFER;
+	req = (enum kauth_network_req)arg0;
+
+	switch (action) {
+	case KAUTH_NETWORK_FIREWALL:
+		switch (req) {
+		case KAUTH_REQ_NETWORK_FIREWALL_FW:
+		case KAUTH_REQ_NETWORK_FIREWALL_NAT:
+			if (kstate == KEYLOCK_CLOSE)
+				result = KAUTH_RESULT_DENY;
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	case KAUTH_NETWORK_FORWSRCRT:
+		if (kstate != KEYLOCK_OPEN)
+			result = KAUTH_RESULT_DENY;
+		break;
+	}
+
+	return result;
+}
+
+/*              
+ * kauth(9) listener
+ *
+ * Security model: Multi-position keylock
+ * Scope: Machdep
+ * Responsibility: Keylock
+ */
+int
+secmodel_keylock_machdep_cb(kauth_cred_t cred,
+    kauth_action_t action, void *cookie, void *arg0,
+    void *arg1, void *arg2, void *arg3)
+{
+        int result, kstate;
+
+	kstate = keylock_state();
+	if (kstate == KEYLOCK_ABSENT)
+		return KAUTH_RESULT_DEFER;
+	else if (kstate == KEYLOCK_TAMPER)
+		return KAUTH_RESULT_DENY;
+
+        result = KAUTH_RESULT_DEFER;
+
+        switch (action) {
+	case KAUTH_MACHDEP_IOPERM_SET:
+	case KAUTH_MACHDEP_IOPL:
+		if (kstate != KEYLOCK_OPEN)
+			result = KAUTH_RESULT_DENY;
+		break;
+
+	case KAUTH_MACHDEP_UNMANAGEDMEM:
+		if (kstate != KEYLOCK_OPEN)
+			result = KAUTH_RESULT_DENY;
+		break;
+	}
+
+	return result;
+}
+
+/*
+ * kauth(9) listener
+ *
+ * Security model: Multi-position keylock
+ * Scope: Device 
+ * Responsibility: Keylock
+ */
+int
+secmodel_keylock_device_cb(kauth_cred_t cred,
+    kauth_action_t action, void *cookie, void *arg0,
+    void *arg1, void *arg2, void *arg3)
+{
+	int result, kstate;
+
+	kstate = keylock_state();
+	if (kstate == KEYLOCK_ABSENT)
+		return KAUTH_RESULT_DEFER;
+	else if (kstate == KEYLOCK_TAMPER)
+		return KAUTH_RESULT_DENY;
+
+	result = KAUTH_RESULT_DEFER;
+
+	switch (action) {
+	case KAUTH_DEVICE_RAWIO_SPEC: {
+		struct vnode *vp, *bvp;
+		enum kauth_device_req req;
+		dev_t dev;
+		int d_type;
+
+		req = (enum kauth_device_req)arg0;
+		vp = arg1;
+
+		KASSERT(vp != NULL);
+
+		dev = vp->v_rdev;
+		d_type = D_OTHER;
+		bvp = NULL;
+
+		/* Handle /dev/mem and /dev/kmem. */
+		if ((vp->v_type == VCHR) && iskmemdev(dev)) {
+			switch (req) {
+			case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
+				break;
+
+			case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
+			case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
+				if (kstate != KEYLOCK_OPEN)
+					result = KAUTH_RESULT_DENY;
+				break;
+			default:
+				break;
+			}
+			break;
+		}
+
+		switch (req) {
+		case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
+			break;
+
+		case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
+		case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
+			switch (vp->v_type) {
+			case VCHR: {
+				const struct cdevsw *cdev;
+
+				cdev = cdevsw_lookup(dev);
+				if (cdev != NULL) {
+					dev_t blkdev;
+
+					blkdev = devsw_chr2blk(dev);
+					if (blkdev != NODEV) {
+						vfinddev(blkdev, VBLK, &bvp);
+						if (bvp != NULL)
+							d_type = (cdev->d_flag
+							    & D_TYPEMASK);
+					}
+				}
+
+				break;
+				}
+			case VBLK: {
+				const struct bdevsw *bdev;
+
+				bdev = bdevsw_lookup(dev);
+				if (bdev != NULL)
+					d_type = (bdev->d_flag & D_TYPEMASK);
+
+				bvp = vp;
+
+				break;
+				}
+			default:
+				break;
+			}
+
+			if (d_type != D_DISK)
+				break;
+
+			/*
+			 * XXX: This is bogus. We should be failing the request
+			 * XXX: not only if this specific slice is mounted, but
+			 * XXX: if it's on a disk with any other mounted slice.
+			 */
+			if (vfs_mountedon(bvp) && (kstate != KEYLOCK_OPEN))
+				break;
+
+			if (kstate == KEYLOCK_CLOSE)
+				result = KAUTH_RESULT_DENY;
+
+			break;
+		default:
+			break;
+		}
+		break;
+		}
+
+	case KAUTH_DEVICE_RAWIO_PASSTHRU:
+		if (kstate != KEYLOCK_OPEN) {
+			u_long bits;
+
+			bits = (u_long)arg0;
+
+			KASSERT(bits != 0);
+			KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL)
+			    == 0);
+
+			if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
+				result = KAUTH_RESULT_DENY;
+		}
+		break;
+
+	case KAUTH_DEVICE_GPIO_PINSET:
+		if (kstate != KEYLOCK_OPEN)
+			result = KAUTH_RESULT_DENY;
+		break;
+	default:
+		break;
+	}
+	return result;
+}

Index: src/sys/sys/keylock.h
diff -u /dev/null src/sys/sys/keylock.h:1.1
--- /dev/null	Fri Aug 14 21:17:22 2009
+++ src/sys/sys/keylock.h	Fri Aug 14 21:17:22 2009
@@ -0,0 +1,49 @@
+/* $NetBSD: keylock.h,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
+
+/*
+ * Copyright (c) 2009 Marc Balmer <m...@msys.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_KEYLOCK_H
+#define _SYS_KEYLOCK_H
+
+#define KEYLOCK_ABSENT          0
+#define KEYLOCK_TAMPER          1
+#define KEYLOCK_OPEN            2
+#define KEYLOCK_SEMIOPEN        3
+#define KEYLOCK_SEMICLOSE	4
+#define KEYLOCK_CLOSE           5
+
+#ifdef _KERNEL
+/* Functions for keylock drivers */
+extern int keylock_register(void *, int, int (*)(void *));
+extern void keylock_unregister(void *, int (*)(void *));
+
+/* Functions to query the keylock state */
+extern int keylock_state(void);
+extern int keylock_position(void);
+extern int keylock_num_positions(void);
+#endif
+
+#endif /* _SYS_KEYLOCK_H */

Reply via email to