Add a new scope, the credentials scope, which is internal to the kauth(9)
implementation and meant to be used by security models to hook credential related operations (init, fork, copy, free -- hooked in kauth_cred_alloc(), kauth_proc_fork(), kauth_cred_clone(), and kauth_cred_free(), respectively) and document it. Add specificdata to credentials, and routines to register/deregister new "keys", as well as set/get routines. This allows security models to add their own private data to a kauth_cred_t. The above two, combined, allow security models to control inheritance of their own private data in credentials which is a requirement for doing stuff like, I dunno, capabilities?
This commit is contained in:
parent
b7e0d69761
commit
c439bcfe43
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: kauth.9,v 1.50 2007/01/28 00:21:04 elad Exp $
|
||||
.\" $NetBSD: kauth.9,v 1.51 2007/01/31 10:08:23 elad Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
|
||||
.\" All rights reserved.
|
||||
|
@ -25,7 +25,7 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd January 28, 2007
|
||||
.Dd January 31, 2007
|
||||
.Dt KAUTH 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -724,6 +724,67 @@ passed as
|
|||
.Ar arg2
|
||||
to the listener, is device-specific data that may be associated with the
|
||||
request.
|
||||
.Ss Credentials Scope
|
||||
The credentials scope,
|
||||
.Dq org.netbsd.kauth.cred ,
|
||||
is a special scope used internally by the
|
||||
.Nm
|
||||
framework to provide hooking to credential-related operations.
|
||||
.Pp
|
||||
It is a
|
||||
.Dq notify-only
|
||||
scope, allowing hooking operations such as initialization of new credentials,
|
||||
credential inheritance during a fork, and copying and freeing of credentials.
|
||||
The main purpose for this scope is to give a security model a way to control
|
||||
the aforementioned operations, especially in cases where the credentials
|
||||
hold security model-private data.
|
||||
.Pp
|
||||
Notifications are made using the following function, which is internal to
|
||||
.Nm :
|
||||
.Pp
|
||||
.Ft int Fn kauth_cred_hook "kauth_cred_t cred" "kauth_action_t action" \
|
||||
"void *arg0" "void *arg1"
|
||||
.Pp
|
||||
With the following actions:
|
||||
.Bl -tag
|
||||
.It Dv KAUTH_CRED_COPY
|
||||
The credentials are being copied.
|
||||
.Ar cred
|
||||
are the credentials of the lwp context doing the copy, and
|
||||
.Ar arg0
|
||||
and
|
||||
.Ar arg1
|
||||
are both
|
||||
.Ft kauth_cred_t
|
||||
representing the
|
||||
.Dq from
|
||||
and
|
||||
.Dq to
|
||||
credentials, respectively.
|
||||
.It Dv KAUTH_CRED_FORK
|
||||
The credentials are being inherited from a parent to a child process during a
|
||||
fork.
|
||||
.Pp
|
||||
.Ar cred
|
||||
are the credentials of the lwp context doing the copy, and
|
||||
.Ar arg0
|
||||
and
|
||||
.Ar arg1
|
||||
are both
|
||||
.Ft struct proc *
|
||||
of the parent and child processes, respectively.
|
||||
.It Dv KAUTH_CRED_FREE
|
||||
The credentials in
|
||||
.Ar cred
|
||||
are being freed.
|
||||
.It Dv KAUTH_CRED_INIT
|
||||
The credentials in
|
||||
.Ar cred
|
||||
are being initialized.
|
||||
.El
|
||||
.Pp
|
||||
Since this is a notify-only scope, all listeners are required to return
|
||||
.Dv KAUTH_RESULT_ALLOW .
|
||||
.Ss Credentials Accessors and Mutators
|
||||
.Nm
|
||||
has a variety of accessor and mutator routines to handle
|
||||
|
@ -841,23 +902,75 @@ The number of groups in
|
|||
.Ar cred
|
||||
will be returned.
|
||||
.El
|
||||
.Ss Credentials Inheritance and Reference Counting
|
||||
.Ss Credential Private Data
|
||||
.Nm
|
||||
provides a KPI for handling a
|
||||
.Ft kauth_cred_t
|
||||
in shared credentials situations and credential inheritance.
|
||||
provides an interface to allow attaching security-model private data to
|
||||
credentials.
|
||||
.Pp
|
||||
The use of this interface has two parts that can be divided to direct and
|
||||
indirect control of the private-data.
|
||||
Directly controlling the private data is done by using the below routines,
|
||||
while the indirect control is often dictated by events such as process
|
||||
fork, and is handled by listening on the credentials scope (see above).
|
||||
.Pp
|
||||
Attaching private data to credentials works by registering a key to serve
|
||||
as a unique identifier, distinguishing various sets of private data that
|
||||
may be associated with the credentials.
|
||||
Registering, and deregistering, a key is done by using these routines:
|
||||
.Pp
|
||||
.Bl -tag
|
||||
.It Ft int Fn kauth_register_key "const char *name" "kauth_key_t *keyp"
|
||||
Register new key for private data for
|
||||
.Ar name
|
||||
(usually, the security model name).
|
||||
.Ar keyp
|
||||
will be used to return the key to be used in further calls.
|
||||
.Pp
|
||||
The function returns 0 on success and an error code (see
|
||||
.Xr errno 2 )
|
||||
on failure.
|
||||
.It Ft int Fn kauth_deregister_key "kauth_key_t key"
|
||||
Deregister private data key
|
||||
.Ar key .
|
||||
.El
|
||||
.Pp
|
||||
Once registered, private data may be manipulated by the following routines:
|
||||
.Bl -tag
|
||||
.It Ft void Fn kauth_cred_setdata "kauth_cred_t cred" "kauth_key_t key" \
|
||||
"void *data"
|
||||
Set private data for
|
||||
.Ar key
|
||||
in
|
||||
.Ar cred
|
||||
to be
|
||||
.Ar data .
|
||||
.It Ft void * Fn kauth_cred_getdata "kauth_cred_t cred" "kauth_key_t key"
|
||||
Retrieve private data for
|
||||
.Ar key
|
||||
in
|
||||
.Ar cred .
|
||||
.El
|
||||
.Pp
|
||||
Note that it is required to use the above routines every time the private
|
||||
data is changed, i.e., using
|
||||
.Fn kauth_cred_getdata
|
||||
and later modifying the private data should be accompanied by a call to
|
||||
.Fn kauth_cred_setdata
|
||||
with the
|
||||
.Dq new
|
||||
private data.
|
||||
.Ss Credential Inheritance and Reference Counting
|
||||
.Nm
|
||||
provides an interface for handling shared credentials.
|
||||
.Pp
|
||||
When a
|
||||
.Ft kauth_cred_t
|
||||
is first allocated, its reference count is set to 1.
|
||||
However, with time, its reference count can grow as more objects (processes,
|
||||
LWPs, files, etc.) reference it.
|
||||
One such case is during a
|
||||
.Xr fork 2
|
||||
where the child process and its LWPs inherit the credentials of the parent.
|
||||
.Pp
|
||||
The following routines are available for managing credentials reference
|
||||
counting and inheritance:
|
||||
counting:
|
||||
.Bl -tag
|
||||
.It Ft void Fn kauth_cred_hold "kauth_cred_t cred"
|
||||
Increases reference count to
|
||||
|
@ -870,12 +983,20 @@ by one.
|
|||
.Pp
|
||||
If the reference count dropped to zero, the memory used by
|
||||
.Ar cred
|
||||
will be returned back to the memory pool.
|
||||
.It Ft void kauth_proc_fork "struct proc *parent" "struct proc *child"
|
||||
Called during a
|
||||
.Xr fork 2
|
||||
to perform credential inheritance.
|
||||
will be freed.
|
||||
.El
|
||||
.Pp
|
||||
Credential inheritance happens during a
|
||||
.Xr fork 2 ,
|
||||
and is handled by the following function:
|
||||
.Pp
|
||||
.Ft void Fn kauth_proc_fork "struct proc *parent" "struct proc *child"
|
||||
.Pp
|
||||
When called, it references the parent's credentials from the child,
|
||||
and calls the credentials scope's hook with the
|
||||
.Dv KAUTH_CRED_FORK
|
||||
action to allow security model-specific handling of the inheritance
|
||||
to take place.
|
||||
.Ss Credentials Memory Management
|
||||
Data-structures for credentials, listeners, and scopes are allocated from
|
||||
memory pools managed by the
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_auth.c,v 1.40 2007/01/26 23:50:36 elad Exp $ */
|
||||
/* $NetBSD: kern_auth.c,v 1.41 2007/01/31 10:08:23 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
|
||||
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.40 2007/01/26 23:50:36 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.41 2007/01/31 10:08:23 elad Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -38,6 +38,15 @@ __KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.40 2007/01/26 23:50:36 elad Exp $");
|
|||
#include <sys/pool.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/specificdata.h>
|
||||
|
||||
/*
|
||||
* Secmodel-specific credentials.
|
||||
*/
|
||||
struct kauth_key {
|
||||
const char *ks_secmodel; /* secmodel */
|
||||
specificdata_key_t ks_key; /* key */
|
||||
};
|
||||
|
||||
/*
|
||||
* Credentials.
|
||||
|
@ -53,6 +62,7 @@ struct kauth_cred {
|
|||
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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -76,6 +86,8 @@ struct kauth_scope {
|
|||
SIMPLEQ_ENTRY(kauth_scope) next_scope; /* scope list */
|
||||
};
|
||||
|
||||
static int kauth_cred_hook(kauth_cred_t, kauth_action_t, void *, void *);
|
||||
|
||||
static POOL_INIT(kauth_cred_pool, sizeof(struct kauth_cred), 0, 0, 0,
|
||||
"kauthcredpl", &pool_allocator_nointr);
|
||||
|
||||
|
@ -90,9 +102,12 @@ static kauth_scope_t kauth_builtin_scope_process;
|
|||
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 unsigned int nsecmodels = 0;
|
||||
|
||||
static specificdata_domain_t kauth_domain;
|
||||
|
||||
/* Allocate new, empty kauth credentials. */
|
||||
kauth_cred_t
|
||||
kauth_cred_alloc(void)
|
||||
|
@ -103,6 +118,8 @@ kauth_cred_alloc(void)
|
|||
memset(cred, 0, sizeof(*cred));
|
||||
simple_lock_init(&cred->cr_lock);
|
||||
cred->cr_refcnt = 1;
|
||||
specificdata_init(kauth_domain, &cred->cr_sd);
|
||||
kauth_cred_hook(cred, KAUTH_CRED_INIT, NULL, NULL);
|
||||
|
||||
return (cred);
|
||||
}
|
||||
|
@ -132,8 +149,11 @@ kauth_cred_free(kauth_cred_t cred)
|
|||
refcnt = --cred->cr_refcnt;
|
||||
simple_unlock(&cred->cr_lock);
|
||||
|
||||
if (refcnt == 0)
|
||||
if (refcnt == 0) {
|
||||
kauth_cred_hook(cred, KAUTH_CRED_FREE, NULL, NULL);
|
||||
specificdata_fini(kauth_domain, &cred->cr_sd);
|
||||
pool_put(&kauth_cred_pool, cred);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -151,6 +171,8 @@ kauth_cred_clone(kauth_cred_t from, kauth_cred_t to)
|
|||
to->cr_svgid = from->cr_svgid;
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -203,6 +225,9 @@ kauth_proc_fork(struct proc *parent, struct proc *child)
|
|||
kauth_cred_hold(parent->p_cred);
|
||||
child->p_cred = parent->p_cred;
|
||||
/* mutex_exit(&parent->p_mutex); */
|
||||
|
||||
kauth_cred_hook(parent->p_cred, KAUTH_CRED_FORK, parent,
|
||||
child);
|
||||
}
|
||||
|
||||
uid_t
|
||||
|
@ -377,6 +402,58 @@ kauth_cred_getgroups(kauth_cred_t cred, gid_t *grbuf, size_t len)
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Match uids in two credentials.
|
||||
*/
|
||||
|
@ -613,7 +690,9 @@ kauth_register_scope(const char *id, kauth_scope_callback_t callback,
|
|||
* Initialize the kernel authorization subsystem.
|
||||
*
|
||||
* Initialize the scopes list lock.
|
||||
* Register built-in scopes: generic, process.
|
||||
* Create specificdata domain.
|
||||
* Register the credentials scope, used in kauth(9) internally.
|
||||
* Register built-in scopes: generic, system, process, network, machdep, device.
|
||||
*/
|
||||
void
|
||||
kauth_init(void)
|
||||
|
@ -621,6 +700,13 @@ kauth_init(void)
|
|||
SIMPLEQ_INIT(&scope_list);
|
||||
simple_lock_init(&scopes_lock);
|
||||
|
||||
/* Create specificdata domain. */
|
||||
kauth_domain = specificdata_domain_create();
|
||||
|
||||
/* Register credentials scope. */
|
||||
kauth_builtin_scope_cred =
|
||||
kauth_register_scope(KAUTH_SCOPE_CRED, NULL, NULL);
|
||||
|
||||
/* Register generic scope. */
|
||||
kauth_builtin_scope_generic = kauth_register_scope(KAUTH_SCOPE_GENERIC,
|
||||
NULL, NULL);
|
||||
|
@ -862,6 +948,20 @@ kauth_authorize_device_passthru(kauth_cred_t cred, dev_t dev, u_long bits,
|
|||
data, NULL));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
KASSERT(r == 0);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
secmodel_register(void)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kauth.h,v 1.35 2007/01/20 16:47:38 elad Exp $ */
|
||||
/* $NetBSD: kauth.h,v 1.36 2007/01/31 10:08:23 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
|
||||
|
@ -48,6 +48,7 @@ typedef struct kauth_listener *kauth_listener_t;
|
|||
typedef uint32_t kauth_action_t;
|
||||
typedef int (*kauth_scope_callback_t)(kauth_cred_t, kauth_action_t,
|
||||
void *, void *, void *, void *, void *);
|
||||
typedef struct kauth_key *kauth_key_t;
|
||||
|
||||
/*
|
||||
* Possible return values for a listener.
|
||||
|
@ -65,6 +66,7 @@ typedef int (*kauth_scope_callback_t)(kauth_cred_t, kauth_action_t,
|
|||
#define KAUTH_SCOPE_NETWORK "org.netbsd.kauth.network"
|
||||
#define KAUTH_SCOPE_MACHDEP "org.netbsd.kauth.machdep"
|
||||
#define KAUTH_SCOPE_DEVICE "org.netbsd.kauth.device"
|
||||
#define KAUTH_SCOPE_CRED "org.netbsd.kauth.cred"
|
||||
|
||||
/*
|
||||
* Generic scope - actions.
|
||||
|
@ -217,6 +219,16 @@ enum kauth_device_req {
|
|||
KAUTH_REQ_DEVICE_RAWIO_SPEC_RW,
|
||||
};
|
||||
|
||||
/*
|
||||
* Credentials scope - actions.
|
||||
*/
|
||||
enum {
|
||||
KAUTH_CRED_INIT=1,
|
||||
KAUTH_CRED_FORK,
|
||||
KAUTH_CRED_COPY,
|
||||
KAUTH_CRED_FREE
|
||||
};
|
||||
|
||||
/*
|
||||
* Device scope, passthru request - identifiers.
|
||||
*/
|
||||
|
@ -290,6 +302,11 @@ u_int kauth_cred_getrefcnt(kauth_cred_t);
|
|||
int kauth_cred_setgroups(kauth_cred_t, gid_t *, size_t, uid_t);
|
||||
int kauth_cred_getgroups(kauth_cred_t, gid_t *, size_t);
|
||||
|
||||
int kauth_register_key(const char *, 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);
|
||||
|
||||
int kauth_cred_uidmatch(kauth_cred_t, kauth_cred_t);
|
||||
void kauth_uucred_to_cred(kauth_cred_t, const struct uucred *);
|
||||
void kauth_cred_to_uucred(struct uucred *, const kauth_cred_t);
|
||||
|
|
Loading…
Reference in New Issue