Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 28562
b: refs/heads/master
c: 04c567d
h: refs/heads/master
v: v3
  • Loading branch information
David Howells authored and Linus Torvalds committed Jun 22, 2006
1 parent 9fd3b9b commit a4430d7
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d720024e94de4e8b7f10ee83c532926f3ad5d708
refs/heads/master: 04c567d9313e4927b9835361d8ac0318ce65af6b
10 changes: 10 additions & 0 deletions trunk/Documentation/keys.txt
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,16 @@ The structure has a number of fields, some of which are mandatory:
It is not safe to sleep in this method; the caller may hold spinlocks.


(*) void (*revoke)(struct key *key);

This method is optional. It is called to discard part of the payload
data upon a key being revoked. The caller will have the key semaphore
write-locked.

It is safe to sleep in this method, though care should be taken to avoid
a deadlock against the key semaphore.


(*) void (*destroy)(struct key *key);

This method is optional. It is called to discard the payload data on a key
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ struct key_type {
/* match a key against a description */
int (*match)(const struct key *key, const void *desc);

/* clear some of the data from a key on revokation (optional)
* - the key's semaphore will be write-locked by the caller
*/
void (*revoke)(struct key *key);

/* clear the data from a key (optional) */
void (*destroy)(struct key *key);

Expand Down
4 changes: 4 additions & 0 deletions trunk/security/keys/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,10 @@ void key_revoke(struct key *key)
* it */
down_write(&key->sem);
set_bit(KEY_FLAG_REVOKED, &key->flags);

if (key->type->revoke)
key->type->revoke(key);

up_write(&key->sem);

} /* end key_revoke() */
Expand Down
42 changes: 26 additions & 16 deletions trunk/security/keys/process_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
struct request_key_auth *rka;
key_ref_t key_ref, ret, err;

might_sleep();

/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* searchable, but we failed to find a key or we found a negative key;
* otherwise we want to return a sample error (probably -EACCES) if
Expand Down Expand Up @@ -496,27 +498,35 @@ key_ref_t search_process_keyrings(struct key_type *type,
*/
if (context->request_key_auth &&
context == current &&
type != &key_type_request_key_auth &&
key_validate(context->request_key_auth) == 0
type != &key_type_request_key_auth
) {
rka = context->request_key_auth->payload.data;
/* defend against the auth key being revoked */
down_read(&context->request_key_auth->sem);

key_ref = search_process_keyrings(type, description, match,
rka->context);
if (key_validate(context->request_key_auth) == 0) {
rka = context->request_key_auth->payload.data;

if (!IS_ERR(key_ref))
goto found;
key_ref = search_process_keyrings(type, description,
match, rka->context);

switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
up_read(&context->request_key_auth->sem);

if (!IS_ERR(key_ref))
goto found;

switch (PTR_ERR(key_ref)) {
case -EAGAIN: /* no key */
if (ret)
break;
case -ENOKEY: /* negative key */
ret = key_ref;
break;
case -ENOKEY: /* negative key */
ret = key_ref;
break;
default:
err = key_ref;
break;
default:
err = key_ref;
break;
}
} else {
up_read(&context->request_key_auth->sem);
}
}

Expand Down
45 changes: 44 additions & 1 deletion trunk/security/keys/request_key_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

static int request_key_auth_instantiate(struct key *, const void *, size_t);
static void request_key_auth_describe(const struct key *, struct seq_file *);
static void request_key_auth_revoke(struct key *);
static void request_key_auth_destroy(struct key *);
static long request_key_auth_read(const struct key *, char __user *, size_t);

Expand All @@ -31,6 +32,7 @@ struct key_type key_type_request_key_auth = {
.def_datalen = sizeof(struct request_key_auth),
.instantiate = request_key_auth_instantiate,
.describe = request_key_auth_describe,
.revoke = request_key_auth_revoke,
.destroy = request_key_auth_destroy,
.read = request_key_auth_read,
};
Expand Down Expand Up @@ -91,6 +93,24 @@ static long request_key_auth_read(const struct key *key,

} /* end request_key_auth_read() */

/*****************************************************************************/
/*
* handle revocation of an authorisation token key
* - called with the key sem write-locked
*/
static void request_key_auth_revoke(struct key *key)
{
struct request_key_auth *rka = key->payload.data;

kenter("{%d}", key->serial);

if (rka->context) {
put_task_struct(rka->context);
rka->context = NULL;
}

} /* end request_key_auth_revoke() */

/*****************************************************************************/
/*
* destroy an instantiation authorisation token key
Expand All @@ -101,6 +121,11 @@ static void request_key_auth_destroy(struct key *key)

kenter("{%d}", key->serial);

if (rka->context) {
put_task_struct(rka->context);
rka->context = NULL;
}

key_put(rka->target_key);
kfree(rka);

Expand Down Expand Up @@ -131,14 +156,26 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
* another process */
if (current->request_key_auth) {
/* it is - use that instantiation context here too */
down_read(&current->request_key_auth->sem);

/* if the auth key has been revoked, then the key we're
* servicing is already instantiated */
if (test_bit(KEY_FLAG_REVOKED,
&current->request_key_auth->flags))
goto auth_key_revoked;

irka = current->request_key_auth->payload.data;
rka->context = irka->context;
rka->pid = irka->pid;
get_task_struct(rka->context);

up_read(&current->request_key_auth->sem);
}
else {
/* it isn't - use this process as the context */
rka->context = current;
rka->pid = current->pid;
get_task_struct(rka->context);
}

rka->target_key = key_get(target);
Expand All @@ -161,9 +198,15 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
if (ret < 0)
goto error_inst;

kleave(" = {%d})", authkey->serial);
kleave(" = {%d}", authkey->serial);
return authkey;

auth_key_revoked:
up_read(&current->request_key_auth->sem);
kfree(rka);
kleave("= -EKEYREVOKED");
return ERR_PTR(-EKEYREVOKED);

error_inst:
key_revoke(authkey);
key_put(authkey);
Expand Down

0 comments on commit a4430d7

Please sign in to comment.