mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-30 10:55:03 +00:00
keys: distinguish per-uid keys in different namespaces
per-uid keys were looked by uid only. Use the user namespace to distinguish the same uid in different namespaces. This does not address key_permission. So a task can for instance try to join a keyring owned by the same uid in another namespace. That will be handled by a separate patch. Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
be38e0fd5f
commit
1d1e97562e
6 changed files with 17 additions and 6 deletions
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
struct user_namespace init_user_ns = {
|
struct user_namespace init_user_ns = {
|
||||||
.kref = {
|
.kref = {
|
||||||
.refcount = ATOMIC_INIT(1),
|
.refcount = ATOMIC_INIT(2),
|
||||||
},
|
},
|
||||||
.creator = &root_user,
|
.creator = &root_user,
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct key_user {
|
||||||
atomic_t nkeys; /* number of keys */
|
atomic_t nkeys; /* number of keys */
|
||||||
atomic_t nikeys; /* number of instantiated keys */
|
atomic_t nikeys; /* number of instantiated keys */
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
struct user_namespace *user_ns;
|
||||||
int qnkeys; /* number of keys allocated to this user */
|
int qnkeys; /* number of keys allocated to this user */
|
||||||
int qnbytes; /* number of bytes allocated to this user */
|
int qnbytes; /* number of bytes allocated to this user */
|
||||||
};
|
};
|
||||||
|
@ -61,7 +62,8 @@ extern struct rb_root key_user_tree;
|
||||||
extern spinlock_t key_user_lock;
|
extern spinlock_t key_user_lock;
|
||||||
extern struct key_user root_key_user;
|
extern struct key_user root_key_user;
|
||||||
|
|
||||||
extern struct key_user *key_user_lookup(uid_t uid);
|
extern struct key_user *key_user_lookup(uid_t uid,
|
||||||
|
struct user_namespace *user_ns);
|
||||||
extern void key_user_put(struct key_user *user);
|
extern void key_user_put(struct key_user *user);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/user_namespace.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static struct kmem_cache *key_jar;
|
static struct kmem_cache *key_jar;
|
||||||
|
@ -60,7 +61,7 @@ void __key_check(const struct key *key)
|
||||||
* get the key quota record for a user, allocating a new record if one doesn't
|
* get the key quota record for a user, allocating a new record if one doesn't
|
||||||
* already exist
|
* already exist
|
||||||
*/
|
*/
|
||||||
struct key_user *key_user_lookup(uid_t uid)
|
struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns)
|
||||||
{
|
{
|
||||||
struct key_user *candidate = NULL, *user;
|
struct key_user *candidate = NULL, *user;
|
||||||
struct rb_node *parent = NULL;
|
struct rb_node *parent = NULL;
|
||||||
|
@ -79,6 +80,10 @@ struct key_user *key_user_lookup(uid_t uid)
|
||||||
p = &(*p)->rb_left;
|
p = &(*p)->rb_left;
|
||||||
else if (uid > user->uid)
|
else if (uid > user->uid)
|
||||||
p = &(*p)->rb_right;
|
p = &(*p)->rb_right;
|
||||||
|
else if (user_ns < user->user_ns)
|
||||||
|
p = &(*p)->rb_left;
|
||||||
|
else if (user_ns > user->user_ns)
|
||||||
|
p = &(*p)->rb_right;
|
||||||
else
|
else
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +111,7 @@ struct key_user *key_user_lookup(uid_t uid)
|
||||||
atomic_set(&candidate->nkeys, 0);
|
atomic_set(&candidate->nkeys, 0);
|
||||||
atomic_set(&candidate->nikeys, 0);
|
atomic_set(&candidate->nikeys, 0);
|
||||||
candidate->uid = uid;
|
candidate->uid = uid;
|
||||||
|
candidate->user_ns = get_user_ns(user_ns);
|
||||||
candidate->qnkeys = 0;
|
candidate->qnkeys = 0;
|
||||||
candidate->qnbytes = 0;
|
candidate->qnbytes = 0;
|
||||||
spin_lock_init(&candidate->lock);
|
spin_lock_init(&candidate->lock);
|
||||||
|
@ -136,6 +142,7 @@ void key_user_put(struct key_user *user)
|
||||||
if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
|
if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
|
||||||
rb_erase(&user->node, &key_user_tree);
|
rb_erase(&user->node, &key_user_tree);
|
||||||
spin_unlock(&key_user_lock);
|
spin_unlock(&key_user_lock);
|
||||||
|
put_user_ns(user->user_ns);
|
||||||
|
|
||||||
kfree(user);
|
kfree(user);
|
||||||
}
|
}
|
||||||
|
@ -234,7 +241,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||||
quotalen = desclen + type->def_datalen;
|
quotalen = desclen + type->def_datalen;
|
||||||
|
|
||||||
/* get hold of the key tracking for this user */
|
/* get hold of the key tracking for this user */
|
||||||
user = key_user_lookup(uid);
|
user = key_user_lookup(uid, cred->user->user_ns);
|
||||||
if (!user)
|
if (!user)
|
||||||
goto no_memory_1;
|
goto no_memory_1;
|
||||||
|
|
||||||
|
|
|
@ -726,7 +726,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
|
||||||
/* change the UID */
|
/* change the UID */
|
||||||
if (uid != (uid_t) -1 && uid != key->uid) {
|
if (uid != (uid_t) -1 && uid != key->uid) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
newowner = key_user_lookup(uid);
|
newowner = key_user_lookup(uid, current_user_ns());
|
||||||
if (!newowner)
|
if (!newowner)
|
||||||
goto error_put;
|
goto error_put;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/user_namespace.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ struct key_user root_key_user = {
|
||||||
.nkeys = ATOMIC_INIT(2),
|
.nkeys = ATOMIC_INIT(2),
|
||||||
.nikeys = ATOMIC_INIT(2),
|
.nikeys = ATOMIC_INIT(2),
|
||||||
.uid = 0,
|
.uid = 0,
|
||||||
|
.user_ns = &init_user_ns,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
@ -365,7 +365,7 @@ static struct key *construct_key_and_link(struct key_type *type,
|
||||||
|
|
||||||
kenter("");
|
kenter("");
|
||||||
|
|
||||||
user = key_user_lookup(current_fsuid());
|
user = key_user_lookup(current_fsuid(), current_user_ns());
|
||||||
if (!user)
|
if (!user)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue