diff options
Diffstat (limited to 'kernel/user.c')
| -rw-r--r-- | kernel/user.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/kernel/user.c b/kernel/user.c index e7d11cef6998..9ca2848fc356 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
| @@ -55,25 +55,22 @@ struct user_struct root_user = { | |||
| 55 | /* | 55 | /* |
| 56 | * These routines must be called with the uidhash spinlock held! | 56 | * These routines must be called with the uidhash spinlock held! |
| 57 | */ | 57 | */ |
| 58 | static inline void uid_hash_insert(struct user_struct *up, struct list_head *hashent) | 58 | static inline void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent) |
| 59 | { | 59 | { |
| 60 | list_add(&up->uidhash_list, hashent); | 60 | hlist_add_head(&up->uidhash_node, hashent); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static inline void uid_hash_remove(struct user_struct *up) | 63 | static inline void uid_hash_remove(struct user_struct *up) |
| 64 | { | 64 | { |
| 65 | list_del(&up->uidhash_list); | 65 | hlist_del_init(&up->uidhash_node); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *hashent) | 68 | static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) |
| 69 | { | 69 | { |
| 70 | struct list_head *up; | 70 | struct user_struct *user; |
| 71 | 71 | struct hlist_node *h; | |
| 72 | list_for_each(up, hashent) { | ||
| 73 | struct user_struct *user; | ||
| 74 | |||
| 75 | user = list_entry(up, struct user_struct, uidhash_list); | ||
| 76 | 72 | ||
| 73 | hlist_for_each_entry(user, h, hashent, uidhash_node) { | ||
| 77 | if(user->uid == uid) { | 74 | if(user->uid == uid) { |
| 78 | atomic_inc(&user->__count); | 75 | atomic_inc(&user->__count); |
| 79 | return user; | 76 | return user; |
| @@ -122,7 +119,7 @@ void free_uid(struct user_struct *up) | |||
| 122 | 119 | ||
| 123 | struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) | 120 | struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) |
| 124 | { | 121 | { |
| 125 | struct list_head *hashent = uidhashentry(ns, uid); | 122 | struct hlist_head *hashent = uidhashentry(ns, uid); |
| 126 | struct user_struct *up; | 123 | struct user_struct *up; |
| 127 | 124 | ||
| 128 | spin_lock_irq(&uidhash_lock); | 125 | spin_lock_irq(&uidhash_lock); |
| @@ -202,6 +199,30 @@ void switch_uid(struct user_struct *new_user) | |||
| 202 | suid_keys(current); | 199 | suid_keys(current); |
| 203 | } | 200 | } |
| 204 | 201 | ||
| 202 | void release_uids(struct user_namespace *ns) | ||
| 203 | { | ||
| 204 | int i; | ||
| 205 | unsigned long flags; | ||
| 206 | struct hlist_head *head; | ||
| 207 | struct hlist_node *nd; | ||
| 208 | |||
| 209 | spin_lock_irqsave(&uidhash_lock, flags); | ||
| 210 | /* | ||
| 211 | * collapse the chains so that the user_struct-s will | ||
| 212 | * be still alive, but not in hashes. subsequent free_uid() | ||
| 213 | * will free them. | ||
| 214 | */ | ||
| 215 | for (i = 0; i < UIDHASH_SZ; i++) { | ||
| 216 | head = ns->uidhash_table + i; | ||
| 217 | while (!hlist_empty(head)) { | ||
| 218 | nd = head->first; | ||
| 219 | hlist_del_init(nd); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | spin_unlock_irqrestore(&uidhash_lock, flags); | ||
| 223 | |||
| 224 | free_uid(ns->root_user); | ||
| 225 | } | ||
| 205 | 226 | ||
| 206 | static int __init uid_cache_init(void) | 227 | static int __init uid_cache_init(void) |
| 207 | { | 228 | { |
| @@ -211,7 +232,7 @@ static int __init uid_cache_init(void) | |||
| 211 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 232 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); |
| 212 | 233 | ||
| 213 | for(n = 0; n < UIDHASH_SZ; ++n) | 234 | for(n = 0; n < UIDHASH_SZ; ++n) |
| 214 | INIT_LIST_HEAD(init_user_ns.uidhash_table + n); | 235 | INIT_HLIST_HEAD(init_user_ns.uidhash_table + n); |
| 215 | 236 | ||
| 216 | /* Insert the root user immediately (init already runs as root) */ | 237 | /* Insert the root user immediately (init already runs as root) */ |
| 217 | spin_lock_irq(&uidhash_lock); | 238 | spin_lock_irq(&uidhash_lock); |
