Commit 93b9c98b authored by James Morris's avatar James Morris

Merge branch 'next-queue' into next

parents efb3bb4f 58068960
...@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key) ...@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key)
return key ? key->serial : 0; return key ? key->serial : 0;
} }
/**
* key_is_instantiated - Determine if a key has been positively instantiated
* @key: The key to check.
*
* Return true if the specified key has been positively instantiated, false
* otherwise.
*/
static inline bool key_is_instantiated(const struct key *key)
{
return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
!test_bit(KEY_FLAG_NEGATIVE, &key->flags);
}
#define rcu_dereference_key(KEY) \ #define rcu_dereference_key(KEY) \
(rcu_dereference_protected((KEY)->payload.rcudata, \ (rcu_dereference_protected((KEY)->payload.rcudata, \
rwsem_is_locked(&((struct key *)(KEY))->sem))) rwsem_is_locked(&((struct key *)(KEY))->sem)))
......
...@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m) ...@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m)
int err = key->type_data.x[0]; int err = key->type_data.x[0];
seq_puts(m, key->description); seq_puts(m, key->description);
if (err) if (key_is_instantiated(key)) {
seq_printf(m, ": %d", err); if (err)
else seq_printf(m, ": %d", err);
seq_printf(m, ": %u", key->datalen); else
seq_printf(m, ": %u", key->datalen);
}
} }
/* /*
......
...@@ -167,6 +167,7 @@ config INTEL_TXT ...@@ -167,6 +167,7 @@ config INTEL_TXT
config LSM_MMAP_MIN_ADDR config LSM_MMAP_MIN_ADDR
int "Low address space for LSM to protect from user allocation" int "Low address space for LSM to protect from user allocation"
depends on SECURITY && SECURITY_SELINUX depends on SECURITY && SECURITY_SELINUX
default 32768 if ARM
default 65536 default 65536
help help
This is the portion of low virtual memory which should be protected This is the portion of low virtual memory which should be protected
......
...@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
const struct cred *cred, const struct cred *cred,
struct key_type *type, struct key_type *type,
const void *description, const void *description,
key_match_func_t match); key_match_func_t match,
bool no_state_check);
extern key_ref_t search_my_process_keyrings(struct key_type *type, extern key_ref_t search_my_process_keyrings(struct key_type *type,
const void *description, const void *description,
key_match_func_t match, key_match_func_t match,
bool no_state_check,
const struct cred *cred); const struct cred *cred);
extern key_ref_t search_process_keyrings(struct key_type *type, extern key_ref_t search_process_keyrings(struct key_type *type,
const void *description, const void *description,
......
...@@ -206,8 +206,14 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, ...@@ -206,8 +206,14 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
goto error5; goto error5;
} }
/* wait for the key to finish being constructed */
ret = wait_for_key_construction(key, 1);
if (ret < 0)
goto error6;
ret = key->serial; ret = key->serial;
error6:
key_put(key); key_put(key);
error5: error5:
key_type_put(ktype); key_type_put(ktype);
......
...@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) ...@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
else else
seq_puts(m, "[anon]"); seq_puts(m, "[anon]");
rcu_read_lock(); if (key_is_instantiated(keyring)) {
klist = rcu_dereference(keyring->payload.subscriptions); rcu_read_lock();
if (klist) klist = rcu_dereference(keyring->payload.subscriptions);
seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); if (klist)
else seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
seq_puts(m, ": empty"); else
rcu_read_unlock(); seq_puts(m, ": empty");
rcu_read_unlock();
}
} }
/* /*
...@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, ...@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
* @type: The type of key to search for. * @type: The type of key to search for.
* @description: Parameter for @match. * @description: Parameter for @match.
* @match: Function to rule on whether or not a key is the one required. * @match: Function to rule on whether or not a key is the one required.
* @no_state_check: Don't check if a matching key is bad
* *
* Search the supplied keyring tree for a key that matches the criteria given. * Search the supplied keyring tree for a key that matches the criteria given.
* The root keyring and any linked keyrings must grant Search permission to the * The root keyring and any linked keyrings must grant Search permission to the
...@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
const struct cred *cred, const struct cred *cred,
struct key_type *type, struct key_type *type,
const void *description, const void *description,
key_match_func_t match) key_match_func_t match,
bool no_state_check)
{ {
struct { struct {
struct keyring_list *keylist; struct keyring_list *keylist;
...@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
kflags = keyring->flags; kflags = keyring->flags;
if (keyring->type == type && match(keyring, description)) { if (keyring->type == type && match(keyring, description)) {
key = keyring; key = keyring;
if (no_state_check)
goto found;
/* check it isn't negative and hasn't expired or been /* check it isn't negative and hasn't expired or been
* revoked */ * revoked */
...@@ -384,11 +390,13 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -384,11 +390,13 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
continue; continue;
/* skip revoked keys and expired keys */ /* skip revoked keys and expired keys */
if (kflags & (1 << KEY_FLAG_REVOKED)) if (!no_state_check) {
continue; if (kflags & (1 << KEY_FLAG_REVOKED))
continue;
if (key->expiry && now.tv_sec >= key->expiry) if (key->expiry && now.tv_sec >= key->expiry)
continue; continue;
}
/* keys that don't match */ /* keys that don't match */
if (!match(key, description)) if (!match(key, description))
...@@ -399,6 +407,9 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -399,6 +407,9 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
cred, KEY_SEARCH) < 0) cred, KEY_SEARCH) < 0)
continue; continue;
if (no_state_check)
goto found;
/* we set a different error code if we pass a negative key */ /* we set a different error code if we pass a negative key */
if (kflags & (1 << KEY_FLAG_NEGATIVE)) { if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
err = key->type_data.reject_error; err = key->type_data.reject_error;
...@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring, ...@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring,
return ERR_PTR(-ENOKEY); return ERR_PTR(-ENOKEY);
return keyring_search_aux(keyring, current->cred, return keyring_search_aux(keyring, current->cred,
type, description, type->match); type, description, type->match, false);
} }
EXPORT_SYMBOL(keyring_search); EXPORT_SYMBOL(keyring_search);
......
...@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
if (key->perm & KEY_POS_VIEW) { if (key->perm & KEY_POS_VIEW) {
skey_ref = search_my_process_keyrings(key->type, key, skey_ref = search_my_process_keyrings(key->type, key,
lookup_user_key_possessed, lookup_user_key_possessed,
cred); true, cred);
if (!IS_ERR(skey_ref)) { if (!IS_ERR(skey_ref)) {
key_ref_put(skey_ref); key_ref_put(skey_ref);
key_ref = make_key_ref(key, 1); key_ref = make_key_ref(key, 1);
......
...@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk) ...@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk)
key_ref_t search_my_process_keyrings(struct key_type *type, key_ref_t search_my_process_keyrings(struct key_type *type,
const void *description, const void *description,
key_match_func_t match, key_match_func_t match,
bool no_state_check,
const struct cred *cred) const struct cred *cred)
{ {
key_ref_t key_ref, ret, err; key_ref_t key_ref, ret, err;
...@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
if (cred->thread_keyring) { if (cred->thread_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(cred->thread_keyring, 1), make_key_ref(cred->thread_keyring, 1),
cred, type, description, match); cred, type, description, match, no_state_check);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
if (cred->tgcred->process_keyring) { if (cred->tgcred->process_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(cred->tgcred->process_keyring, 1), make_key_ref(cred->tgcred->process_keyring, 1),
cred, type, description, match); cred, type, description, match, no_state_check);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
make_key_ref(rcu_dereference( make_key_ref(rcu_dereference(
cred->tgcred->session_keyring), cred->tgcred->session_keyring),
1), 1),
cred, type, description, match); cred, type, description, match, no_state_check);
rcu_read_unlock(); rcu_read_unlock();
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
...@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
else if (cred->user->session_keyring) { else if (cred->user->session_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(cred->user->session_keyring, 1), make_key_ref(cred->user->session_keyring, 1),
cred, type, description, match); cred, type, description, match, no_state_check);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
might_sleep(); might_sleep();
key_ref = search_my_process_keyrings(type, description, match, cred); key_ref = search_my_process_keyrings(type, description, match,
false, cred);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
err = key_ref; err = key_ref;
......
...@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type, ...@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type,
dest_keyring, flags); dest_keyring, flags);
/* search all the process keyrings for a key */ /* search all the process keyrings for a key */
key_ref = search_process_keyrings(type, description, type->match, key_ref = search_process_keyrings(type, description, type->match, cred);
cred);
if (!IS_ERR(key_ref)) { if (!IS_ERR(key_ref)) {
key = key_ref_to_ptr(key_ref); key = key_ref_to_ptr(key_ref);
......
...@@ -59,7 +59,8 @@ static void request_key_auth_describe(const struct key *key, ...@@ -59,7 +59,8 @@ 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, rka->callout_len); if (key_is_instantiated(key))
seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
} }
/* /*
......
...@@ -169,8 +169,8 @@ EXPORT_SYMBOL_GPL(user_destroy); ...@@ -169,8 +169,8 @@ EXPORT_SYMBOL_GPL(user_destroy);
void user_describe(const struct key *key, struct seq_file *m) void user_describe(const struct key *key, struct seq_file *m)
{ {
seq_puts(m, key->description); seq_puts(m, key->description);
if (key_is_instantiated(key))
seq_printf(m, ": %u", key->datalen); seq_printf(m, ": %u", key->datalen);
} }
EXPORT_SYMBOL_GPL(user_describe); EXPORT_SYMBOL_GPL(user_describe);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment