userns: Convert security/keys to the new userns infrastructure
- Replace key_user ->user_ns equality checks with kuid_has_mapping checks. - Use from_kuid to generate key descriptions - Use kuid_t and kgid_t and the associated helpers instead of uid_t and gid_t - Avoid potential problems with file descriptor passing by displaying keys in the user namespace of the opener of key status proc files. Cc: linux-security-module@vger.kernel.org Cc: keyrings@linux-nfs.org Cc: David Howells <dhowells@redhat.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include "internal.h"
|
||||
|
||||
struct kmem_cache *key_jar;
|
||||
@@ -52,7 +51,7 @@ void __key_check(const struct key *key)
|
||||
* Get the key quota record for a user, allocating a new record if one doesn't
|
||||
* already exist.
|
||||
*/
|
||||
struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns)
|
||||
struct key_user *key_user_lookup(kuid_t uid)
|
||||
{
|
||||
struct key_user *candidate = NULL, *user;
|
||||
struct rb_node *parent = NULL;
|
||||
@@ -67,13 +66,9 @@ try_again:
|
||||
parent = *p;
|
||||
user = rb_entry(parent, struct key_user, node);
|
||||
|
||||
if (uid < user->uid)
|
||||
if (uid_lt(uid, user->uid))
|
||||
p = &(*p)->rb_left;
|
||||
else if (uid > user->uid)
|
||||
p = &(*p)->rb_right;
|
||||
else if (user_ns < user->user_ns)
|
||||
p = &(*p)->rb_left;
|
||||
else if (user_ns > user->user_ns)
|
||||
else if (uid_gt(uid, user->uid))
|
||||
p = &(*p)->rb_right;
|
||||
else
|
||||
goto found;
|
||||
@@ -102,7 +97,6 @@ try_again:
|
||||
atomic_set(&candidate->nkeys, 0);
|
||||
atomic_set(&candidate->nikeys, 0);
|
||||
candidate->uid = uid;
|
||||
candidate->user_ns = get_user_ns(user_ns);
|
||||
candidate->qnkeys = 0;
|
||||
candidate->qnbytes = 0;
|
||||
spin_lock_init(&candidate->lock);
|
||||
@@ -131,7 +125,6 @@ void key_user_put(struct key_user *user)
|
||||
if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
|
||||
rb_erase(&user->node, &key_user_tree);
|
||||
spin_unlock(&key_user_lock);
|
||||
put_user_ns(user->user_ns);
|
||||
|
||||
kfree(user);
|
||||
}
|
||||
@@ -229,7 +222,7 @@ serial_exists:
|
||||
* key_alloc() calls don't race with module unloading.
|
||||
*/
|
||||
struct key *key_alloc(struct key_type *type, const char *desc,
|
||||
uid_t uid, gid_t gid, const struct cred *cred,
|
||||
kuid_t uid, kgid_t gid, const struct cred *cred,
|
||||
key_perm_t perm, unsigned long flags)
|
||||
{
|
||||
struct key_user *user = NULL;
|
||||
@@ -253,16 +246,16 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||
quotalen = desclen + type->def_datalen;
|
||||
|
||||
/* get hold of the key tracking for this user */
|
||||
user = key_user_lookup(uid, cred->user_ns);
|
||||
user = key_user_lookup(uid);
|
||||
if (!user)
|
||||
goto no_memory_1;
|
||||
|
||||
/* check that the user's quota permits allocation of another key and
|
||||
* its description */
|
||||
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
|
||||
unsigned maxkeys = (uid == 0) ?
|
||||
unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ?
|
||||
key_quota_root_maxkeys : key_quota_maxkeys;
|
||||
unsigned maxbytes = (uid == 0) ?
|
||||
unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
|
||||
key_quota_root_maxbytes : key_quota_maxbytes;
|
||||
|
||||
spin_lock(&user->lock);
|
||||
@@ -380,7 +373,7 @@ int key_payload_reserve(struct key *key, size_t datalen)
|
||||
|
||||
/* contemplate the quota adjustment */
|
||||
if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
|
||||
unsigned maxbytes = (key->user->uid == 0) ?
|
||||
unsigned maxbytes = uid_eq(key->user->uid, GLOBAL_ROOT_UID) ?
|
||||
key_quota_root_maxbytes : key_quota_maxbytes;
|
||||
|
||||
spin_lock(&key->user->lock);
|
||||
|
||||
Reference in New Issue
Block a user