Fix user namespace exiting OOPs
[sfrench/cifs-2.6.git] / kernel / user.c
index add57c7e4c074237572da1b9beaf4592b4488896..9ca2848fc35676fa8ebac52f20c33f7f056d09ff 100644 (file)
@@ -62,7 +62,7 @@ static inline void uid_hash_insert(struct user_struct *up, struct hlist_head *ha
 
 static inline void uid_hash_remove(struct user_struct *up)
 {
-       hlist_del(&up->uidhash_node);
+       hlist_del_init(&up->uidhash_node);
 }
 
 static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
@@ -199,6 +199,30 @@ void switch_uid(struct user_struct *new_user)
        suid_keys(current);
 }
 
+void release_uids(struct user_namespace *ns)
+{
+       int i;
+       unsigned long flags;
+       struct hlist_head *head;
+       struct hlist_node *nd;
+
+       spin_lock_irqsave(&uidhash_lock, flags);
+       /*
+        * collapse the chains so that the user_struct-s will
+        * be still alive, but not in hashes. subsequent free_uid()
+        * will free them.
+        */
+       for (i = 0; i < UIDHASH_SZ; i++) {
+               head = ns->uidhash_table + i;
+               while (!hlist_empty(head)) {
+                       nd = head->first;
+                       hlist_del_init(nd);
+               }
+       }
+       spin_unlock_irqrestore(&uidhash_lock, flags);
+
+       free_uid(ns->root_user);
+}
 
 static int __init uid_cache_init(void)
 {