NetBSD/sys/kern/kern_auth.c

1164 lines
26 KiB
C
Raw Normal View History

2009-12-31 05:20:36 +03:00
/* $NetBSD: kern_auth.c,v 1.65 2009/12/31 02:20:36 elad Exp $ */
/*-
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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.
*/
2006-05-15 01:12:38 +04:00
/*-
* Copyright (c) 2005, 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
2006-05-15 01:12:38 +04:00
* 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>
2009-12-31 05:20:36 +03:00
__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.65 2009/12/31 02:20:36 elad Exp $");
#include <sys/types.h>
2006-05-15 01:12:38 +04:00
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/proc.h>
#include <sys/ucred.h>
#include <sys/pool.h>
#include <sys/kauth.h>
#include <sys/kmem.h>
2007-02-10 00:55:00 +03:00
#include <sys/rwlock.h>
2009-12-31 05:20:36 +03:00
#include <sys/sysctl.h>
#include <sys/atomic.h>
#include <sys/specificdata.h>
#include <sys/vnode.h>
/*
* Secmodel-specific credentials.
*/
struct kauth_key {
const char *ks_secmodel; /* secmodel */
specificdata_key_t ks_key; /* key */
};
2006-05-15 01:12:38 +04:00
/*
* Credentials.
*
* A subset of this structure is used in kvm(3) (src/lib/libkvm/kvm_proc.c)
* and should be synchronized with this structure when the update is
* relevant.
*/
struct kauth_cred {
/*
* Ensure that the first part of the credential resides in its own
* cache line. Due to sharing there aren't many kauth_creds in a
* typical system, but the reference counts change very often.
* Keeping it seperate from the rest of the data prevents false
* sharing between CPUs.
*/
u_int cr_refcnt; /* reference count */
#if COHERENCY_UNIT > 4
uint8_t cr_pad[COHERENCY_UNIT - 4];
#endif
uid_t cr_uid; /* user id */
uid_t cr_euid; /* effective user id */
uid_t cr_svuid; /* saved effective user id */
gid_t cr_gid; /* group id */
gid_t cr_egid; /* effective group id */
gid_t cr_svgid; /* saved effective group id */
u_int cr_ngroups; /* number of groups */
gid_t cr_groups[NGROUPS]; /* group memberships */
specificdata_reference cr_sd; /* specific data */
};
2006-05-15 01:12:38 +04:00
/*
* Listener.
*/
struct kauth_listener {
kauth_scope_callback_t func; /* callback */
kauth_scope_t scope; /* scope backpointer */
u_int refcnt; /* reference count */
2006-05-15 01:12:38 +04:00
SIMPLEQ_ENTRY(kauth_listener) listener_next; /* listener list */
};
/*
* Scope.
*/
struct kauth_scope {
const char *id; /* scope name */
void *cookie; /* user cookie */
u_int nlisteners; /* # of listeners */
2006-05-15 01:12:38 +04:00
SIMPLEQ_HEAD(, kauth_listener) listenq; /* listener list */
SIMPLEQ_ENTRY(kauth_scope) next_scope; /* scope list */
};
static int kauth_cred_hook(kauth_cred_t, kauth_action_t, void *, void *);
2006-05-15 01:12:38 +04:00
/* List of scopes and its lock. */
static SIMPLEQ_HEAD(, kauth_scope) scope_list =
SIMPLEQ_HEAD_INITIALIZER(scope_list);
2006-05-15 01:12:38 +04:00
/* Built-in scopes: generic, process. */
static kauth_scope_t kauth_builtin_scope_generic;
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
static kauth_scope_t kauth_builtin_scope_system;
2006-05-15 01:12:38 +04:00
static kauth_scope_t kauth_builtin_scope_process;
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
static kauth_scope_t kauth_builtin_scope_network;
static kauth_scope_t kauth_builtin_scope_machdep;
static kauth_scope_t kauth_builtin_scope_device;
static kauth_scope_t kauth_builtin_scope_cred;
static kauth_scope_t kauth_builtin_scope_vnode;
2006-05-15 01:12:38 +04:00
static unsigned int nsecmodels = 0;
static specificdata_domain_t kauth_domain;
static pool_cache_t kauth_cred_cache;
2009-12-31 05:20:36 +03:00
2007-02-10 00:55:00 +03:00
krwlock_t kauth_lock;
2006-05-15 01:12:38 +04:00
/* Allocate new, empty kauth credentials. */
kauth_cred_t
2006-05-23 04:43:30 +04:00
kauth_cred_alloc(void)
{
2006-05-15 01:12:38 +04:00
kauth_cred_t cred;
cred = pool_cache_get(kauth_cred_cache, PR_WAITOK);
2006-05-15 01:12:38 +04:00
cred->cr_refcnt = 1;
cred->cr_uid = 0;
cred->cr_euid = 0;
cred->cr_svuid = 0;
cred->cr_gid = 0;
cred->cr_egid = 0;
cred->cr_svgid = 0;
cred->cr_ngroups = 0;
specificdata_init(kauth_domain, &cred->cr_sd);
kauth_cred_hook(cred, KAUTH_CRED_INIT, NULL, NULL);
2006-05-15 01:12:38 +04:00
return (cred);
}
/* Increment reference count to cred. */
void
kauth_cred_hold(kauth_cred_t cred)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt > 0);
2006-05-15 01:12:38 +04:00
atomic_inc_uint(&cred->cr_refcnt);
2006-05-15 01:12:38 +04:00
}
/* Decrease reference count to cred. If reached zero, free it. */
void
2006-05-23 04:43:30 +04:00
kauth_cred_free(kauth_cred_t cred)
{
2006-05-15 01:12:38 +04:00
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt > 0);
2009-08-16 15:01:12 +04:00
ASSERT_SLEEPABLE();
2006-05-15 01:12:38 +04:00
2007-11-29 22:50:28 +03:00
if (atomic_dec_uint_nv(&cred->cr_refcnt) > 0)
return;
2006-05-15 01:12:38 +04:00
kauth_cred_hook(cred, KAUTH_CRED_FREE, NULL, NULL);
specificdata_fini(kauth_domain, &cred->cr_sd);
pool_cache_put(kauth_cred_cache, cred);
2006-05-15 01:12:38 +04:00
}
static void
kauth_cred_clone1(kauth_cred_t from, kauth_cred_t to, bool copy_groups)
2006-05-15 01:12:38 +04:00
{
KASSERT(from != NULL);
KASSERT(to != NULL);
KASSERT(from->cr_refcnt > 0);
2006-05-15 01:12:38 +04:00
to->cr_uid = from->cr_uid;
to->cr_euid = from->cr_euid;
to->cr_svuid = from->cr_svuid;
to->cr_gid = from->cr_gid;
to->cr_egid = from->cr_egid;
to->cr_svgid = from->cr_svgid;
if (copy_groups) {
to->cr_ngroups = from->cr_ngroups;
memcpy(to->cr_groups, from->cr_groups, sizeof(to->cr_groups));
}
kauth_cred_hook(from, KAUTH_CRED_COPY, to, NULL);
2006-05-15 01:12:38 +04:00
}
void
kauth_cred_clone(kauth_cred_t from, kauth_cred_t to)
{
kauth_cred_clone1(from, to, true);
}
2006-05-15 01:12:38 +04:00
/*
* Duplicate cred and return a new kauth_cred_t.
*/
kauth_cred_t
kauth_cred_dup(kauth_cred_t cred)
{
kauth_cred_t new_cred;
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt > 0);
2006-05-15 01:12:38 +04:00
new_cred = kauth_cred_alloc();
kauth_cred_clone(cred, new_cred);
return (new_cred);
}
/*
* Similar to crcopy(), only on a kauth_cred_t.
* XXX: Is this even needed? [kauth_cred_copy]
*/
kauth_cred_t
kauth_cred_copy(kauth_cred_t cred)
{
kauth_cred_t new_cred;
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt > 0);
2006-05-15 01:12:38 +04:00
/* If the provided credentials already have one reference, use them. */
if (cred->cr_refcnt == 1)
return (cred);
new_cred = kauth_cred_alloc();
kauth_cred_clone(cred, new_cred);
kauth_cred_free(cred);
return (new_cred);
}
void
kauth_proc_fork(struct proc *parent, struct proc *child)
{
2007-02-10 00:55:00 +03:00
mutex_enter(parent->p_lock);
kauth_cred_hold(parent->p_cred);
child->p_cred = parent->p_cred;
mutex_exit(parent->p_lock);
2007-02-10 00:55:00 +03:00
/* XXX: relies on parent process stalling during fork() */
kauth_cred_hook(parent->p_cred, KAUTH_CRED_FORK, parent,
child);
}
2006-05-15 01:12:38 +04:00
uid_t
kauth_cred_getuid(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_uid);
}
uid_t
kauth_cred_geteuid(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_euid);
}
uid_t
kauth_cred_getsvuid(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_svuid);
}
gid_t
kauth_cred_getgid(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_gid);
}
gid_t
kauth_cred_getegid(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_egid);
}
gid_t
kauth_cred_getsvgid(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_svgid);
}
void
kauth_cred_setuid(kauth_cred_t cred, uid_t uid)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
cred->cr_uid = uid;
}
void
kauth_cred_seteuid(kauth_cred_t cred, uid_t uid)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
cred->cr_euid = uid;
}
void
kauth_cred_setsvuid(kauth_cred_t cred, uid_t uid)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
cred->cr_svuid = uid;
}
void
kauth_cred_setgid(kauth_cred_t cred, gid_t gid)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
cred->cr_gid = gid;
}
void
kauth_cred_setegid(kauth_cred_t cred, gid_t gid)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
cred->cr_egid = gid;
}
void
kauth_cred_setsvgid(kauth_cred_t cred, gid_t gid)
{
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
cred->cr_svgid = gid;
}
/* Checks if gid is a member of the groups in cred. */
int
kauth_cred_ismember_gid(kauth_cred_t cred, gid_t gid, int *resultp)
{
2009-04-05 15:48:02 +04:00
uint32_t i;
2006-05-15 01:12:38 +04:00
KASSERT(cred != NULL);
KASSERT(resultp != NULL);
*resultp = 0;
for (i = 0; i < cred->cr_ngroups; i++)
if (cred->cr_groups[i] == gid) {
*resultp = 1;
break;
}
return (0);
}
u_int
2006-05-15 01:12:38 +04:00
kauth_cred_ngroups(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_ngroups);
}
/*
* Return the group at index idx from the groups in cred.
*/
gid_t
kauth_cred_group(kauth_cred_t cred, u_int idx)
2006-05-15 01:12:38 +04:00
{
KASSERT(cred != NULL);
KASSERT(idx < cred->cr_ngroups);
return (cred->cr_groups[idx]);
}
/* XXX elad: gmuid is unused for now. */
int
kauth_cred_setgroups(kauth_cred_t cred, const gid_t *grbuf, size_t len,
2007-09-23 20:00:08 +04:00
uid_t gmuid, enum uio_seg seg)
2006-05-15 01:12:38 +04:00
{
int error = 0;
2006-05-15 01:12:38 +04:00
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt == 1);
2006-05-15 01:12:38 +04:00
2008-08-15 05:31:02 +04:00
if (len > __arraycount(cred->cr_groups))
return EINVAL;
if (len) {
2007-09-23 20:00:08 +04:00
if (seg == UIO_SYSSPACE) {
memcpy(cred->cr_groups, grbuf,
len * sizeof(cred->cr_groups[0]));
2007-09-23 20:00:08 +04:00
} else {
error = copyin(grbuf, cred->cr_groups,
len * sizeof(cred->cr_groups[0]));
if (error != 0)
len = 0;
}
}
2006-05-15 01:12:38 +04:00
memset(cred->cr_groups + len, 0xff,
sizeof(cred->cr_groups) - (len * sizeof(cred->cr_groups[0])));
cred->cr_ngroups = len;
return error;
}
/* This supports sys_setgroups() */
int
kauth_proc_setgroups(struct lwp *l, kauth_cred_t ncred)
{
kauth_cred_t cred;
int error;
/*
* At this point we could delete duplicate groups from ncred,
* and plausibly sort the list - but in general the later is
* a bad idea.
*/
proc_crmod_enter();
/* Maybe we should use curproc here ? */
cred = l->l_proc->p_cred;
kauth_cred_clone1(cred, ncred, false);
error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
l->l_proc, NULL, NULL, NULL);
if (error != 0) {
proc_crmod_leave(cred, ncred, false);
return error;
}
/* Broadcast our credentials to the process and other LWPs. */
proc_crmod_leave(ncred, cred, true);
return 0;
}
2006-05-15 01:12:38 +04:00
int
kauth_cred_getgroups(kauth_cred_t cred, gid_t *grbuf, size_t len,
2007-09-23 20:00:08 +04:00
enum uio_seg seg)
2006-05-15 01:12:38 +04:00
{
KASSERT(cred != NULL);
if (len > cred->cr_ngroups)
return EINVAL;
2006-05-15 01:12:38 +04:00
2007-09-23 20:00:08 +04:00
if (seg == UIO_USERSPACE)
return copyout(cred->cr_groups, grbuf, sizeof(*grbuf) * len);
memcpy(grbuf, cred->cr_groups, sizeof(*grbuf) * len);
2006-05-15 01:12:38 +04:00
return 0;
}
int
kauth_register_key(const char *secmodel, kauth_key_t *result)
{
kauth_key_t k;
specificdata_key_t key;
int error;
KASSERT(result != NULL);
error = specificdata_key_create(kauth_domain, &key, NULL);
if (error)
return (error);
k = kmem_alloc(sizeof(*k), KM_SLEEP);
k->ks_secmodel = secmodel;
k->ks_key = key;
*result = k;
return (0);
}
int
kauth_deregister_key(kauth_key_t key)
{
KASSERT(key != NULL);
specificdata_key_delete(kauth_domain, key->ks_key);
kmem_free(key, sizeof(*key));
return (0);
}
void *
kauth_cred_getdata(kauth_cred_t cred, kauth_key_t key)
{
KASSERT(cred != NULL);
KASSERT(key != NULL);
return (specificdata_getspecific(kauth_domain, &cred->cr_sd,
key->ks_key));
}
void
kauth_cred_setdata(kauth_cred_t cred, kauth_key_t key, void *data)
{
KASSERT(cred != NULL);
KASSERT(key != NULL);
specificdata_setspecific(kauth_domain, &cred->cr_sd, key->ks_key, data);
}
2006-05-15 01:12:38 +04:00
/*
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
* Match uids in two credentials.
2006-05-15 01:12:38 +04:00
*/
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
int
2006-05-15 01:12:38 +04:00
kauth_cred_uidmatch(kauth_cred_t cred1, kauth_cred_t cred2)
{
KASSERT(cred1 != NULL);
KASSERT(cred2 != NULL);
if (cred1->cr_uid == cred2->cr_uid ||
cred1->cr_euid == cred2->cr_uid ||
cred1->cr_uid == cred2->cr_euid ||
cred1->cr_euid == cred2->cr_euid)
return (1);
return (0);
}
u_int
2006-05-15 01:12:38 +04:00
kauth_cred_getrefcnt(kauth_cred_t cred)
{
KASSERT(cred != NULL);
return (cred->cr_refcnt);
}
/*
* Convert userland credentials (struct uucred) to kauth_cred_t.
* XXX: For NFS & puffs
2006-05-15 01:12:38 +04:00
*/
void
kauth_uucred_to_cred(kauth_cred_t cred, const struct uucred *uuc)
{
2006-05-15 01:12:38 +04:00
KASSERT(cred != NULL);
KASSERT(uuc != NULL);
2006-05-15 01:12:38 +04:00
cred->cr_refcnt = 1;
cred->cr_uid = uuc->cr_uid;
cred->cr_euid = uuc->cr_uid;
cred->cr_svuid = uuc->cr_uid;
cred->cr_gid = uuc->cr_gid;
cred->cr_egid = uuc->cr_gid;
cred->cr_svgid = uuc->cr_gid;
cred->cr_ngroups = min(uuc->cr_ngroups, NGROUPS);
kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups),
cred->cr_ngroups, -1, UIO_SYSSPACE);
2006-05-15 01:12:38 +04:00
}
/*
* Convert kauth_cred_t to userland credentials (struct uucred).
* XXX: For NFS & puffs
*/
void
kauth_cred_to_uucred(struct uucred *uuc, const kauth_cred_t cred)
{
KASSERT(cred != NULL);
KASSERT(uuc != NULL);
int ng;
ng = min(cred->cr_ngroups, NGROUPS);
uuc->cr_uid = cred->cr_euid;
uuc->cr_gid = cred->cr_egid;
uuc->cr_ngroups = ng;
kauth_cred_getgroups(cred, uuc->cr_groups, ng, UIO_SYSSPACE);
}
2006-05-15 01:12:38 +04:00
/*
* Compare kauth_cred_t and uucred credentials.
* XXX: Modelled after crcmp() for NFS.
*/
int
kauth_cred_uucmp(kauth_cred_t cred, const struct uucred *uuc)
{
KASSERT(cred != NULL);
KASSERT(uuc != NULL);
if (cred->cr_euid == uuc->cr_uid &&
cred->cr_egid == uuc->cr_gid &&
2009-04-05 15:48:02 +04:00
cred->cr_ngroups == (uint32_t)uuc->cr_ngroups) {
2006-05-15 01:12:38 +04:00
int i;
/* Check if all groups from uuc appear in cred. */
for (i = 0; i < uuc->cr_ngroups; i++) {
int ismember;
ismember = 0;
if (kauth_cred_ismember_gid(cred, uuc->cr_groups[i],
&ismember) != 0 || !ismember)
return (1);
2006-05-15 01:12:38 +04:00
}
return (0);
2006-05-15 01:12:38 +04:00
}
return (1);
2006-05-15 01:12:38 +04:00
}
/*
* Make a struct ucred out of a kauth_cred_t. For compatibility.
2006-05-15 01:12:38 +04:00
*/
void
kauth_cred_toucred(kauth_cred_t cred, struct ki_ucred *uc)
2006-05-15 01:12:38 +04:00
{
KASSERT(cred != NULL);
KASSERT(uc != NULL);
uc->cr_ref = cred->cr_refcnt;
2006-05-15 01:12:38 +04:00
uc->cr_uid = cred->cr_euid;
uc->cr_gid = cred->cr_egid;
2008-08-15 05:31:02 +04:00
uc->cr_ngroups = min(cred->cr_ngroups, __arraycount(uc->cr_groups));
2006-05-15 01:12:38 +04:00
memcpy(uc->cr_groups, cred->cr_groups,
uc->cr_ngroups * sizeof(uc->cr_groups[0]));
}
/*
* Make a struct pcred out of a kauth_cred_t. For compatibility.
2006-05-15 01:12:38 +04:00
*/
void
kauth_cred_topcred(kauth_cred_t cred, struct ki_pcred *pc)
2006-05-15 01:12:38 +04:00
{
KASSERT(cred != NULL);
KASSERT(pc != NULL);
pc->p_pad = NULL;
2006-05-15 01:12:38 +04:00
pc->p_ruid = cred->cr_uid;
pc->p_svuid = cred->cr_svuid;
pc->p_rgid = cred->cr_gid;
pc->p_svgid = cred->cr_svgid;
pc->p_refcnt = cred->cr_refcnt;
}
/*
* Return kauth_cred_t for the current LWP.
2006-05-15 01:12:38 +04:00
*/
kauth_cred_t
kauth_cred_get(void)
{
return (curlwp->l_cred);
2006-05-15 01:12:38 +04:00
}
/*
* Returns a scope matching the provided id.
* Requires the scope list lock to be held by the caller.
*/
static kauth_scope_t
2006-05-23 04:43:30 +04:00
kauth_ifindscope(const char *id)
{
2006-05-15 01:12:38 +04:00
kauth_scope_t scope;
2007-02-10 00:55:00 +03:00
KASSERT(rw_lock_held(&kauth_lock));
2006-05-15 01:12:38 +04:00
scope = NULL;
SIMPLEQ_FOREACH(scope, &scope_list, next_scope) {
if (strcmp(scope->id, id) == 0)
break;
}
return (scope);
}
/*
* Register a new scope.
*
* id - identifier for the scope
* callback - the scope's default listener
* cookie - cookie to be passed to the listener(s)
*/
kauth_scope_t
kauth_register_scope(const char *id, kauth_scope_callback_t callback,
void *cookie)
2006-05-15 01:12:38 +04:00
{
kauth_scope_t scope;
kauth_listener_t listener = NULL; /* XXX gcc */
2006-05-15 01:12:38 +04:00
/* Sanitize input */
if (id == NULL)
2006-05-15 01:12:38 +04:00
return (NULL);
/* Allocate space for a new scope and listener. */
scope = kmem_alloc(sizeof(*scope), KM_SLEEP);
if (scope == NULL)
return NULL;
if (callback != NULL) {
listener = kmem_alloc(sizeof(*listener), KM_SLEEP);
if (listener == NULL) {
kmem_free(scope, sizeof(*scope));
return (NULL);
}
}
2006-05-15 01:12:38 +04:00
/*
* Acquire scope list lock.
*/
2007-02-10 00:55:00 +03:00
rw_enter(&kauth_lock, RW_WRITER);
2006-05-15 01:12:38 +04:00
/* Check we don't already have a scope with the same id */
if (kauth_ifindscope(id) != NULL) {
2007-02-10 00:55:00 +03:00
rw_exit(&kauth_lock);
2006-05-15 01:12:38 +04:00
kmem_free(scope, sizeof(*scope));
if (callback != NULL)
kmem_free(listener, sizeof(*listener));
2006-05-15 01:12:38 +04:00
return (NULL);
}
/* Initialize new scope with parameters */
scope->id = id;
scope->cookie = cookie;
scope->nlisteners = 1;
SIMPLEQ_INIT(&scope->listenq);
/* Add default listener */
if (callback != NULL) {
listener->func = callback;
listener->scope = scope;
listener->refcnt = 0;
SIMPLEQ_INSERT_HEAD(&scope->listenq, listener, listener_next);
}
2006-05-15 01:12:38 +04:00
/* Insert scope to scopes list */
SIMPLEQ_INSERT_TAIL(&scope_list, scope, next_scope);
2006-05-15 01:12:38 +04:00
2007-02-10 00:55:00 +03:00
rw_exit(&kauth_lock);
2006-05-15 01:12:38 +04:00
return (scope);
}
/*
* Initialize the kernel authorization subsystem.
*
* Initialize the scopes list lock.
* Create specificdata domain.
* Register the credentials scope, used in kauth(9) internally.
* Register built-in scopes: generic, system, process, network, machdep, device.
2006-05-15 01:12:38 +04:00
*/
void
kauth_init(void)
{
2007-02-10 00:55:00 +03:00
rw_init(&kauth_lock);
2006-05-15 01:12:38 +04:00
kauth_cred_cache = pool_cache_init(sizeof(struct kauth_cred),
coherency_unit, 0, 0, "kcredpl", NULL, IPL_NONE,
NULL, NULL, NULL);
/* Create specificdata domain. */
kauth_domain = specificdata_domain_create();
/* Register credentials scope. */
kauth_builtin_scope_cred =
kauth_register_scope(KAUTH_SCOPE_CRED, NULL, NULL);
2006-05-15 01:12:38 +04:00
/* Register generic scope. */
kauth_builtin_scope_generic = kauth_register_scope(KAUTH_SCOPE_GENERIC,
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
NULL, NULL);
/* Register system scope. */
kauth_builtin_scope_system = kauth_register_scope(KAUTH_SCOPE_SYSTEM,
NULL, NULL);
2006-05-15 01:12:38 +04:00
/* Register process scope. */
kauth_builtin_scope_process = kauth_register_scope(KAUTH_SCOPE_PROCESS,
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
NULL, NULL);
/* Register network scope. */
kauth_builtin_scope_network = kauth_register_scope(KAUTH_SCOPE_NETWORK,
NULL, NULL);
/* Register machdep scope. */
kauth_builtin_scope_machdep = kauth_register_scope(KAUTH_SCOPE_MACHDEP,
NULL, NULL);
/* Register device scope. */
kauth_builtin_scope_device = kauth_register_scope(KAUTH_SCOPE_DEVICE,
NULL, NULL);
/* Register vnode scope. */
kauth_builtin_scope_vnode = kauth_register_scope(KAUTH_SCOPE_VNODE,
NULL, NULL);
2006-05-15 01:12:38 +04:00
}
/*
* Deregister a scope.
* Requires scope list lock to be held by the caller.
*
* scope - the scope to deregister
*/
void
kauth_deregister_scope(kauth_scope_t scope)
{
if (scope != NULL) {
/* Remove scope from list */
SIMPLEQ_REMOVE(&scope_list, scope, kauth_scope, next_scope);
kmem_free(scope, sizeof(*scope));
2006-05-15 01:12:38 +04:00
}
}
/*
* Register a listener.
*
* id - scope identifier.
* callback - the callback routine for the listener.
* cookie - cookie to pass unmoidfied to the callback.
*/
kauth_listener_t
kauth_listen_scope(const char *id, kauth_scope_callback_t callback,
void *cookie)
2006-05-15 01:12:38 +04:00
{
kauth_scope_t scope;
kauth_listener_t listener;
2007-02-10 00:55:00 +03:00
listener = kmem_alloc(sizeof(*listener), KM_SLEEP);
if (listener == NULL)
return (NULL);
rw_enter(&kauth_lock, RW_WRITER);
/*
* Find scope struct.
*/
2006-05-15 01:12:38 +04:00
scope = kauth_ifindscope(id);
2007-02-10 00:55:00 +03:00
if (scope == NULL) {
rw_exit(&kauth_lock);
kmem_free(listener, sizeof(*listener));
2006-05-15 01:12:38 +04:00
return (NULL);
2007-02-10 00:55:00 +03:00
}
2006-05-15 01:12:38 +04:00
/* Allocate listener */
/* Initialize listener with parameters */
listener->func = callback;
listener->refcnt = 0;
/* Add listener to scope */
SIMPLEQ_INSERT_TAIL(&scope->listenq, listener, listener_next);
/* Raise number of listeners on scope. */
scope->nlisteners++;
listener->scope = scope;
2007-02-10 00:55:00 +03:00
rw_exit(&kauth_lock);
2006-05-15 01:12:38 +04:00
return (listener);
}
/*
* Deregister a listener.
*
* listener - listener reference as returned from kauth_listen_scope().
*/
void
kauth_unlisten_scope(kauth_listener_t listener)
{
2007-02-10 00:55:00 +03:00
2006-05-15 01:12:38 +04:00
if (listener != NULL) {
2007-02-10 00:55:00 +03:00
rw_enter(&kauth_lock, RW_WRITER);
2006-05-23 04:43:30 +04:00
SIMPLEQ_REMOVE(&listener->scope->listenq, listener,
kauth_listener, listener_next);
2006-05-15 01:12:38 +04:00
listener->scope->nlisteners--;
2007-02-10 00:55:00 +03:00
rw_exit(&kauth_lock);
kmem_free(listener, sizeof(*listener));
2006-05-15 01:12:38 +04:00
}
}
/*
* Authorize a request.
*
* scope - the scope of the request as defined by KAUTH_SCOPE_* or as
* returned from kauth_register_scope().
* credential - credentials of the user ("actor") making the request.
* action - request identifier.
* arg[0-3] - passed unmodified to listener(s).
*
* Returns the aggregated result:
* - KAUTH_RESULT_ALLOW if there is at least one KAUTH_RESULT_ALLOW and
* zero KAUTH_DESULT_DENY
* - KAUTH_RESULT_DENY if there is at least one KAUTH_RESULT_DENY
* - KAUTH_RESULT_DEFER if there is nothing but KAUTH_RESULT_DEFER
2006-05-15 01:12:38 +04:00
*/
static int
kauth_authorize_action_internal(kauth_scope_t scope, kauth_cred_t cred,
kauth_action_t action, void *arg0, void *arg1, void *arg2, void *arg3)
2006-05-15 01:12:38 +04:00
{
kauth_listener_t listener;
int error, allow, fail;
KASSERT(cred != NULL);
KASSERT(action != 0);
2006-05-15 01:12:38 +04:00
/* Short-circuit requests coming from the kernel. */
if (cred == NOCRED || cred == FSCRED)
return (0);
KASSERT(scope != NULL);
2006-05-15 01:12:38 +04:00
fail = 0;
allow = 0;
2007-02-10 00:55:00 +03:00
/* rw_enter(&kauth_lock, RW_READER); XXX not yet */
2006-05-15 01:12:38 +04:00
SIMPLEQ_FOREACH(listener, &scope->listenq, listener_next) {
error = listener->func(cred, action, scope->cookie, arg0,
2007-02-10 00:55:00 +03:00
arg1, arg2, arg3);
2006-05-15 01:12:38 +04:00
if (error == KAUTH_RESULT_ALLOW)
allow = 1;
else if (error == KAUTH_RESULT_DENY)
fail = 1;
}
2007-02-10 00:55:00 +03:00
/* rw_exit(&kauth_lock); */
2006-05-15 01:12:38 +04:00
if (fail)
return (KAUTH_RESULT_DENY);
if (allow)
return (KAUTH_RESULT_ALLOW);
return (KAUTH_RESULT_DEFER);
};
int
kauth_authorize_action(kauth_scope_t scope, kauth_cred_t cred,
kauth_action_t action, void *arg0, void *arg1, void *arg2, void *arg3)
{
int r;
r = kauth_authorize_action_internal(scope, cred, action, arg0, arg1,
arg2, arg3);
if (r == KAUTH_RESULT_DENY)
return (EPERM);
if (r == KAUTH_RESULT_ALLOW)
return (0);
if (!nsecmodels)
return (0);
return (EPERM);
}
2006-05-15 01:12:38 +04:00
/*
* Generic scope authorization wrapper.
*/
int
kauth_authorize_generic(kauth_cred_t cred, kauth_action_t action, void *arg0)
{
return (kauth_authorize_action(kauth_builtin_scope_generic, cred,
action, arg0, NULL, NULL, NULL));
}
/*
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
* System scope authorization wrapper.
2006-05-15 01:12:38 +04:00
*/
int
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
kauth_authorize_system(kauth_cred_t cred, kauth_action_t action,
enum kauth_system_req req, void *arg1, void *arg2, void *arg3)
2006-05-15 01:12:38 +04:00
{
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
return (kauth_authorize_action(kauth_builtin_scope_system, cred,
action, (void *)req, arg1, arg2, arg3));
2006-05-15 01:12:38 +04:00
}
/*
* Process scope authorization wrapper.
*/
int
kauth_authorize_process(kauth_cred_t cred, kauth_action_t action,
struct proc *p, void *arg1, void *arg2, void *arg3)
{
return (kauth_authorize_action(kauth_builtin_scope_process, cred,
action, p, arg1, arg2, arg3));
}
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
/*
* Network scope authorization wrapper.
*/
int
kauth_authorize_network(kauth_cred_t cred, kauth_action_t action,
enum kauth_network_req req, void *arg1, void *arg2, void *arg3)
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
{
return (kauth_authorize_action(kauth_builtin_scope_network, cred,
action, (void *)req, arg1, arg2, arg3));
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
}
int
kauth_authorize_machdep(kauth_cred_t cred, kauth_action_t action,
void *arg0, void *arg1, void *arg2, void *arg3)
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
{
return (kauth_authorize_action(kauth_builtin_scope_machdep, cred,
action, arg0, arg1, arg2, arg3));
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
}
int
kauth_authorize_device(kauth_cred_t cred, kauth_action_t action,
void *arg0, void *arg1, void *arg2, void *arg3)
{
return (kauth_authorize_action(kauth_builtin_scope_device, cred,
action, arg0, arg1, arg2, arg3));
}
int
kauth_authorize_device_tty(kauth_cred_t cred, kauth_action_t action,
struct tty *tty)
{
return (kauth_authorize_action(kauth_builtin_scope_device, cred,
action, tty, NULL, NULL, NULL));
}
int
kauth_authorize_device_spec(kauth_cred_t cred, enum kauth_device_req req,
struct vnode *vp)
{
return (kauth_authorize_action(kauth_builtin_scope_device, cred,
KAUTH_DEVICE_RAWIO_SPEC, (void *)req, vp, NULL, NULL));
}
int
kauth_authorize_device_passthru(kauth_cred_t cred, dev_t dev, u_long bits,
void *data)
{
return (kauth_authorize_action(kauth_builtin_scope_device, cred,
KAUTH_DEVICE_RAWIO_PASSTHRU, (void *)bits, (void *)(u_long)dev,
data, NULL));
}
kauth_action_t
kauth_mode_to_action(mode_t mode)
{
kauth_action_t action = 0;
if (mode & VREAD)
action |= KAUTH_VNODE_READ_DATA;
if (mode & VWRITE)
action |= KAUTH_VNODE_WRITE_DATA;
if (mode & VEXEC)
action |= KAUTH_VNODE_EXECUTE;
return action;
}
int
kauth_authorize_vnode(kauth_cred_t cred, kauth_action_t action,
struct vnode *vp, struct vnode *dvp, int fs_decision)
{
int error;
error = kauth_authorize_action_internal(kauth_builtin_scope_vnode, cred,
action, vp, dvp, NULL, NULL);
if (error == KAUTH_RESULT_DENY)
return (EACCES);
if (error == KAUTH_RESULT_ALLOW)
return (0);
/*
* If the file-system does not support decision-before-action, we can
* only short-circuit the operation (deny). If we're here, it means no
* listener denied it, so our only alternative is to supposedly-allow
* it and let the file-system have the last word.
*/
if (fs_decision == KAUTH_VNODE_REMOTEFS)
return (0);
return (fs_decision);
}
static int
kauth_cred_hook(kauth_cred_t cred, kauth_action_t action, void *arg0,
void *arg1)
{
int r;
r = kauth_authorize_action(kauth_builtin_scope_cred, cred, action,
arg0, arg1, NULL, NULL);
#ifdef DIAGNOSTIC
if (!SIMPLEQ_EMPTY(&kauth_builtin_scope_cred->listenq))
KASSERT(r == 0);
#endif /* DIAGNOSTIC */
return (r);
}
void
secmodel_register(void)
{
KASSERT(nsecmodels + 1 != 0);
2007-02-10 00:55:00 +03:00
rw_enter(&kauth_lock, RW_WRITER);
nsecmodels++;
2007-02-10 00:55:00 +03:00
rw_exit(&kauth_lock);
}
void
secmodel_deregister(void)
{
KASSERT(nsecmodels != 0);
2007-02-10 00:55:00 +03:00
rw_enter(&kauth_lock, RW_WRITER);
nsecmodels--;
2007-02-10 00:55:00 +03:00
rw_exit(&kauth_lock);
}