Sun Dec 4 19:25:01 2011 UTC ()
Implement the register/deregister/evaluation API for secmodel(9). It
allows registration of callbacks that can be used later for
cross-secmodel "safe" communication.

When a secmodel wishes to know a property maintained by another
secmodel, it has to submit a request to it so the other secmodel can
proceed to evaluating the request. This is done through the
secmodel_eval(9) call; example:

    bool isroot;
    error = secmodel_eval("org.netbsd.secmodel.suser", "is-root",
        cred, &isroot);
    if (error == 0 && !isroot)
            result = KAUTH_RESULT_DENY;

This one asks the suser module if the credentials are assumed to be root
when evaluated by suser module. If the module is present, it will
respond. If absent, the call will return an error.

Args and command are arbitrarily defined; it's up to the secmodel(9) to
document what it expects.

Typical example is securelevel testing: when someone wants to know
whether securelevel is raised above a certain level or not, the caller
has to request this property to the secmodel_securelevel(9) module.
Given that securelevel module may be absent from system's context (thus
making access to the global "securelevel" variable impossible or
unsafe), this API can cope with this absence and return an error.

We are using secmodel_eval(9) to implement a secmodel_extensions(9)
module, which plugs with the bsd44, suser and securelevel secmodels
to provide the logic behind curtain, usermount and user_set_cpu_affinity
modes, without adding hooks to traditional secmodels. This solves a
real issue with the current secmodel(9) code, as usermount or
user_set_cpu_affinity are not really tied to secmodel_suser(9).

The secmodel_eval(9) is also used to restrict security.models settings
when securelevel is above 0, through the "is-securelevel-above"
evaluation:
- curtain can be enabled any time, but cannot be disabled if
securelevel is above 0.
- usermount/user_set_cpu_affinity can be disabled any time, but cannot
be enabled if securelevel is above 0.

Regarding sysctl(7) entries:
curtain and usermount are now found under security.models.extensions
tree. The security.curtain and vfs.generic.usermount are still
accessible for backwards compat.

Documentation is incoming, I am proof-reading my writings.

Written by elad@, reviewed and tested (anita test + interact for rights
tests) by me. ok elad@.

See also
http://mail-index.netbsd.org/tech-security/2011/11/29/msg000422.html

XXX might consider va0 mapping too.

XXX Having a secmodel(9) specific printf (like aprint_*) for reporting
secmodel(9) errors might be a good idea, but I am not sure on how
to design such a function right now.


(jym)
diff -r1.437 -r1.438 src/sys/kern/init_main.c
diff -r1.65 -r1.66 src/sys/kern/kern_auth.c
diff -r1.85 -r1.86 src/sys/kern/kern_module.c
diff -r1.113 -r1.114 src/sys/rump/librump/rumpkern/Makefile.rumpkern
diff -r1.237 -r1.238 src/sys/rump/librump/rumpkern/rump.c
diff -r1.4 -r1.5 src/sys/secmodel/files.secmodel
diff -r0 -r1.1 src/sys/secmodel/secmodel.c
diff -r0 -r1.4 src/sys/secmodel/secmodel.h
diff -r1.5 -r1.6 src/sys/secmodel/bsd44/bsd44.h
diff -r1.3 -r1.4 src/sys/secmodel/bsd44/files.bsd44
diff -r1.14 -r1.15 src/sys/secmodel/bsd44/secmodel_bsd44.c
diff -r0 -r1.1 src/sys/secmodel/extensions/extensions.h
diff -r0 -r1.1 src/sys/secmodel/extensions/files.extensions
diff -r0 -r1.1 src/sys/secmodel/extensions/secmodel_extensions.c
diff -r1.5 -r1.6 src/sys/secmodel/keylock/secmodel_keylock.c
diff -r1.4 -r1.5 src/sys/secmodel/overlay/overlay.h
diff -r1.11 -r1.12 src/sys/secmodel/overlay/secmodel_overlay.c
diff -r1.22 -r1.23 src/sys/secmodel/securelevel/secmodel_securelevel.c
diff -r1.3 -r1.4 src/sys/secmodel/securelevel/securelevel.h
diff -r1.35 -r1.36 src/sys/secmodel/suser/secmodel_suser.c
diff -r1.1 -r1.2 src/sys/secmodel/suser/suser.h
diff -r1.65 -r1.66 src/sys/sys/kauth.h

cvs diff -r1.437 -r1.438 src/sys/kern/init_main.c (expand / switch to context diff)
--- src/sys/kern/init_main.c 2011/11/19 22:51:25 1.437
+++ src/sys/kern/init_main.c 2011/12/04 19:24:58 1.438
@@ -1,4 +1,4 @@
-/*	$NetBSD: init_main.c,v 1.437 2011/11/19 22:51:25 tls Exp $	*/
+/*	$NetBSD: init_main.c,v 1.438 2011/12/04 19:24:58 jym Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.437 2011/11/19 22:51:25 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.438 2011/12/04 19:24:58 jym Exp $");
 
 #include "opt_ddb.h"
 #include "opt_ipsec.h"
@@ -211,6 +211,8 @@
 #include <sys/pax.h>
 #endif /* PAX_MPROTECT || PAX_SEGVGUARD || PAX_ASLR */
 
+#include <secmodel/secmodel.h>
+
 #include <ufs/ufs/quota.h>
 
 #include <miscfs/genfs/genfs.h>
@@ -345,6 +347,8 @@
 
 	/* Initialize the kernel authorization subsystem. */
 	kauth_init();
+
+	secmodel_init();
 
 	spec_init();
 

cvs diff -r1.65 -r1.66 src/sys/kern/kern_auth.c (expand / switch to context diff)
--- src/sys/kern/kern_auth.c 2009/12/31 02:20:36 1.65
+++ src/sys/kern/kern_auth.c 2011/12/04 19:24:58 1.66
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_auth.c,v 1.65 2009/12/31 02:20:36 elad Exp $ */
+/* $NetBSD: kern_auth.c,v 1.66 2011/12/04 19:24:58 jym Exp $ */
 
 /*-
  * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.65 2009/12/31 02:20:36 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.66 2011/12/04 19:24:58 jym Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -70,11 +70,13 @@
 #include <sys/specificdata.h>
 #include <sys/vnode.h>
 
+#include <secmodel/secmodel.h>
+
 /*
  * Secmodel-specific credentials.
  */
 struct kauth_key {
-	const char *ks_secmodel;	/* secmodel */
+	secmodel_t ks_secmodel;		/* secmodel */
 	specificdata_key_t ks_key;	/* key */
 };
 
@@ -145,8 +147,6 @@
 static kauth_scope_t kauth_builtin_scope_cred;
 static kauth_scope_t kauth_builtin_scope_vnode;
 
-static unsigned int nsecmodels = 0;
-
 static specificdata_domain_t kauth_domain;
 static pool_cache_t kauth_cred_cache;
 
@@ -507,7 +507,7 @@
 }
 
 int
