Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[powerpc.git] / kernel / user.c
index 2116642..220e586 100644 (file)
@@ -140,7 +140,7 @@ struct user_struct * alloc_uid(uid_t uid)
                atomic_set(&new->processes, 0);
                atomic_set(&new->files, 0);
                atomic_set(&new->sigpending, 0);
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
                atomic_set(&new->inotify_watches, 0);
                atomic_set(&new->inotify_devs, 0);
 #endif
@@ -148,7 +148,7 @@ struct user_struct * alloc_uid(uid_t uid)
                new->mq_bytes = 0;
                new->locked_shm = 0;
 
-               if (alloc_uid_keyring(new) < 0) {
+               if (alloc_uid_keyring(new, current) < 0) {
                        kmem_cache_free(uid_cachep, new);
                        return NULL;
                }
@@ -187,6 +187,17 @@ void switch_uid(struct user_struct *new_user)
        atomic_dec(&old_user->processes);
        switch_uid_keyring(new_user);
        current->user = new_user;
+
+       /*
+        * We need to synchronize with __sigqueue_alloc()
+        * doing a get_uid(p->user).. If that saw the old
+        * user value, we need to wait until it has exited
+        * its critical region before we can free the old
+        * structure.
+        */
+       smp_mb();
+       spin_unlock_wait(&current->sighand->siglock);
+
        free_uid(old_user);
        suid_keys(current);
 }