keys: allow the callout data to be passed as a blob rather than a string

Allow the callout data to be passed as a blob rather than a string for
internal kernel services that call any request_key_*() interface other than
request_key().  request_key() itself still takes a NUL-terminated string.

The functions that change are:

	request_key_with_auxdata()
	request_key_async()
	request_key_async_with_auxdata()

Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Paul Moore <paul.moore@hp.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: James Morris <jmorris@namei.org>
Cc: Kevin Coffman <kwc@citi.umich.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
David Howells 2008-04-29 01:01:24 -07:00 committed by Linus Torvalds
parent dceba99441
commit 4a38e122e2
7 changed files with 70 additions and 41 deletions

View file

@ -11,26 +11,29 @@ request_key*():
struct key *request_key(const struct key_type *type, struct key *request_key(const struct key_type *type,
const char *description, const char *description,
const char *callout_string); const char *callout_info);
or: or:
struct key *request_key_with_auxdata(const struct key_type *type, struct key *request_key_with_auxdata(const struct key_type *type,
const char *description, const char *description,
const char *callout_string, const char *callout_info,
size_t callout_len,
void *aux); void *aux);
or: or:
struct key *request_key_async(const struct key_type *type, struct key *request_key_async(const struct key_type *type,
const char *description, const char *description,
const char *callout_string); const char *callout_info,
size_t callout_len);
or: or:
struct key *request_key_async_with_auxdata(const struct key_type *type, struct key *request_key_async_with_auxdata(const struct key_type *type,
const char *description, const char *description,
const char *callout_string, const char *callout_info,
size_t callout_len,
void *aux); void *aux);
Or by userspace invoking the request_key system call: Or by userspace invoking the request_key system call:

View file

@ -771,7 +771,7 @@ payload contents" for more information.
struct key *request_key(const struct key_type *type, struct key *request_key(const struct key_type *type,
const char *description, const char *description,
const char *callout_string); const char *callout_info);
This is used to request a key or keyring with a description that matches This is used to request a key or keyring with a description that matches
the description specified according to the key type's match function. This the description specified according to the key type's match function. This
@ -793,24 +793,28 @@ payload contents" for more information.
struct key *request_key_with_auxdata(const struct key_type *type, struct key *request_key_with_auxdata(const struct key_type *type,
const char *description, const char *description,
const char *callout_string, const void *callout_info,
size_t callout_len,
void *aux); void *aux);
This is identical to request_key(), except that the auxiliary data is This is identical to request_key(), except that the auxiliary data is
passed to the key_type->request_key() op if it exists. passed to the key_type->request_key() op if it exists, and the callout_info
is a blob of length callout_len, if given (the length may be 0).
(*) A key can be requested asynchronously by calling one of: (*) A key can be requested asynchronously by calling one of:
struct key *request_key_async(const struct key_type *type, struct key *request_key_async(const struct key_type *type,
const char *description, const char *description,
const char *callout_string); const void *callout_info,
size_t callout_len);
or: or:
struct key *request_key_async_with_auxdata(const struct key_type *type, struct key *request_key_async_with_auxdata(const struct key_type *type,
const char *description, const char *description,
const char *callout_string, const char *callout_info,
size_t callout_len,
void *aux); void *aux);
which are asynchronous equivalents of request_key() and which are asynchronous equivalents of request_key() and

View file