-kauth_register_key(const char *secmodel, kauth_key_t *result)
+kauth_register_key(secmodel_t secmodel, kauth_key_t *result)
 {
 	kauth_key_t k;
 	specificdata_key_t key;
@@ -993,7 +993,7 @@
 	if (r == KAUTH_RESULT_ALLOW)
 		return (0);
 
-	if (!nsecmodels)
+	if (secmodel_nsecmodels() == 0)
 		return (0);
 
 	return (EPERM);
@@ -1140,24 +1140,4 @@
 #endif /* DIAGNOSTIC */
 
 	return (r);
-}
-
-void
-secmodel_register(void)
-{
-	KASSERT(nsecmodels + 1 != 0);
-
-	rw_enter(&kauth_lock, RW_WRITER);
-	nsecmodels++;
-	rw_exit(&kauth_lock);
-}
-
-void
-secmodel_deregister(void)
-{
-	KASSERT(nsecmodels != 0);
-
-	rw_enter(&kauth_lock, RW_WRITER);
-	nsecmodels--;
-	rw_exit(&kauth_lock);
 }

cvs diff -r1.85 -r1.86 src/sys/kern/kern_module.c (expand / switch to context diff)
--- src/sys/kern/kern_module.c 2011/11/28 03:13:31 1.85
+++ src/sys/kern/kern_module.c 2011/12/04 19:24:59 1.86
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_module.c,v 1.85 2011/11/28 03:13:31 jnemeth Exp $	*/
+/*	$NetBSD: kern_module.c,v 1.86 2011/12/04 19:24:59 jym Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.85 2011/11/28 03:13:31 jnemeth Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.86 2011/12/04 19:24:59 jym Exp $");
 
 #define _MODULE_INTERNAL
 
@@ -795,8 +795,6 @@
 	if (modp != NULL) {
 		*modp = mod;
 	}
-	if (mi->mi_class == MODULE_CLASS_SECMODEL)
-		secmodel_register();
 	module_enqueue(mod);
 	return 0;
 }
@@ -1071,9 +1069,6 @@
 		goto fail;
 	}
 
-	if (mi->mi_class == MODULE_CLASS_SECMODEL)
-		secmodel_register();
-
 	/*
 	 * Good, the module loaded successfully.  Put it onto the
 	 * list and add references to its requisite modules.
@@ -1150,8 +1145,6 @@
 		    error);
 		return error;
 	}
-	if (mod->mod_info->mi_class == MODULE_CLASS_SECMODEL)
-		secmodel_deregister();
 	module_count--;
 	TAILQ_REMOVE(&module_list, mod, mod_chain);
 	for (i = 0; i < mod->mod_nrequired; i++) {

cvs diff -r1.113 -r1.114 src/sys/rump/librump/rumpkern/Makefile.rumpkern (expand / switch to context diff)
--- src/sys/rump/librump/rumpkern/Makefile.rumpkern 2011/11/27 00:38:12 1.113
+++ src/sys/rump/librump/rumpkern/Makefile.rumpkern 2011/12/04 19:24:59 1.114
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.rumpkern,v 1.113 2011/11/27 00:38:12 tsutsui Exp $
+#	$NetBSD: Makefile.rumpkern,v 1.114 2011/12/04 19:24:59 jym Exp $
 #
 
 .include "${RUMPTOP}/Makefile.rump"
@@ -12,6 +12,7 @@
 	${RUMPTOP}/../uvm					\
 	${RUMPTOP}/../conf					\
 	${RUMPTOP}/../dev					\
+	${RUMPTOP}/../secmodel					\
 	${RUMPTOP}/../secmodel/suser				\
 	${RUMPTOP}/../compat/common
 
@@ -109,6 +110,7 @@
 SRCS+=	uvm_aobj.c uvm_readahead.c uvm_object.c
 
 # 4.4BSD secmodel.  selection is hardcoded for now
+SRCS+=	secmodel.c
 SRCS+=	secmodel_suser.c
 
 # the funny bit.  this doesn't really belong here, but helps with the

cvs diff -r1.237 -r1.238 src/sys/rump/librump/rumpkern/rump.c (expand / switch to context diff)
--- src/sys/rump/librump/rumpkern/rump.c 2011/12/01 19:15:15 1.237
+++ src/sys/rump/librump/rumpkern/rump.c 2011/12/04 19:24:59 1.238
@@ -1,4 +1,4 @@
-/*	$NetBSD: rump.c,v 1.237 2011/12/01 19:15:15 tls Exp $	*/
+/*	$NetBSD: rump.c,v 1.238 2011/12/04 19:24:59 jym Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.237 2011/12/01 19:15:15 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.238 2011/12/04 19:24:59 jym Exp $");
 
 #include <sys/systm.h>
 #define ELFSIZE ARCH_ELFSIZE
@@ -313,6 +313,8 @@
 	loginit();
 
 	kauth_init();
+
+	secmodel_init();
 
 	/*
 	 * Create the kernel cprng.  Yes, it's currently stubbed out

cvs diff -r1.4 -r1.5 src/sys/secmodel/files.secmodel (expand / switch to context diff)
--- src/sys/secmodel/files.secmodel 2009/10/02 18:50:13 1.4
+++ src/sys/secmodel/files.secmodel 2011/12/04 19:24:59 1.5
@@ -1,5 +1,7 @@
-# $NetBSD: files.secmodel,v 1.4 2009/10/02 18:50:13 elad Exp $
+# $NetBSD: files.secmodel,v 1.5 2011/12/04 19:24:59 jym Exp $
 
+file	secmodel/secmodel.c
+
 #
 # Traditional 4.4BSD - Superuser ("root" as effective user-id 0)
 #
@@ -9,6 +11,11 @@
 # Traditional 4.4BSD - Securelevel
 #
 include "secmodel/securelevel/files.securelevel"
+
+#
+# NetBSD Extensions 
+#
+include "secmodel/extensions/files.extensions"
 
 #
 # Traditional NetBSD (derived from 4.4BSD)

File Added: src/sys/secmodel/secmodel.c
/* $NetBSD: secmodel.c,v 1.1 2011/12/04 19:24:59 jym Exp $ */
/*-
 * Copyright (c) 2011 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.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>

#include <sys/atomic.h>
#include <sys/kauth.h>
#include <sys/kmem.h>
#include <sys/queue.h>
#include <sys/rwlock.h>
#include <secmodel/secmodel.h>
#include <prop/proplib.h>

/* List of secmodels, parameters, and lock. */
static LIST_HEAD(, secmodel_descr) secmodels =
    LIST_HEAD_INITIALIZER(secmodels);
static unsigned int secmodel_copy_cred_on_fork = false;
static krwlock_t secmodels_lock;
static int nsecmodels = 0; /* number of registered secmodels */

static int secmodel_plug(secmodel_t);
static int secmodel_unplug(secmodel_t);

int
secmodel_nsecmodels(void)
{

	return nsecmodels;
}

void
secmodel_init(void)
{

	rw_init(&secmodels_lock);

	secmodel_copy_cred_on_fork = false;
}

/*
 * Register a new secmodel.
 */
int
secmodel_register(secmodel_t *secmodel, const char *id, const char *name,
		  prop_dictionary_t behavior,
		  secmodel_eval_t eval, secmodel_setinfo_t setinfo)
{
	int err;
	secmodel_t sm;

	sm = kmem_alloc(sizeof(*sm), KM_SLEEP);

	sm->sm_id = id;
	sm->sm_name = name;
	sm->sm_behavior = behavior;
	sm->sm_eval = eval;
	sm->sm_setinfo = setinfo;

	err = secmodel_plug(sm);
	if (err == 0) {
		atomic_inc_uint(&nsecmodels);
	} else {
		kmem_free(sm, sizeof(*sm));
		sm = NULL;
	}

	*secmodel = sm;
	return err;
}

