Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[linux-2.6-microblaze.git] / kernel / signal.c
index de09203..a3229ad 100644 (file)
@@ -426,18 +426,30 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t gfp_flags,
        rcu_read_lock();
        ucounts = task_ucounts(t);
        sigpending = inc_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING, 1);
-       if (sigpending == 1)
-               ucounts = get_ucounts(ucounts);
+       switch (sigpending) {
+       case 1:
+               if (likely(get_ucounts(ucounts)))
+                       break;
+               fallthrough;
+       case LONG_MAX:
+               /*
+                * we need to decrease the ucount in the userns tree on any
+                * failure to avoid counts leaking.
+                */
+               dec_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING, 1);
+               rcu_read_unlock();
+               return NULL;
+       }
        rcu_read_unlock();
 
-       if (override_rlimit || (sigpending < LONG_MAX && sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) {
+       if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) {
                q = kmem_cache_alloc(sigqueue_cachep, gfp_flags);
        } else {
                print_dropped_signal(sig);
        }
 
        if (unlikely(q == NULL)) {
-               if (ucounts && dec_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING, 1))
+               if (dec_rlimit_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING, 1))
                        put_ucounts(ucounts);
        } else {
                INIT_LIST_HEAD(&q->list);
@@ -2830,6 +2842,8 @@ static void signal_delivered(struct ksignal *ksig, int stepping)
        if (!(ksig->ka.sa.sa_flags & SA_NODEFER))
                sigaddset(&blocked, ksig->sig);
        set_current_blocked(&blocked);
+       if (current->sas_ss_flags & SS_AUTODISARM)
+               sas_ss_reset(current);
        tracehook_signal_handler(stepping);
 }
 
@@ -4148,11 +4162,7 @@ int __save_altstack(stack_t __user *uss, unsigned long sp)
        int err = __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) |
                __put_user(t->sas_ss_flags, &uss->ss_flags) |
                __put_user(t->sas_ss_size, &uss->ss_size);
-       if (err)
-               return err;
-       if (t->sas_ss_flags & SS_AUTODISARM)
-               sas_ss_reset(t);
-       return 0;
+       return err;
 }
 
 #ifdef CONFIG_COMPAT
@@ -4207,11 +4217,7 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp)
                         &uss->ss_sp) |
                __put_user(t->sas_ss_flags, &uss->ss_flags) |
                __put_user(t->sas_ss_size, &uss->ss_size);
-       if (err)
-               return err;
-       if (t->sas_ss_flags & SS_AUTODISARM)
-               sas_ss_reset(t);
-       return 0;
+       return err;
 }
 #endif