@ -208,16 +208,19 @@ extern struct key *request_key(struct key_type *type,
extern struct key *request_key_with_auxdata(struct key_type *type, extern struct key *request_key_with_auxdata(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const void *callout_info,
size_t callout_len,
void *aux); void *aux);
extern struct key *request_key_async(struct key_type *type, extern struct key *request_key_async(struct key_type *type,
const char *description, const char *description,
const char *callout_info); const void *callout_info,
size_t callout_len);
extern struct key *request_key_async_with_auxdata(struct key_type *type, extern struct key *request_key_async_with_auxdata(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const void *callout_info,
size_t callout_len,
void *aux); void *aux);
extern int wait_for_key_construction(struct key *key, bool intr); extern int wait_for_key_construction(struct key *key, bool intr);

View file

@ -109,7 +109,8 @@ extern int install_process_keyring(struct task_struct *tsk);
extern struct key *request_key_and_link(struct key_type *type, extern struct key *request_key_and_link(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const void *callout_info,
size_t callout_len,
void *aux, void *aux,
struct key *dest_keyring, struct key *dest_keyring,
unsigned long flags); unsigned long flags);
@ -120,13 +121,15 @@ extern struct key *request_key_and_link(struct key_type *type,
struct request_key_auth { struct request_key_auth {
struct key *target_key; struct key *target_key;
struct task_struct *context; struct task_struct *context;
char *callout_info; void *callout_info;
size_t callout_len;
pid_t pid; pid_t pid;
}; };
extern struct key_type key_type_request_key_auth; extern struct key_type key_type_request_key_auth;
extern struct key *request_key_auth_new(struct key *target, extern struct key *request_key_auth_new(struct key *target,
const char *callout_info); const void *callout_info,
size_t callout_len);
extern struct key *key_get_instantiation_authkey(key_serial_t target_id); extern struct key *key_get_instantiation_authkey(key_serial_t target_id);

View file

@ -152,6 +152,7 @@ asmlinkage long sys_request_key(const char __user *_type,
struct key_type *ktype; struct key_type *ktype;
struct key *key; struct key *key;
key_ref_t dest_ref; key_ref_t dest_ref;
size_t callout_len;
char type[32], *description, *callout_info; char type[32], *description, *callout_info;
long ret; long ret;
@ -169,12 +170,14 @@ asmlinkage long sys_request_key(const char __user *_type,
/* pull the callout info into kernel space */ /* pull the callout info into kernel space */
callout_info = NULL; callout_info = NULL;
callout_len = 0;
if (_callout_info) { if (_callout_info) {
callout_info = strndup_user(_callout_info, PAGE_SIZE); callout_info = strndup_user(_callout_info, PAGE_SIZE);
if (IS_ERR(callout_info)) { if (IS_ERR(callout_info)) {
ret = PTR_ERR(callout_info); ret = PTR_ERR(callout_info);
goto error2; goto error2;
} }
callout_len = strlen(callout_info);
} }
/* get the destination keyring if specified */ /* get the destination keyring if specified */
@ -195,8 +198,8 @@ asmlinkage long sys_request_key(const char __user *_type,
} }
/* do the search */ /* do the search */
key = request_key_and_link(ktype, description, callout_info, NULL, key = request_key_and_link(ktype, description, callout_info,
key_ref_to_ptr(dest_ref), callout_len, NULL, key_ref_to_ptr(dest_ref),
KEY_ALLOC_IN_QUOTA); KEY_ALLOC_IN_QUOTA);
if (IS_ERR(key)) { if (IS_ERR(key)) {
ret = PTR_ERR(key); ret = PTR_ERR(key);

View file

@ -161,21 +161,22 @@ error_alloc:
* call out to userspace for key construction * call out to userspace for key construction
* - we ignore program failure and go on key status instead * - we ignore program failure and go on key status instead
*/ */
static int construct_key(struct key *key, const char *callout_info, void *aux) static int construct_key(struct key *key, const void *callout_info,
size_t callout_len, void *aux)
{ {
struct key_construction *cons; struct key_construction *cons;
request_key_actor_t actor; request_key_actor_t actor;
struct key *authkey; struct key *authkey;
int ret; int ret;
kenter("%d,%s,%p", key->serial, callout_info, aux); kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
cons = kmalloc(sizeof(*cons), GFP_KERNEL); cons = kmalloc(sizeof(*cons), GFP_KERNEL);
if (!cons) if (!cons)
return -ENOMEM; return -ENOMEM;
/* allocate an authorisation key */ /* allocate an authorisation key */
authkey = request_key_auth_new(key, callout_info); authkey = request_key_auth_new(key, callout_info, callout_len);
if (IS_ERR(authkey)) { if (IS_ERR(authkey)) {
kfree(cons); kfree(cons);
ret = PTR_ERR(authkey); ret = PTR_ERR(authkey);
@ -331,6 +332,7 @@ alloc_failed:
static struct key *construct_key_and_link(struct key_type *type, static struct key *construct_key_and_link(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const char *callout_info,
size_t callout_len,
void *aux, void *aux,
struct key *dest_keyring, struct key *dest_keyring,
unsigned long flags) unsigned long flags)
@ -348,7 +350,7 @@ static struct key *construct_key_and_link(struct key_type *type,
key_user_put(user); key_user_put(user);
if (ret == 0) { if (ret == 0) {
ret = construct_key(key, callout_info, aux); ret = construct_key(key, callout_info, callout_len, aux);
if (ret < 0) if (ret < 0)
goto construction_failed; goto construction_failed;
} }
@ -370,7 +372,8 @@ construction_failed:
*/ */
struct key *request_key_and_link(struct key_type *type, struct key *request_key_and_link(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const void *callout_info,
size_t callout_len,
void *aux, void *aux,
struct key *dest_keyring, struct key *dest_keyring,
unsigned long flags) unsigned long flags)
@ -378,8 +381,8 @@ struct key *request_key_and_link(struct key_type *type,
struct key *key; struct key *key;
key_ref_t key_ref; key_ref_t key_ref;
kenter("%s,%s,%s,%p,%p,%lx", kenter("%s,%s,%p,%zu,%p,%p,%lx",
type->name, description, callout_info, aux, type->name, description, callout_info, callout_len, aux,
dest_keyring, flags); dest_keyring, flags);
/* search all the process keyrings for a key */ /* search all the process keyrings for a key */
@ -398,7 +401,8 @@ struct key *request_key_and_link(struct key_type *type,
goto error; goto error;
key = construct_key_and_link(type, description, callout_info, key = construct_key_and_link(type, description, callout_info,
aux, dest_keyring, flags); callout_len, aux, dest_keyring,
flags);
} }
error: error:
@ -434,10 +438,13 @@ struct key *request_key(struct key_type *type,
const char *callout_info) const char *callout_info)
{ {
struct key *key; struct key *key;
size_t callout_len = 0;
int ret; int ret;
key = request_key_and_link(type, description, callout_info, NULL, if (callout_info)
NULL, KEY_ALLOC_IN_QUOTA); callout_len = strlen(callout_info);
key = request_key_and_link(type, description, callout_info, callout_len,
NULL, NULL, KEY_ALLOC_IN_QUOTA);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
ret = wait_for_key_construction(key, false); ret = wait_for_key_construction(key, false);
if (ret < 0) { if (ret < 0) {
@ -458,14 +465,15 @@ EXPORT_SYMBOL(request_key);
*/ */
struct key *request_key_with_auxdata(struct key_type *type, struct key *request_key_with_auxdata(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const void *callout_info,
size_t callout_len,
void *aux) void *aux)
{ {
struct key *key; struct key *key;
int ret; int ret;
key = request_key_and_link(type, description, callout_info, aux, key = request_key_and_link(type, description, callout_info, callout_len,
NULL, KEY_ALLOC_IN_QUOTA); aux, NULL, KEY_ALLOC_IN_QUOTA);
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
ret = wait_for_key_construction(key, false); ret = wait_for_key_construction(key, false);
if (ret < 0) { if (ret < 0) {
@ -485,10 +493,12 @@ EXPORT_SYMBOL(request_key_with_auxdata);
*/ */
struct key *request_key_async(struct key_type *type, struct key *request_key_async(struct key_type *type,
const char *description, const char *description,
const char *callout_info) const void *callout_info,
size_t callout_len)
{ {
return request_key_and_link(type, description, callout_info, NULL, return request_key_and_link(type, description, callout_info,
NULL, KEY_ALLOC_IN_QUOTA); callout_len, NULL, NULL,
KEY_ALLOC_IN_QUOTA);
} }
EXPORT_SYMBOL(request_key_async); EXPORT_SYMBOL(request_key_async);
@ -500,10 +510,11 @@ EXPORT_SYMBOL(request_key_async);
*/ */
struct key *request_key_async_with_auxdata(struct key_type *type, struct key *request_key_async_with_auxdata(struct key_type *type,
const char *description, const char *description,
const char *callout_info, const void *callout_info,
size_t callout_len,
void *aux) void *aux)
{ {
return request_key_and_link(type, description, callout_info, aux, return request_key_and_link(type, description, callout_info,
NULL, KEY_ALLOC_IN_QUOTA); callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA);
} }
EXPORT_SYMBOL(request_key_async_with_auxdata); EXPORT_SYMBOL(request_key_async_with_auxdata);

View file

@ -61,7 +61,7 @@ static void request_key_auth_describe(const struct key *key,
seq_puts(m, "key:"); seq_puts(m, "key:");
seq_puts(m, key->description); seq_puts(m, key->description);
seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info)); seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
} /* end request_key_auth_describe() */ } /* end request_key_auth_describe() */
@ -77,7 +77,7 @@ static long request_key_auth_read(const struct key *key,
size_t datalen; size_t datalen;
long ret; long ret;
datalen = strlen(rka->callout_info); datalen = rka->callout_len;
ret = datalen; ret = datalen;
/* we can return the data as is */ /* we can return the data as is */
@ -137,7 +137,8 @@ static void request_key_auth_destroy(struct key *key)
* create an authorisation token for /sbin/request-key or whoever to gain * create an authorisation token for /sbin/request-key or whoever to gain
* access to the caller's security data * access to the caller's security data
*/ */
struct key *request_key_auth_new(struct key *target, const char *callout_info) struct key *request_key_auth_new(struct key *target, const void *callout_info,
size_t callout_len)
{ {
struct request_key_auth *rka, *irka; struct request_key_auth *rka, *irka;
struct key *authkey = NULL; struct key *authkey = NULL;
@ -152,7 +153,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
kleave(" = -ENOMEM"); kleave(" = -ENOMEM");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL); rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
if (!rka->callout_info) { if (!rka->callout_info) {
kleave(" = -ENOMEM"); kleave(" = -ENOMEM");
kfree(rka); kfree(rka);
@ -186,7 +187,8 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
} }
rka->target_key = key_get(target); rka->target_key = key_get(target);
strcpy(rka->callout_info, callout_info); memcpy(rka->callout_info, callout_info, callout_len);
rka->callout_len = callout_len;
/* allocate the auth key */ /* allocate the auth key */
sprintf(desc, "%x", target->serial); sprintf(desc, "%x", target->serial);