/*
 * Deregister a secmodel.
 */
int
secmodel_deregister(secmodel_t sm)
{
	int error;

	error = secmodel_unplug(sm);
	if (error == 0) {
		atomic_dec_uint(&nsecmodels);
		kmem_free(sm, sizeof(*sm));
	}

	return error;
}

/*
 * Lookup a secmodel by its id.
 *
 * Requires "secmodels_lock" handling by the caller.
 */
static secmodel_t
secmodel_lookup(const char *id)
{
	secmodel_t tsm;

	KASSERT(rw_lock_held(&secmodels_lock));

	LIST_FOREACH(tsm, &secmodels, sm_list) {
		if (strcasecmp(tsm->sm_id, id) == 0) {
			return tsm;
		}
	}

	return NULL;
}

/*
 * Adjust system-global secmodel behavior following the addition
 * or removal of a secmodel.
 *
 * Requires "secmodels_lock" to be held by the caller.
 */
static void
secmodel_adjust_behavior(secmodel_t sm, bool added)
{
	bool r, b;

	KASSERT(rw_write_held(&secmodels_lock));

#define	ADJUST_COUNTER(which, added)		\
	do {					\
		if (added) {			\
			(which)++;		\
		} else {			\
			if ((which) > 0)	\
				(which)--;	\
		}				\
	} while (/*CONSTCOND*/0)

	/* Copy credentials on fork? */
	r = prop_dictionary_get_bool(sm->sm_behavior, "copy-cred-on-fork", &b);
	if (r) {
		ADJUST_COUNTER(secmodel_copy_cred_on_fork, added);
	}

#undef ADJUST_COUNTER
}

static int
secmodel_plug(secmodel_t sm)
{
	secmodel_t tsm;
	int error = 0;

	if (sm == NULL) {
		error = EFAULT;
		goto out;
	}

	/* Check if the secmodel is already present. */
	rw_enter(&secmodels_lock, RW_WRITER);
	tsm = secmodel_lookup(sm->sm_id);
	if (tsm != NULL) {
		error = EEXIST;
		goto out;
	}

	/* Add the secmodel. */
	LIST_INSERT_HEAD(&secmodels, sm, sm_list);

	/* Adjust behavior. */
	secmodel_adjust_behavior(sm, true);

 out:
	/* Unlock the secmodels list. */
	rw_exit(&secmodels_lock);

	return error;
}

static int
secmodel_unplug(secmodel_t sm)
{
	secmodel_t tsm;
	int error = 0;

	if (sm == NULL) {
		error = EFAULT;
		goto out;
	}

	/* Make sure the secmodel is present. */
	rw_enter(&secmodels_lock, RW_WRITER);
	tsm = secmodel_lookup(sm->sm_id);
	if (tsm == NULL) {
		error = ENOENT;
		goto out;
	}

	/* Remove the secmodel. */
	LIST_REMOVE(tsm, sm_list);

	/* Adjust behavior. */
	secmodel_adjust_behavior(tsm, false);

 out:
	/* Unlock the secmodels list. */
	rw_exit(&secmodels_lock);

	return error;
}

/* XXX TODO */
int
secmodel_setinfo(const char *id, void *v, int *err)
{

	return EOPNOTSUPP;
}

int
secmodel_eval(const char *id, const char *what, void *arg, void *ret)
{
	secmodel_t sm;
	int error = 0;

	rw_enter(&secmodels_lock, RW_READER);
	sm = secmodel_lookup(id);
	if (sm == NULL) {
		error = EINVAL;
		goto out;
	}

	if (sm->sm_eval == NULL) {
		error = ENOENT;
		goto out;
	}

	if (ret == NULL) {
		error = EFAULT;
		goto out;
	}

	error = sm->sm_eval(what, arg, ret);
	/* pass error from a secmodel(9) callback as a negative value */
	error = -error;

 out:
	rw_exit(&secmodels_lock);

	return error;
}

File Added: src/sys/secmodel/secmodel.h
/* $NetBSD: secmodel.h,v 1.4 2011/12/04 19:24:59 jym Exp $ */
/*-
 * Copyright (c) 2006, 2011 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.
 */

#ifndef _SECMODEL_SECMODEL_H_
#define	_SECMODEL_SECMODEL_H_

#include <prop/proplib.h>

void secmodel_init(void);

/*
 * Functions used for inter-secmodel communication, allowing evaluation
 * or setting information.
 */
typedef int (*secmodel_eval_t)(const char *, void *, void *);
typedef int (*secmodel_setinfo_t)(void *); /* XXX TODO */

/*
 * Secmodel entry.
 */
struct secmodel_descr {
	LIST_ENTRY(secmodel_descr) sm_list;
	const char *sm_id;
	const char *sm_name;
	prop_dictionary_t sm_behavior;
	secmodel_eval_t sm_eval;
	secmodel_setinfo_t sm_setinfo;
};
typedef struct secmodel_descr *secmodel_t;

int secmodel_register(secmodel_t *, const char *, const char *,
    prop_dictionary_t, secmodel_eval_t, secmodel_setinfo_t);
int secmodel_deregister(secmodel_t);
int secmodel_nsecmodels(void);

int secmodel_eval(const char *, const char *, void *, void *);
int secmodel_setinfo(const char *, void *, int *); /* XXX TODO */
#endif /* !_SECMODEL_SECMODEL_H_ */

