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:
Родитель
dceba99441
Коммит
4a38e122e2
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче