X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=security%2Fkeys%2Frequest_key.c;h=58d1efd4fc2c66788788edcc2e5d90bd32e1dc10;hb=ba262e4a4d4c23b5e6c15dbb3a99696b562e8035;hp=5cc4bba70db61eab5157bb0bb7ffe6b673a11ab3;hpb=c85749e6d1df55ca5b23cb1d220ed7df92df8d78;p=linux-2.6-omap-h63xx.git diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 5cc4bba70db..58d1efd4fc2 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -29,28 +29,37 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); /*****************************************************************************/ /* * request userspace finish the construction of a key - * - execute "/sbin/request-key " + * - execute "/sbin/request-key " */ -static int call_request_key(struct key *key, - const char *op, - const char *callout_info) +static int call_sbin_request_key(struct key *key, + struct key *authkey, + const char *op) { struct task_struct *tsk = current; key_serial_t prkey, sskey; - struct key *session_keyring, *rkakey; - char *argv[10], *envp[3], uid_str[12], gid_str[12]; + struct key *keyring; + char *argv[9], *envp[3], uid_str[12], gid_str[12]; char key_str[12], keyring_str[3][12]; + char desc[20]; int ret, i; - kenter("{%d},%s,%s", key->serial, op, callout_info); + kenter("{%d},{%d},%s", key->serial, authkey->serial, op); - /* generate a new session keyring with an auth key in it */ - session_keyring = request_key_auth_new(key, &rkakey); - if (IS_ERR(session_keyring)) { - ret = PTR_ERR(session_keyring); - goto error; + /* allocate a new session keyring */ + sprintf(desc, "_req.%u", key->serial); + + keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, + KEY_ALLOC_QUOTA_OVERRUN, NULL); + if (IS_ERR(keyring)) { + ret = PTR_ERR(keyring); + goto error_alloc; } + /* attach the auth key to the session keyring */ + ret = __key_link(keyring, authkey); + if (ret < 0) + goto error_link; + /* record the UID and GID */ sprintf(uid_str, "%d", current->fsuid); sprintf(gid_str, "%d", current->fsgid); @@ -95,22 +104,19 @@ static int call_request_key(struct key *key, argv[i++] = keyring_str[0]; argv[i++] = keyring_str[1]; argv[i++] = keyring_str[2]; - argv[i++] = (char *) callout_info; argv[i] = NULL; /* do it */ - ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1); + ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1); - /* dispose of the special keys */ - key_revoke(rkakey); - key_put(rkakey); - key_put(session_keyring); +error_link: + key_put(keyring); - error: +error_alloc: kleave(" = %d", ret); return ret; -} /* end call_request_key() */ +} /* end call_sbin_request_key() */ /*****************************************************************************/ /* @@ -120,18 +126,21 @@ static int call_request_key(struct key *key, */ static struct key *__request_key_construction(struct key_type *type, const char *description, - const char *callout_info) + const char *callout_info, + unsigned long flags) { + request_key_actor_t actor; struct key_construction cons; struct timespec now; - struct key *key; + struct key *key, *authkey; int ret, negated; - kenter("%s,%s,%s", type->name, description, callout_info); + kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); /* create a key and add it to the queue */ key = key_alloc(type, description, - current->fsuid, current->fsgid, KEY_POS_ALL, 0); + current->fsuid, current->fsgid, current, KEY_POS_ALL, + flags); if (IS_ERR(key)) goto alloc_failed; @@ -143,8 +152,19 @@ static struct key *__request_key_construction(struct key_type *type, /* we drop the construction sem here on behalf of the caller */ up_write(&key_construction_sem); + /* allocate an authorisation key */ + authkey = request_key_auth_new(key, callout_info); + if (IS_ERR(authkey)) { + ret = PTR_ERR(authkey); + authkey = NULL; + goto alloc_authkey_failed; + } + /* make the call */ - ret = call_request_key(key, "create", callout_info); + actor = call_sbin_request_key; + if (type->request_key) + actor = type->request_key; + ret = actor(key, authkey, "create"); if (ret < 0) goto request_failed; @@ -153,22 +173,29 @@ static struct key *__request_key_construction(struct key_type *type, if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) goto request_failed; + key_revoke(authkey); + key_put(authkey); + down_write(&key_construction_sem); list_del(&cons.link); up_write(&key_construction_sem); /* also give an error if the key was negatively instantiated */ - check_not_negative: +check_not_negative: if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { key_put(key); key = ERR_PTR(-ENOKEY); } - out: +out: kleave(" = %p", key); return key; - request_failed: +request_failed: + key_revoke(authkey); + key_put(authkey); + +alloc_authkey_failed: /* it wasn't instantiated * - remove from construction queue * - mark the key as dead @@ -217,7 +244,7 @@ static struct key *__request_key_construction(struct key_type *type, key = ERR_PTR(ret); goto out; - alloc_failed: +alloc_failed: up_write(&key_construction_sem); goto out; @@ -232,15 +259,16 @@ static struct key *__request_key_construction(struct key_type *type, static struct key *request_key_construction(struct key_type *type, const char *description, struct key_user *user, - const char *callout_info) + const char *callout_info, + unsigned long flags) { struct key_construction *pcons; struct key *key, *ckey; DECLARE_WAITQUEUE(myself, current); - kenter("%s,%s,{%d},%s", - type->name, description, user->uid, callout_info); + kenter("%s,%s,{%d},%s,%lx", + type->name, description, user->uid, callout_info, flags); /* see if there's such a key under construction already */ down_write(&key_construction_sem); @@ -256,7 +284,8 @@ static struct key *request_key_construction(struct key_type *type, } /* see about getting userspace to construct the key */ - key = __request_key_construction(type, description, callout_info); + key = __request_key_construction(type, description, callout_info, + flags); error: kleave(" = %p", key); return key; @@ -363,14 +392,15 @@ static void request_key_link(struct key *key, struct key *dest_keyring) struct key *request_key_and_link(struct key_type *type, const char *description, const char *callout_info, - struct key *dest_keyring) + struct key *dest_keyring, + unsigned long flags) { struct key_user *user; struct key *key; key_ref_t key_ref; - kenter("%s,%s,%s,%p", - type->name, description, callout_info, dest_keyring); + kenter("%s,%s,%s,%p,%lx", + type->name, description, callout_info, dest_keyring, flags); /* search all the process keyrings for a key */ key_ref = search_process_keyrings(type, description, type->match, @@ -403,7 +433,8 @@ struct key *request_key_and_link(struct key_type *type, /* ask userspace (returns NULL if it waited on a key * being constructed) */ key = request_key_construction(type, description, - user, callout_info); + user, callout_info, + flags); if (key) break; @@ -459,40 +490,9 @@ struct key *request_key(struct key_type *type, const char *description, const char *callout_info) { - return request_key_and_link(type, description, callout_info, NULL); + return request_key_and_link(type, description, callout_info, NULL, + KEY_ALLOC_IN_QUOTA); } /* end request_key() */ EXPORT_SYMBOL(request_key); - -/*****************************************************************************/ -/* - * validate a key - */ -int key_validate(struct key *key) -{ - struct timespec now; - int ret = 0; - - if (key) { - /* check it's still accessible */ - ret = -EKEYREVOKED; - if (test_bit(KEY_FLAG_REVOKED, &key->flags) || - test_bit(KEY_FLAG_DEAD, &key->flags)) - goto error; - - /* check it hasn't expired */ - ret = 0; - if (key->expiry) { - now = current_kernel_time(); - if (now.tv_sec >= key->expiry) - ret = -EKEYEXPIRED; - } - } - - error: - return ret; - -} /* end key_validate() */ - -EXPORT_SYMBOL(key_validate);