cvs diff -r1.5 -r1.6 src/sys/secmodel/bsd44/bsd44.h (expand / switch to context diff)
--- src/sys/secmodel/bsd44/bsd44.h 2009/10/02 18:50:13 1.5
+++ src/sys/secmodel/bsd44/bsd44.h 2011/12/04 19:25:00 1.6
@@ -1,4 +1,4 @@
-/* $NetBSD: bsd44.h,v 1.5 2009/10/02 18:50:13 elad Exp $ */
+/* $NetBSD: bsd44.h,v 1.6 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -28,6 +28,9 @@
 
 #ifndef _SECMODEL_BSD44_BSD44_H_
 #define	_SECMODEL_BSD44_BSD44_H_
+
+#define SECMODEL_BSD44_ID   "org.netbsd.secmodel.bsd44"
+#define SECMODEL_BSD44_NAME "Traditional NetBSD: 4.4BSD"
 
 void secmodel_bsd44_init(void);
 void secmodel_bsd44_start(void);

cvs diff -r1.3 -r1.4 src/sys/secmodel/bsd44/files.bsd44 (expand / switch to context diff)
--- src/sys/secmodel/bsd44/files.bsd44 2009/10/02 18:50:13 1.3
+++ src/sys/secmodel/bsd44/files.bsd44 2011/12/04 19:25:00 1.4
@@ -1,6 +1,6 @@
-# $NetBSD: files.bsd44,v 1.3 2009/10/02 18:50:13 elad Exp $
+# $NetBSD: files.bsd44,v 1.4 2011/12/04 19:25:00 jym Exp $
 
 defflag secmodel_bsd44_logic
-defflag secmodel_bsd44 : secmodel_bsd44_logic, secmodel_suser, secmodel_securelevel
+defflag secmodel_bsd44 : secmodel_bsd44_logic, secmodel_suser, secmodel_securelevel, secmodel_extensions
 
 file	secmodel/bsd44/secmodel_bsd44.c			secmodel_bsd44

cvs diff -r1.14 -r1.15 src/sys/secmodel/bsd44/secmodel_bsd44.c (expand / switch to context diff)
--- src/sys/secmodel/bsd44/secmodel_bsd44.c 2011/11/28 22:28:33 1.14
+++ src/sys/secmodel/bsd44/secmodel_bsd44.c 2011/12/04 19:25:00 1.15
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_bsd44.c,v 1.14 2011/11/28 22:28:33 jym Exp $ */
+/* $NetBSD: secmodel_bsd44.c,v 1.15 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44.c,v 1.14 2011/11/28 22:28:33 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44.c,v 1.15 2011/12/04 19:25:00 jym Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -41,9 +41,11 @@
 #include <secmodel/bsd44/bsd44.h>
 #include <secmodel/suser/suser.h>
 #include <secmodel/securelevel/securelevel.h>
+#include <secmodel/extensions/extensions.h>
 
-MODULE(MODULE_CLASS_SECMODEL, secmodel_bsd44, "suser,securelevel");
+MODULE(MODULE_CLASS_SECMODEL, secmodel_bsd44, "suser,securelevel,extensions");
 
+static secmodel_t bsd44_sm;
 static struct sysctllog *sysctl_bsd44_log;
 
 void
@@ -72,7 +74,8 @@
 	sysctl_createv(clog, 0, &rnode, NULL,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "name", NULL,
-		       NULL, 0, __UNCONST("Traditional NetBSD (derived from 4.4BSD)"), 0,
+		       NULL, 0,
+		       __UNCONST(SECMODEL_BSD44_NAME), 0,
 		       CTL_CREATE, CTL_EOL);
 }
 
@@ -101,6 +104,14 @@
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
+
+		error = secmodel_register(&bsd44_sm,
+		    SECMODEL_BSD44_ID, SECMODEL_BSD44_NAME,
+		    NULL, NULL, NULL);
+		if (error != 0)
+			printf("secmodel_bsd44_modcmd::init: "
+			    "secmodel_register returned %d\n", error);
+
 		secmodel_bsd44_init();
 		secmodel_bsd44_start();
 		sysctl_security_bsd44_setup(&sysctl_bsd44_log);
@@ -109,6 +120,11 @@
 	case MODULE_CMD_FINI:
 		sysctl_teardown(&sysctl_bsd44_log);
 		secmodel_bsd44_stop();
+
+		error = secmodel_deregister(bsd44_sm);
+		if (error != 0)
+			printf("secmodel_bsd44_modcmd::fini: "
+			    "secmodel_deregister returned %d\n", error);
 		break;
 
 	default:

File Added: src/sys/secmodel/extensions/extensions.h
/* $NetBSD: extensions.h,v 1.1 2011/12/04 19:25:00 jym Exp $ */
/*-
 * Copyright (c) 2011 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.
 */

#ifndef _SECMODEL_EXTENSIONS_EXTENSIONS_H_
#define	_SECMODEL_EXTENSIONS_EXTENSIONS_H_

#define SECMODEL_EXTENSIONS_ID   "org.netbsd.secmodel.extensions"
#define SECMODEL_EXTENSIONS_NAME "Traditional NetBSD: Extensions"

#endif /* !_SECMODEL_EXTENSIONS_EXTENSIONS_H_ */

File Added: src/sys/secmodel/extensions/files.extensions
# $NetBSD: files.extensions,v 1.1 2011/12/04 19:25:00 jym Exp $

defflag secmodel_extensions

file	secmodel/extensions/secmodel_extensions.c	secmodel_extensions

File Added: src/sys/secmodel/extensions/secmodel_extensions.c
/* $NetBSD: secmodel_extensions.c,v 1.1 2011/12/04 19:25:00 jym Exp $ */
/*-
 * Copyright (c) 2011 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.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.1 2011/12/04 19:25:00 jym Exp $");

#include <sys/types.h>
#include <sys/param.h>
#include <sys/kauth.h>

#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <sys/module.h>

#include <secmodel/secmodel.h>
#include <secmodel/extensions/extensions.h>

MODULE(MODULE_CLASS_SECMODEL, extensions, NULL);

/* static */ int dovfsusermount;
static int curtain;
static int user_set_cpu_affinity;

static kauth_listener_t l_system, l_process, l_network;

static secmodel_t extensions_sm;
static struct sysctllog *extensions_sysctl_log;

static void secmodel_extensions_init(void);
static void secmodel_extensions_start(void);
static void secmodel_extensions_stop(void);

static void sysctl_security_extensions_setup(struct sysctllog **);
static int  sysctl_extensions_user_handler(SYSCTLFN_PROTO);
static int  sysctl_extensions_curtain_handler(SYSCTLFN_PROTO);
static bool is_securelevel_above(int);

static int secmodel_extensions_system_cb(kauth_cred_t, kauth_action_t,
    void *, void *, void *, void *, void *);
static int secmodel_extensions_process_cb(kauth_cred_t, kauth_action_t,
    void *, void *, void *, void *, void *);
static int secmodel_extensions_network_cb(kauth_cred_t, kauth_action_t,
    void *, void *, void *, void *, void *);

static void
sysctl_security_extensions_setup(struct sysctllog **clog)
{
	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, "extensions", NULL,
		       NULL, 0, NULL, 0,
		       CTL_CREATE, CTL_EOL);

	sysctl_createv(clog, 0, &rnode, NULL,
		       CTLFLAG_PERMANENT,
		       CTLTYPE_STRING, "name", NULL,
		       NULL, 0, __UNCONST(SECMODEL_EXTENSIONS_NAME), 0,
		       CTL_CREATE, CTL_EOL);

	sysctl_createv(clog, 0, &rnode, NULL,
		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
		       CTLTYPE_INT, "usermount",
		       SYSCTL_DESCR("Whether unprivileged users may mount "
				    "filesystems"),
		       sysctl_extensions_user_handler, 0, &dovfsusermount, 0,
		       CTL_CREATE, CTL_EOL);

	sysctl_createv(clog, 0, &rnode, NULL,
		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
		       CTLTYPE_INT, "curtain",
		       SYSCTL_DESCR("Curtain information about objects to "\
		       		    "users not owning them."),
		       sysctl_extensions_curtain_handler, 0, &curtain, 0,
		       CTL_CREATE, CTL_EOL);

	sysctl_createv(clog, 0, &rnode, NULL,
		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
		       CTLTYPE_INT, "user_set_cpu_affinity",
		       SYSCTL_DESCR("Whether unprivileged users may control "\
		       		    "CPU affinity."),
		       sysctl_extensions_user_handler, 0,
		       &user_set_cpu_affinity, 0,
		       CTL_CREATE, CTL_EOL);

	/* Compatibility: vfs.generic.usermount */
	sysctl_createv(clog, 0, NULL, NULL,
		       CTLFLAG_PERMANENT,
		       CTLTYPE_NODE, "vfs", NULL,
		       NULL, 0, NULL, 0,
		       CTL_VFS, CTL_EOL);

	sysctl_createv(clog, 0, NULL, NULL,
		       CTLFLAG_PERMANENT,
		       CTLTYPE_NODE, "generic",
		       SYSCTL_DESCR("Non-specific vfs related information"),
		       NULL, 0, NULL, 0,
		       CTL_VFS, VFS_GENERIC, CTL_EOL);

	sysctl_createv(clog, 0, NULL, NULL,
		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
		       CTLTYPE_INT, "usermount",
		       SYSCTL_DESCR("Whether unprivileged users may mount "
				    "filesystems"),
		       sysctl_extensions_user_handler, 0, &dovfsusermount, 0,
		       CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);

	/* Compatibility: security.curtain */
	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, NULL,
		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
		       CTLTYPE_INT, "curtain",
		       SYSCTL_DESCR("Curtain information about objects to "\
		       		    "users not owning them."),
		       sysctl_extensions_curtain_handler, 0, &curtain, 0,
		       CTL_CREATE, CTL_EOL);
}

