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 tron@. Thanks to everyone who provided feedback.
This commit is contained in:
parent
eaf64f1b6c
commit
3ab4ce4739
|
@ -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
|
||||
|
|
|
@ -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 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \
|
|||
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 \
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
.\" $NetBSD: gpiolock.4,v 1.1 2009/08/14 21:17:21 mbalmer Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009 Marc Balmer <marc@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 marc@msys.ch .
|
|
@ -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 MBUFTRACE
|
|||
defflag PTRACE
|
||||
defflag COREDUMP
|
||||
defflag MODULAR
|
||||
defflag KEYLOCK
|
||||
|
||||
defparam DEFCORENAME
|
||||
defparam HZ
|
||||
|
@ -1371,6 +1372,7 @@ file dev/dkwedge/dkwedge_gpt.c dkwedge_method_gpt
|
|||
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
|
||||
|
|
|
@ -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 @@ file dev/gpio/gpioiic.c gpioiic
|
|||
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
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/* $NetBSD: gpiolock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Marc Balmer <marc@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;
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
/* $NetBSD: keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Marc Balmer <marc@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;
|
||||
}
|
||||
|
|
@ -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 @@ include "secmodel/bsd44/files.bsd44"
|
|||
# Sample overlay model on-top of the traditional one
|
||||
#
|
||||
include "secmodel/overlay/files.overlay"
|
||||
|
||||
#
|
||||
# Multi-position keylock
|
||||
#
|
||||
include "secmodel/keylock/files.keylock"
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,51 @@
|
|||
/* $NetBSD: keylock.h,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2009 Marc Balmer <marc@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_ */
|
|
@ -0,0 +1,548 @@
|
|||
/* $NetBSD: secmodel_keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2009 Marc Balmer <marc@msys.ch>
|
||||
* Copyright (c) 2006 Elad Efrat <elad@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;
|
||||
}
|
|
@ -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 @@ INCS= acct.h agpio.h aio.h ansi.h ataio.h atomic.h audioio.h \
|
|||
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 \
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* $NetBSD: keylock.h,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Marc Balmer <marc@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 */
|
Loading…
Reference in New Issue