diff options
Diffstat (limited to 'kernel/user.c')
| -rw-r--r-- | kernel/user.c | 51 | 
1 files changed, 33 insertions, 18 deletions
diff --git a/kernel/user.c b/kernel/user.c index 71dd2363ab0..b815fefbe76 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -22,10 +22,27 @@   * and 1 for... ?   */  struct user_namespace init_user_ns = { +	.uid_map = { +		.nr_extents = 1, +		.extent[0] = { +			.first = 0, +			.lower_first = 0, +			.count = 4294967295U, +		}, +	}, +	.gid_map = { +		.nr_extents = 1, +		.extent[0] = { +			.first = 0, +			.lower_first = 0, +			.count = 4294967295U, +		}, +	},  	.kref = {  		.refcount	= ATOMIC_INIT(3),  	}, -	.creator = &root_user, +	.owner = GLOBAL_ROOT_UID, +	.group = GLOBAL_ROOT_GID,  };  EXPORT_SYMBOL_GPL(init_user_ns); @@ -34,11 +51,14 @@ EXPORT_SYMBOL_GPL(init_user_ns);   * when changing user ID's (ie setuid() and friends).   */ +#define UIDHASH_BITS	(CONFIG_BASE_SMALL ? 3 : 7) +#define UIDHASH_SZ	(1 << UIDHASH_BITS)  #define UIDHASH_MASK		(UIDHASH_SZ - 1)  #define __uidhashfn(uid)	(((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK) -#define uidhashentry(ns, uid)	((ns)->uidhash_table + __uidhashfn((uid))) +#define uidhashentry(uid)	(uidhash_table + __uidhashfn((__kuid_val(uid))))  static struct kmem_cache *uid_cachep; +struct hlist_head uidhash_table[UIDHASH_SZ];  /*   * The uidhash_lock is mostly taken from process context, but it is @@ -51,14 +71,14 @@ static struct kmem_cache *uid_cachep;   */  static DEFINE_SPINLOCK(uidhash_lock); -/* root_user.__count is 2, 1 for init task cred, 1 for init_user_ns->user_ns */ +/* root_user.__count is 1, for init task cred */  struct user_struct root_user = { -	.__count	= ATOMIC_INIT(2), +	.__count	= ATOMIC_INIT(1),  	.processes	= ATOMIC_INIT(1),  	.files		= ATOMIC_INIT(0),  	.sigpending	= ATOMIC_INIT(0),  	.locked_shm     = 0, -	.user_ns	= &init_user_ns, +	.uid		= GLOBAL_ROOT_UID,  };  /* @@ -72,16 +92,15 @@ static void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent)  static void uid_hash_remove(struct user_struct *up)  {  	hlist_del_init(&up->uidhash_node); -	put_user_ns(up->user_ns);  } -static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) +static struct user_struct *uid_hash_find(kuid_t uid, struct hlist_head *hashent)  {  	struct user_struct *user;  	struct hlist_node *h;  	hlist_for_each_entry(user, h, hashent, uidhash_node) { -		if (user->uid == uid) { +		if (uid_eq(user->uid, uid)) {  			atomic_inc(&user->__count);  			return user;  		} @@ -110,14 +129,13 @@ static void free_user(struct user_struct *up, unsigned long flags)   *   * If the user_struct could not be found, return NULL.   */ -struct user_struct *find_user(uid_t uid) +struct user_struct *find_user(kuid_t uid)  {  	struct user_struct *ret;  	unsigned long flags; -	struct user_namespace *ns = current_user_ns();  	spin_lock_irqsave(&uidhash_lock, flags); -	ret = uid_hash_find(uid, uidhashentry(ns, uid)); +	ret = uid_hash_find(uid, uidhashentry(uid));  	spin_unlock_irqrestore(&uidhash_lock, flags);  	return ret;  } @@ -136,9 +154,9 @@ void free_uid(struct user_struct *up)  		local_irq_restore(flags);  } -struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) +struct user_struct *alloc_uid(kuid_t uid)  { -	struct hlist_head *hashent = uidhashentry(ns, uid); +	struct hlist_head *hashent = uidhashentry(uid);  	struct user_struct *up, *new;  	spin_lock_irq(&uidhash_lock); @@ -153,8 +171,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)  		new->uid = uid;  		atomic_set(&new->__count, 1); -		new->user_ns = get_user_ns(ns); -  		/*  		 * Before adding this, check whether we raced  		 * on adding the same user already.. @@ -162,7 +178,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)  		spin_lock_irq(&uidhash_lock);  		up = uid_hash_find(uid, hashent);  		if (up) { -			put_user_ns(ns);  			key_put(new->uid_keyring);  			key_put(new->session_keyring);  			kmem_cache_free(uid_cachep, new); @@ -187,11 +202,11 @@ static int __init uid_cache_init(void)  			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);  	for(n = 0; n < UIDHASH_SZ; ++n) -		INIT_HLIST_HEAD(init_user_ns.uidhash_table + n); +		INIT_HLIST_HEAD(uidhash_table + n);  	/* Insert the root user immediately (init already runs as root) */  	spin_lock_irq(&uidhash_lock); -	uid_hash_insert(&root_user, uidhashentry(&init_user_ns, 0)); +	uid_hash_insert(&root_user, uidhashentry(GLOBAL_ROOT_UID));  	spin_unlock_irq(&uidhash_lock);  	return 0;  |