static int
sysctl_extensions_curtain_handler(SYSCTLFN_ARGS)
{
	struct sysctlnode node;
	int val, error;

	val = *(int *)rnode->sysctl_data;

	node = *rnode;
	node.sysctl_data = &val;

	error = sysctl_lookup(SYSCTLFN_CALL(&node));
	if (error || newp == NULL)
		return error;

	/* shortcut */
	if (val == *(int *)rnode->sysctl_data)
		return 0;

	/* curtain cannot be disabled when securelevel is above 0 */
	if (val == 0 && is_securelevel_above(0)) {
		return EPERM;
	}

	*(int *)rnode->sysctl_data = val;
	return 0;
}

/*
 * Generic sysctl extensions handler for user mount and set CPU affinity
 * rights. Checks the following conditions:
 * - setting value to 0 is always permitted (decrease user rights)
 * - setting value != 0 is not permitted when securelevel is above 0 (increase
 *   user rights).
 */
static int
sysctl_extensions_user_handler(SYSCTLFN_ARGS)
{
	struct sysctlnode node;
	int val, error;

	val = *(int *)rnode->sysctl_data;

	node = *rnode;
	node.sysctl_data = &val;

	error = sysctl_lookup(SYSCTLFN_CALL(&node));
	if (error || newp == NULL)
		return error;

	/* shortcut */
	if (val == *(int *)rnode->sysctl_data)
		return 0;

	/* we cannot grant more rights to users when securelevel is above 0 */
	if (val != 0 && is_securelevel_above(0)) {
		return EPERM;
	}

	*(int *)rnode->sysctl_data = val;
	return 0;
}

/*
 * Query secmodel_securelevel(9) to know whether securelevel is strictly
 * above 'level' or not.
 * Returns true if it is, false otherwise (when securelevel is absent or
 * securelevel is at or below 'level').
 */
static bool
is_securelevel_above(int level)
{
	bool above;
	int error;

	error = secmodel_eval("org.netbsd.secmodel.securelevel",
	    "is-securelevel-above", KAUTH_ARG(level), &above);
	if (error == 0 && above)
		return true;
	else
		return false;
}

static void
secmodel_extensions_init(void)
{

	curtain = 0;
	user_set_cpu_affinity = 0;
}

static void
secmodel_extensions_start(void)
{

	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
	    secmodel_extensions_system_cb, NULL);
	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
	    secmodel_extensions_process_cb, NULL);
	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
	    secmodel_extensions_network_cb, NULL);
}

static void
secmodel_extensions_stop(void)
{

	kauth_unlisten_scope(l_system);
	kauth_unlisten_scope(l_process);
	kauth_unlisten_scope(l_network);
}

static int
extensions_modcmd(modcmd_t cmd, void *arg)
{
	int error = 0;

	switch (cmd) {
	case MODULE_CMD_INIT:
		error = secmodel_register(&extensions_sm,
		    SECMODEL_EXTENSIONS_ID, SECMODEL_EXTENSIONS_NAME,
		    NULL, NULL, NULL);
		if (error != 0)
			printf("extensions_modcmd::init: secmodel_register "
			    "returned %d\n", error);

		secmodel_extensions_init();
		secmodel_extensions_start();
		sysctl_security_extensions_setup(&extensions_sysctl_log);
		break;

	case MODULE_CMD_FINI:
		sysctl_teardown(&extensions_sysctl_log);
		secmodel_extensions_stop();

		error = secmodel_deregister(extensions_sm);
		if (error != 0)
			printf("extensions_modcmd::fini: secmodel_deregister "
			    "returned %d\n", error);

		break;

	case MODULE_CMD_AUTOUNLOAD:
		error = EPERM;
		break;

	default:
		error = ENOTTY;
		break;
	}

	return (error);
}

static int
secmodel_extensions_system_cb(kauth_cred_t cred, kauth_action_t action,
    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
{
	struct mount *mp;
	u_long flags;
	int result;
	enum kauth_system_req req;

	req = (enum kauth_system_req)arg0;
	result = KAUTH_RESULT_DEFER;

	if (action != KAUTH_SYSTEM_MOUNT || dovfsusermount == 0)
		return result;

	switch (req) {
	case KAUTH_REQ_SYSTEM_MOUNT_NEW:
		mp = ((struct vnode *)arg1)->v_mount;
		flags = (u_long)arg2;

		if (usermount_common_policy(mp, flags) == 0)
			result = KAUTH_RESULT_ALLOW;

		break;

	case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
		mp = arg1;

		/* Must own the mount. */
		if (mp->mnt_stat.f_owner == kauth_cred_geteuid(cred))
			result = KAUTH_RESULT_ALLOW;

		break;

	case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
		mp = arg1;
		flags = (u_long)arg2;

		/* Must own the mount. */
		if (mp->mnt_stat.f_owner == kauth_cred_geteuid(cred) &&
		    usermount_common_policy(mp, flags) == 0)
			result = KAUTH_RESULT_ALLOW;

		break;

	default:
		break;
	}

	return (result);
}

static int
secmodel_extensions_process_cb(kauth_cred_t cred, kauth_action_t action,
    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
{
	int result;
	enum kauth_process_req req;

	result = KAUTH_RESULT_DEFER;
	req = (enum kauth_process_req)arg1;

	switch (action) {
	case KAUTH_PROCESS_CANSEE:
		switch (req) {
		case KAUTH_REQ_PROCESS_CANSEE_ARGS:
		case KAUTH_REQ_PROCESS_CANSEE_ENTRY:
		case KAUTH_REQ_PROCESS_CANSEE_OPENFILES:
			if (curtain != 0) {
				struct proc *p = arg0;

				/*
				 * Only process' owner and root can see
				 * through curtain
				 */
				if (!kauth_cred_uidmatch(cred, p->p_cred)) {
					int error;
					bool isroot = false;

					error = secmodel_eval(
					    "org.netbsd.secmodel.suser",
					    "is-root", cred, &isroot);
					if (error == 0 && !isroot)
						result = KAUTH_RESULT_DENY;
				}
			}

			break;

		default:
			break;
		}

		break;

	case KAUTH_PROCESS_SCHEDULER_SETAFFINITY:
		if (user_set_cpu_affinity != 0) {
			result = KAUTH_RESULT_ALLOW;
		}
		break;

	default:
		break;
	}

	return (result);
}

static int
secmodel_extensions_network_cb(kauth_cred_t cred, kauth_action_t action,
    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
{
	int result;
	enum kauth_network_req req;

	result = KAUTH_RESULT_DEFER;
	req = (enum kauth_network_req)arg0;

	if (action != KAUTH_NETWORK_SOCKET ||
	    req != KAUTH_REQ_NETWORK_SOCKET_CANSEE)
		return result;

	if (curtain != 0) {
		struct socket *so = (struct socket *)arg1;

		if (!kauth_cred_uidmatch(cred, so->so_cred)) {
			int error;
			bool isroot = false;

			error = secmodel_eval("org.netbsd.secmodel.suser",
			    "is-root", cred, &isroot);
			if (error == 0 && !isroot)
				result = KAUTH_RESULT_DENY;
		}
	}

	return (result);
}

cvs diff -r1.5 -r1.6 src/sys/secmodel/keylock/secmodel_keylock.c (expand / switch to context diff)
--- src/sys/secmodel/keylock/secmodel_keylock.c 2009/10/19 08:20:21 1.5
+++ src/sys/secmodel/keylock/secmodel_keylock.c 2011/12/04 19:25:00 1.6
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_keylock.c,v 1.5 2009/10/19 08:20:21 cegger Exp $ */
+/* $NetBSD: secmodel_keylock.c,v 1.6 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2009 Marc Balmer <marc@msys.ch>
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.5 2009/10/19 08:20:21 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.6 2011/12/04 19:25:00 jym Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -108,6 +108,12 @@
 void
 secmodel_keylock_init(void)
 {
+	int error = secmodel_register(&keylock_sm,
+	    "org.netbsd.secmodel.keylock",
+	    "NetBSD Security Model: Keylock", NULL, NULL, NULL);
+	if (error != 0)
+		printf("secmodel_keylock_init: secmodel_register "
+		    "returned %d\n", error);
 }
 
 void
@@ -128,11 +134,18 @@
 void
 secmodel_keylock_stop(void)
 {
+	int error;
+
 	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);
+
+	error = secmodel_deregister(&keylock_sm);
+	if (error != 0)
+		printf("secmodel_keylock_stop: secmodel_deregister "
+		    "returned %d\n", error);
 }
 
 /*

cvs diff -r1.4 -r1.5 src/sys/secmodel/overlay/overlay.h (expand / switch to context diff)
--- src/sys/secmodel/overlay/overlay.h 2009/10/02 18:50:13 1.4
+++ src/sys/secmodel/overlay/overlay.h 2011/12/04 19:25:00 1.5
@@ -1,4 +1,4 @@
-/* $NetBSD: overlay.h,v 1.4 2009/10/02 18:50:13 elad Exp $ */
+/* $NetBSD: overlay.h,v 1.5 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -28,6 +28,9 @@
 
 #ifndef _SECMODEL_OVERLAY_OVERLAY_H_
 #define	_SECMODEL_OVERLAY_OVERLAY_H_
+
+#define SECMODEL_OVERLAY_NAME "Overlay security model"
+#define SECMODEL_OVERLAY_ID   "org.netbsd.secmodel.overlay"
 
 void secmodel_overlay_init(void);
 void secmodel_overlay_start(void);

cvs diff -r1.11 -r1.12 src/sys/secmodel/overlay/secmodel_overlay.c (expand / switch to context diff)
--- src/sys/secmodel/overlay/secmodel_overlay.c 2011/11/28 22:28:34 1.11
+++ src/sys/secmodel/overlay/secmodel_overlay.c 2011/12/04 19:25:00 1.12
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_overlay.c,v 1.11 2011/11/28 22:28:34 jym Exp $ */
+/* $NetBSD: secmodel_overlay.c,v 1.12 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_overlay.c,v 1.11 2011/11/28 22:28:34 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_overlay.c,v 1.12 2011/12/04 19:25:00 jym Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -36,8 +36,9 @@
 
 #include <sys/sysctl.h>
 
-#include <secmodel/overlay/overlay.h>
+#include <secmodel/secmodel.h>
 
+#include <secmodel/overlay/overlay.h>
 #include <secmodel/bsd44/bsd44.h>
 #include <secmodel/suser/suser.h>
 #include <secmodel/securelevel/securelevel.h>
@@ -66,6 +67,7 @@
 static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep,
     l_device, l_vnode;
 
+static secmodel_t overlay_sm;
 static struct sysctllog *sysctl_overlay_log;
 
 /*
@@ -145,14 +147,14 @@
 	sysctl_createv(clog, 0, &rnode, &rnode,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_NODE, "overlay",
-		       SYSCTL_DESCR("Overlay security model on-top of bsd44, "),
+		       SYSCTL_DESCR("Overlay security model on-top of bsd44"),
 		       NULL, 0, NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 
 	sysctl_createv(clog, 0, &rnode, NULL,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "name", NULL,
-		       NULL, 0, __UNCONST("Overlay (on-top of bsd44)"), 0,
+		       NULL, 0, __UNCONST(SECMODEL_OVERLAY_NAME), 0,
 		       CTL_CREATE, CTL_EOL);
 }
 
@@ -200,6 +202,13 @@
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
+		error = secmodel_register(&overlay_sm,
+		    SECMODEL_OVERLAY_ID, SECMODEL_OVERLAY_NAME,
+		    NULL, NULL, NULL);
+		if (error != 0)
+			printf("secmodel_overlay_modcmd::init: "
+			    "secmodel_register returned %d\n", error);
+
 		secmodel_overlay_init();
 		secmodel_suser_stop();
 		secmodel_securelevel_stop();
@@ -210,6 +219,11 @@
 	case MODULE_CMD_FINI:
 		sysctl_teardown(&sysctl_overlay_log);
 		secmodel_overlay_stop();
+
+		error = secmodel_deregister(overlay_sm);
+		if (error != 0)
+			printf("secmodel_overlay_modcmd::fini: "
+			    "secmodel_deregister returned %d\n", error);
 		break;
 
 	case MODULE_CMD_AUTOUNLOAD:

cvs diff -r1.22 -r1.23 src/sys/secmodel/securelevel/secmodel_securelevel.c (expand / switch to context diff)
--- src/sys/secmodel/securelevel/secmodel_securelevel.c 2011/11/28 20:57:51 1.22
+++ src/sys/secmodel/securelevel/secmodel_securelevel.c 2011/12/04 19:25:00 1.23
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_securelevel.c,v 1.22 2011/11/28 20:57:51 jym Exp $ */
+/* $NetBSD: secmodel_securelevel.c,v 1.23 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.22 2011/11/28 20:57:51 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.23 2011/12/04 19:25:00 jym Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_insecure.h"
@@ -54,6 +54,7 @@
 
 #include <miscfs/specfs/specdev.h>
 
+#include <secmodel/secmodel.h>
 #include <secmodel/securelevel/securelevel.h>
 
 MODULE(MODULE_CLASS_SECMODEL, securelevel, NULL);
@@ -63,6 +64,7 @@
 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device,
     l_vnode;
 
+static secmodel_t securelevel_sm;
 static struct sysctllog *securelevel_sysctl_log;
 
 /*
@@ -116,7 +118,7 @@
 	sysctl_createv(clog, 0, &rnode, NULL,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "name", NULL,
-		       NULL, 0, __UNCONST("Traditional NetBSD: Securelevel"), 0,
+		       NULL, 0, __UNCONST(SECMODEL_SECURELEVEL_NAME), 0,
 		       CTL_CREATE, CTL_EOL);
 
 	sysctl_createv(clog, 0, &rnode, NULL,
@@ -180,12 +182,36 @@
 }
 
 static int
+securelevel_eval(const char *what, void *arg, void *ret)
+{
+	int error = 0;
+
+	if (strcasecmp(what, "is-securelevel-above") == 0) {
+		int level = (int)(uintptr_t)arg;
+		bool *bp = ret;
+
+		*bp = (securelevel > level);
+	} else {
+		error = ENOENT;
+	}
+
+	return error;
+}
+
+static int
 securelevel_modcmd(modcmd_t cmd, void *arg)
 {
 	int error = 0;
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
+		error = secmodel_register(&securelevel_sm,
+		    SECMODEL_SECURELEVEL_ID, SECMODEL_SECURELEVEL_NAME,
+		    NULL, securelevel_eval, NULL);
+		if (error != 0)
+			printf("securelevel_modcmd::init: secmodel_register "
+			    "returned %d\n", error);
+
 		secmodel_securelevel_init();
 		secmodel_securelevel_start();
 		sysctl_security_securelevel_setup(&securelevel_sysctl_log);
@@ -194,6 +220,12 @@
 	case MODULE_CMD_FINI:
 		sysctl_teardown(&securelevel_sysctl_log);
 		secmodel_securelevel_stop();
+
+		error = secmodel_deregister(securelevel_sm);
+		if (error != 0)
+			printf("securelevel_modcmd::fini: secmodel_deregister "
+			    "returned %d\n", error);
+
 		break;
 
 	case MODULE_CMD_AUTOUNLOAD:

cvs diff -r1.3 -r1.4 src/sys/secmodel/securelevel/securelevel.h (expand / switch to context diff)
--- src/sys/secmodel/securelevel/securelevel.h 2009/10/02 18:50:14 1.3
+++ src/sys/secmodel/securelevel/securelevel.h 2011/12/04 19:25:00 1.4
@@ -1,4 +1,4 @@
-/* $NetBSD: securelevel.h,v 1.3 2009/10/02 18:50:14 elad Exp $ */
+/* $NetBSD: securelevel.h,v 1.4 2011/12/04 19:25:00 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -28,6 +28,9 @@
 
 #ifndef _SECMODEL_SECURELEVEL_SECURELEVEL_H_
 #define	_SECMODEL_SECURELEVEL_SECURELEVEL_H_
+
+#define SECMODEL_SECURELEVEL_ID   "org.netbsd.secmodel.securelevel"
+#define SECMODEL_SECURELEVEL_NAME "Traditional NetBSD: Securelevel"
 
 int secmodel_securelevel_sysctl(SYSCTLFN_PROTO);
 

cvs diff -r1.35 -r1.36 src/sys/secmodel/suser/secmodel_suser.c (expand / switch to context diff)
--- src/sys/secmodel/suser/secmodel_suser.c 2011/11/23 10:47:49 1.35
+++ src/sys/secmodel/suser/secmodel_suser.c 2011/12/04 19:25:01 1.36
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_suser.c,v 1.35 2011/11/23 10:47:49 tls Exp $ */
+/* $NetBSD: secmodel_suser.c,v 1.36 2011/12/04 19:25:01 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.35 2011/11/23 10:47:49 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.36 2011/12/04 19:25:01 jym Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -52,16 +52,15 @@
 #include <sys/proc.h>
 #include <sys/module.h>
 
+#include <secmodel/secmodel.h>
 #include <secmodel/suser/suser.h>
 
 MODULE(MODULE_CLASS_SECMODEL, suser, NULL);
 
-static int secmodel_suser_curtain;
-/* static */ int dovfsusermount;
-
 static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep,
     l_device, l_vnode;
 
+static secmodel_t suser_sm;
 static struct sysctllog *suser_sysctl_log;
 
 void
@@ -90,67 +89,14 @@
 	sysctl_createv(clog, 0, &rnode, NULL,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "name", NULL,
-		       NULL, 0, __UNCONST("Traditional NetBSD: Superuser"), 0,
+		       NULL, 0, __UNCONST(SECMODEL_SUSER_NAME), 0,
 		       CTL_CREATE, CTL_EOL);
-
-	sysctl_createv(clog, 0, &rnode, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "curtain",
-		       SYSCTL_DESCR("Curtain information about objects to "\
-		       		    "users not owning them."),
-		       NULL, 0, &secmodel_suser_curtain, 0,
-		       CTL_CREATE, CTL_EOL);
-
-	sysctl_createv(clog, 0, &rnode, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "usermount",
-		       SYSCTL_DESCR("Whether unprivileged users may mount "
-				    "filesystems"),
-		       NULL, 0, &dovfsusermount, 0,
-		       CTL_CREATE, CTL_EOL);
-
-	/* Compatibility: security.curtain */
-	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, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "curtain",
-		       SYSCTL_DESCR("Curtain information about objects to "\
-		       		    "users not owning them."),
-		       NULL, 0, &secmodel_suser_curtain, 0,
-		       CTL_CREATE, CTL_EOL);
-
-	/* Compatibility: vfs.generic.usermount */
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_NODE, "vfs", NULL,
-		       NULL, 0, NULL, 0,
-		       CTL_VFS, CTL_EOL);
-
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_NODE, "generic",
-		       SYSCTL_DESCR("Non-specific vfs related information"),
-		       NULL, 0, NULL, 0,
-		       CTL_VFS, VFS_GENERIC, CTL_EOL);
-
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "usermount",
-		       SYSCTL_DESCR("Whether unprivileged users may mount "
-				    "filesystems"),
-		       NULL, 0, &dovfsusermount, 0,
-		       CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);
 }
 
 void
 secmodel_suser_init(void)
 {
-	secmodel_suser_curtain = 0;
+
 }
 
 void
@@ -184,13 +130,43 @@
 	kauth_unlisten_scope(l_vnode);
 }
 
+static bool
+suser_isroot(kauth_cred_t cred)
+{
+	return kauth_cred_geteuid(cred) == 0;
+}
+
 static int
+suser_eval(const char *what, void *arg, void *ret)
+{
+	int error = 0;
+
+	if (strcasecmp(what, "is-root") == 0) {
+		kauth_cred_t cred = arg;
+		bool *bp = ret;
+
+		*bp = suser_isroot(cred);
+	} else {
+		error = ENOENT;
+	}
+
+	return error;
+}
+
+static int
 suser_modcmd(modcmd_t cmd, void *arg)
 {
 	int error = 0;
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
+		error = secmodel_register(&suser_sm,
+		    SECMODEL_SUSER_ID, SECMODEL_SUSER_NAME,
+		    NULL, suser_eval, NULL);
+		if (error != 0)
+			printf("suser_modcmd::init: secmodel_register "
+			    "returned %d\n", error);
+
 		secmodel_suser_init();
 		secmodel_suser_start();
 		sysctl_security_suser_setup(&suser_sysctl_log);
@@ -199,6 +175,12 @@
 	case MODULE_CMD_FINI:
 		sysctl_teardown(&suser_sysctl_log);
 		secmodel_suser_stop();
+
+		error = secmodel_deregister(suser_sm);
+		if (error != 0)
+			printf("suser_modcmd::fini: secmodel_deregister "
+			    "returned %d\n", error);
+
 		break;
 
 	case MODULE_CMD_AUTOUNLOAD:
@@ -227,7 +209,7 @@
 	bool isroot;
 	int result;
 
-	isroot = (kauth_cred_geteuid(cred) == 0);
+	isroot = suser_isroot(cred);
 	result = KAUTH_RESULT_DEFER;
 
 	switch (action) {
@@ -243,64 +225,6 @@
 	return (result);
 }
 
-static int
-suser_usermount_policy(kauth_cred_t cred, enum kauth_system_req req, void *arg1,
-    void *arg2)
-{
-	struct mount *mp;
-	u_long flags;
-	int result;
-
-	result = KAUTH_RESULT_DEFER;
-
-	if (!dovfsusermount)
-		return result;
-
-	switch (req) {
-	case KAUTH_REQ_SYSTEM_MOUNT_NEW:
-		mp = ((struct vnode *)arg1)->v_mount;
-		flags= (u_long)arg2;
-
-		if (usermount_common_policy(mp, flags) != 0)
-			break;
-
-		result = KAUTH_RESULT_ALLOW;
-			
-		break;
-
-	case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
-		mp = arg1;
-
-		/* Must own the mount. */
-		if (mp->mnt_stat.f_owner != kauth_cred_geteuid(cred))
-			break;
-
-		result = KAUTH_RESULT_ALLOW;
-
-		break;
-
-	case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
-		mp = arg1;
-		flags = (u_long)arg2;
-
-		/* Must own the mount. */
-		if (mp->mnt_stat.f_owner != kauth_cred_geteuid(cred))
-			break;
-
-		if (usermount_common_policy(mp, flags) != 0)
-			break;
-
-		result = KAUTH_RESULT_ALLOW;
-
-		break;
-
-	default:
-		break;
-	}
-
-	return result;
-}
-
 /*
  * kauth(9) listener
  *
@@ -316,7 +240,7 @@
 	int result;
 	enum kauth_system_req req;
 
-	isroot = (kauth_cred_geteuid(cred) == 0);
+	isroot = suser_isroot(cred);
 	result = KAUTH_RESULT_DEFER;
 	req = (enum kauth_system_req)arg0;
 
@@ -369,8 +293,6 @@
 				break;
 			}
 
-			result = suser_usermount_policy(cred, req, arg1, arg2);
-
 			break;
 
 		default:
@@ -489,7 +411,7 @@
 	bool isroot;
 	int result;
 
-	isroot = (kauth_cred_geteuid(cred) == 0);
+	isroot = suser_isroot(cred);
 	result = KAUTH_RESULT_DEFER;
 	p = arg0;
 
@@ -527,11 +449,6 @@
 				break;
 			}
 
-			if (secmodel_suser_curtain) {
-				if (!kauth_cred_uidmatch(cred, p->p_cred))
-					result = KAUTH_RESULT_DENY;
-			}
-
 			break;
 
 		case KAUTH_REQ_PROCESS_CANSEE_ENV:
@@ -589,7 +506,7 @@
 	int result;
 	enum kauth_network_req req;
 
-	isroot = (kauth_cred_geteuid(cred) == 0);
+	isroot = suser_isroot(cred);
 	result = KAUTH_RESULT_DEFER;
 	req = (enum kauth_network_req)arg0;
 
@@ -749,15 +666,6 @@
 				break;
 			}
 
-			if (secmodel_suser_curtain) {
-				struct socket *so;
-
-				so = (struct socket *)arg1;
-
-				if (!proc_uidmatch(cred, so->so_cred))
-					result = KAUTH_RESULT_DENY;
-			}
-
 			break;
 
 		default:
@@ -788,7 +696,7 @@
         bool isroot;
         int result;
 
-        isroot = (kauth_cred_geteuid(cred) == 0);
+        isroot = suser_isroot(cred);
         result = KAUTH_RESULT_DEFER;
 
         switch (action) {
@@ -827,7 +735,7 @@
         bool isroot;
         int result;
 
-        isroot = (kauth_cred_geteuid(cred) == 0);
+        isroot = suser_isroot(cred);
         result = KAUTH_RESULT_DEFER;
 
 	switch (action) {
@@ -887,7 +795,7 @@
 	bool isroot;
 	int result;
 
-	isroot = (kauth_cred_geteuid(cred) == 0);
+	isroot = suser_isroot(cred);
 	result = KAUTH_RESULT_DEFER;
 
 	if (isroot)

cvs diff -r1.1 -r1.2 src/sys/secmodel/suser/suser.h (expand / switch to context diff)
--- src/sys/secmodel/suser/suser.h 2009/10/02 18:50:13 1.1
+++ src/sys/secmodel/suser/suser.h 2011/12/04 19:25:01 1.2
@@ -1,4 +1,4 @@
-/* $NetBSD: suser.h,v 1.1 2009/10/02 18:50:13 elad Exp $ */
+/* $NetBSD: suser.h,v 1.2 2011/12/04 19:25:01 jym Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
  * All rights reserved.
@@ -28,6 +28,9 @@
 
 #ifndef _SECMODEL_SUSER_SUSER_H_
 #define	_SECMODEL_SUSER_SUSER_H_
+
+#define SECMODEL_SUSER_ID   "org.netbsd.secmodel.suser"
+#define SECMODEL_SUSER_NAME "Traditional NetBSD: Superuser"
 
 void secmodel_suser_init(void);
 void secmodel_suser_start(void);

cvs diff -r1.65 -r1.66 src/sys/sys/kauth.h (expand / switch to context diff)
--- src/sys/sys/kauth.h 2011/11/23 10:47:49 1.65
+++ src/sys/sys/kauth.h 2011/12/04 19:25:01 1.66
@@ -1,4 +1,4 @@
-/* $NetBSD: kauth.h,v 1.65 2011/11/23 10:47:49 tls Exp $ */
+/* $NetBSD: kauth.h,v 1.66 2011/12/04 19:25:01 jym Exp $ */
 
 /*-
  * Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>  
@@ -35,6 +35,8 @@
 #ifndef _SYS_KAUTH_H_
 #define	_SYS_KAUTH_H_
 
+#include <secmodel/secmodel.h> /* for secmodel_t type */
+
 struct uucred;
 struct ki_ucred;
 struct ki_pcred;
@@ -402,7 +404,7 @@
 /* This is for sys_setgroups() */
 int kauth_proc_setgroups(struct lwp *, kauth_cred_t);
 
-int kauth_register_key(const char *, kauth_key_t *);
+int kauth_register_key(secmodel_t, kauth_key_t *);
 int kauth_deregister_key(kauth_key_t);
 void kauth_cred_setdata(kauth_cred_t, kauth_key_t, void *);
 void *kauth_cred_getdata(kauth_cred_t, kauth_key_t);
@@ -419,8 +421,4 @@
 kauth_cred_t kauth_cred_get(void);
 
 void kauth_proc_fork(struct proc *, struct proc *);
-
-void secmodel_register(void);
-void secmodel_deregister(void);
-
 #endif	/* !_SYS_KAUTH_H_ */