Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Linus Torvalds [Sun, 24 Feb 2013 02:50:11 +0000 (18:50 -0800)]
Pull signal handling cleanups from Al Viro:
 "This is the first pile; another one will come a bit later and will
  contain SYSCALL_DEFINE-related patches.

   - a bunch of signal-related syscalls (both native and compat)
     unified.

   - a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE
     (fixing several potential problems with missing argument
     validation, while we are at it)

   - a lot of now-pointless wrappers killed

   - a couple of architectures (cris and hexagon) forgot to save
     altstack settings into sigframe, even though they used the
     (uninitialized) values in sigreturn; fixed.

   - microblaze fixes for delivery of multiple signals arriving at once

   - saner set of helpers for signal delivery introduced, several
     architectures switched to using those."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits)
  x86: convert to ksignal
  sparc: convert to ksignal
  arm: switch to struct ksignal * passing
  alpha: pass k_sigaction and siginfo_t using ksignal pointer
  burying unused conditionals
  make do_sigaltstack() static
  arm64: switch to generic old sigaction() (compat-only)
  arm64: switch to generic compat rt_sigaction()
  arm64: switch compat to generic old sigsuspend
  arm64: switch to generic compat rt_sigqueueinfo()
  arm64: switch to generic compat rt_sigpending()
  arm64: switch to generic compat rt_sigprocmask()
  arm64: switch to generic sigaltstack
  sparc: switch to generic old sigsuspend
  sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE
  sparc: kill sign-extending wrappers for native syscalls
  kill sparc32_open()
  sparc: switch to use of generic old sigaction
  sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE
  mips: switch to generic sys_fork() and sys_clone()
  ...

29 files changed:
1  2 
arch/Kconfig
arch/alpha/Kconfig
arch/arm/Kconfig
arch/arm64/Kconfig
arch/arm64/kernel/signal32.c
arch/frv/Kconfig
arch/m68k/include/asm/unistd.h
arch/mips/Kconfig
arch/parisc/include/asm/signal.h
arch/parisc/include/asm/unistd.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/signal.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/Kconfig
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/s390/Kconfig
arch/sh/Kconfig
arch/sparc/Kconfig
arch/x86/Kconfig
arch/x86/ia32/ia32entry.S
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/um/Kconfig
include/linux/sched.h
kernel/compat.c
kernel/futex_compat.c
kernel/signal.c

diff --cc arch/Kconfig
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -703,13 -560,9 +560,9 @@@ int compat_setup_rt_frame(int usig, str
        err |= copy_siginfo_to_user32(&frame->info, info);
  
        __put_user_error(0, &frame->sig.uc.uc_flags, err);
 -      __put_user_error(NULL, &frame->sig.uc.uc_link, err);
 +      __put_user_error(0, &frame->sig.uc.uc_link, err);
  
-       memset(&stack, 0, sizeof(stack));
-       stack.ss_sp = (compat_uptr_t)current->sas_ss_sp;
-       stack.ss_flags = sas_ss_flags(regs->compat_sp);
-       stack.ss_size = current->sas_ss_size;
-       err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
+       err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->compat_sp);
  
        err |= compat_setup_sigframe(&frame->sig, regs, set);
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -142,7 -144,8 +142,9 @@@ config PP
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS
 +      select ARCH_USE_BUILTIN_BSWAP
+       select OLD_SIGSUSPEND
+       select OLD_SIGACTION if PPC32
  
  config EARLY_PRINTK
        bool
Simple merge
@@@ -817,223 -513,7 +742,140 @@@ static long restore_user_regs(struct pt
        return 0;
  }
  
 +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 +/*
 + * Restore the current user register values from the user stack, except for
 + * MSR, and recheckpoint the original checkpointed register state for processes
 + * in transactions.
 + */
 +static long restore_tm_user_regs(struct pt_regs *regs,
 +                               struct mcontext __user *sr,
 +                               struct mcontext __user *tm_sr)
 +{
 +      long err;
 +      unsigned long msr;
 +#ifdef CONFIG_VSX
 +      int i;
 +#endif
 +
 +      /*
 +       * restore general registers but not including MSR or SOFTE. Also
 +       * take care of keeping r2 (TLS) intact if not a signal.
 +       * See comment in signal_64.c:restore_tm_sigcontexts();
 +       * TFHAR is restored from the checkpointed NIP; TEXASR and TFIAR
 +       * were set by the signal delivery.
 +       */
 +      err = restore_general_regs(regs, tm_sr);
 +      err |= restore_general_regs(&current->thread.ckpt_regs, sr);
 +
 +      err |= __get_user(current->thread.tm_tfhar, &sr->mc_gregs[PT_NIP]);
 +
 +      err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
 +      if (err)
 +              return 1;
 +
 +      /* Restore the previous little-endian mode */
 +      regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
 +
 +      /*
 +       * Do this before updating the thread state in
 +       * current->thread.fpr/vr/evr.  That way, if we get preempted
 +       * and another task grabs the FPU/Altivec/SPE, it won't be
 +       * tempted to save the current CPU state into the thread_struct
 +       * and corrupt what we are writing there.
 +       */
 +      discard_lazy_cpu_state();
 +
 +#ifdef CONFIG_ALTIVEC
 +      regs->msr &= ~MSR_VEC;
 +      if (msr & MSR_VEC) {
 +              /* restore altivec registers from the stack */
 +              if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
 +                                   sizeof(sr->mc_vregs)) ||
 +                  __copy_from_user(current->thread.transact_vr,
 +                                   &tm_sr->mc_vregs,
 +                                   sizeof(sr->mc_vregs)))
 +                      return 1;
 +      } else if (current->thread.used_vr) {
 +              memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
 +              memset(current->thread.transact_vr, 0,
 +                     ELF_NVRREG * sizeof(vector128));
 +      }
 +
 +      /* Always get VRSAVE back */
 +      if (__get_user(current->thread.vrsave,
 +                     (u32 __user *)&sr->mc_vregs[32]) ||
 +          __get_user(current->thread.transact_vrsave,
 +                     (u32 __user *)&tm_sr->mc_vregs[32]))
 +              return 1;
 +#endif /* CONFIG_ALTIVEC */
 +
 +      regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
 +
 +      if (copy_fpr_from_user(current, &sr->mc_fregs) ||
 +          copy_transact_fpr_from_user(current, &tm_sr->mc_fregs))
 +              return 1;
 +
 +#ifdef CONFIG_VSX
 +      regs->msr &= ~MSR_VSX;
 +      if (msr & MSR_VSX) {
 +              /*
 +               * Restore altivec registers from the stack to a local
 +               * buffer, then write this out to the thread_struct
 +               */
 +              if (copy_vsx_from_user(current, &sr->mc_vsregs) ||
 +                  copy_transact_vsx_from_user(current, &tm_sr->mc_vsregs))
 +                      return 1;
 +      } else if (current->thread.used_vsr)
 +              for (i = 0; i < 32 ; i++) {
 +                      current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
 +                      current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0;
 +              }
 +#endif /* CONFIG_VSX */
 +
 +#ifdef CONFIG_SPE
 +      /* SPE regs are not checkpointed with TM, so this section is
 +       * simply the same as in restore_user_regs().
 +       */
 +      regs->msr &= ~MSR_SPE;
 +      if (msr & MSR_SPE) {
 +              if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
 +                                   ELF_NEVRREG * sizeof(u32)))
 +                      return 1;
 +      } else if (current->thread.used_spe)
 +              memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
 +
 +      /* Always get SPEFSCR back */
 +      if (__get_user(current->thread.spefscr, (u32 __user *)&sr->mc_vregs
 +                     + ELF_NEVRREG))
 +              return 1;
 +#endif /* CONFIG_SPE */
 +
 +      /* Now, recheckpoint.  This loads up all of the checkpointed (older)
 +       * registers, including FP and V[S]Rs.  After recheckpointing, the
 +       * transactional versions should be loaded.
 +       */
 +      tm_enable();
 +      /* This loads the checkpointed FP/VEC state, if used */
 +      tm_recheckpoint(&current->thread, msr);
 +      /* The task has moved into TM state S, so ensure MSR reflects this */
 +      regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S;
 +
 +      /* This loads the speculative FP/VEC state, if used */
 +      if (msr & MSR_FP) {
 +              do_load_up_transact_fpu(&current->thread);
 +              regs->msr |= (MSR_FP | current->thread.fpexc_mode);
 +      }
 +      if (msr & MSR_VEC) {
 +              do_load_up_transact_altivec(&current->thread);
 +              regs->msr |= MSR_VEC;
 +      }
 +
 +      return 0;
 +}
 +#endif
 +
  #ifdef CONFIG_PPC64
- long compat_sys_rt_sigaction(int sig, const struct sigaction32 __user *act,
-               struct sigaction32 __user *oact, size_t sigsetsize)
- {
-       struct k_sigaction new_ka, old_ka;
-       int ret;
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(compat_sigset_t))
-               return -EINVAL;
-       if (act) {
-               compat_uptr_t handler;
-               ret = get_user(handler, &act->sa_handler);
-               new_ka.sa.sa_handler = compat_ptr(handler);
-               ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask);
-               ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-               if (ret)
-                       return -EFAULT;
-       }
-       ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-       if (!ret && oact) {
-               ret = put_user(to_user_ptr(old_ka.sa.sa_handler), &oact->sa_handler);
-               ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask);
-               ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-       }
-       return ret;
- }
- /*
-  * Note: it is necessary to treat how as an unsigned int, with the
-  * corresponding cast to a signed int to insure that the proper
-  * conversion (sign extension) between the register representation
-  * of a signed int (msr in 32-bit mode) and the register representation
-  * of a signed int (msr in 64-bit mode) is performed.
-  */
- long compat_sys_rt_sigprocmask(u32 how, compat_sigset_t __user *set,
-               compat_sigset_t __user *oset, size_t sigsetsize)
- {
-       sigset_t s;
-       sigset_t __user *up;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-       if (set) {
-               if (get_sigset_t(&s, set))
-                       return -EFAULT;
-       }
-       set_fs(KERNEL_DS);
-       /* This is valid because of the set_fs() */
-       up = (sigset_t __user *) &s;
-       ret = sys_rt_sigprocmask((int)how, set ? up : NULL, oset ? up : NULL,
-                                sigsetsize);
-       set_fs(old_fs);
-       if (ret)
-               return ret;
-       if (oset) {
-               if (put_sigset_t(oset, &s))
-                       return -EFAULT;
-       }
-       return 0;
- }
- long compat_sys_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
- {
-       sigset_t s;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       /* The __user pointer cast is valid because of the set_fs() */
-       ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
-       set_fs(old_fs);
-       if (!ret) {
-               if (put_sigset_t(set, &s))
-                       return -EFAULT;
-       }
-       return ret;
- }
  int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
  {
        int err;
@@@ -1202,10 -607,8 +971,7 @@@ int handle_rt_signal32(unsigned long si
        /* Put the siginfo & fill in most of the ucontext */
        if (copy_siginfo_to_user(&rt_sf->info, info)
            || __put_user(0, &rt_sf->uc.uc_flags)
-           || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
-           || __put_user(sas_ss_flags(regs->gpr[1]),
-                         &rt_sf->uc.uc_stack.ss_flags)
-           || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
 -          || __put_user(0, &rt_sf->uc.uc_link)
+           || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1])
            || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),
                    &rt_sf->uc.uc_regs)
            || put_sigset_t(&rt_sf->uc.uc_sigmask, oldset))
@@@ -723,29 -413,10 +721,26 @@@ int handle_rt_signal64(int signr, struc
  
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->uc.uc_flags);
-       err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-       err |= __put_user(sas_ss_flags(regs->gpr[1]),
-                         &frame->uc.uc_stack.ss_flags);
-       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 -      err |= __put_user(0, &frame->uc.uc_link);
+       err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
 -      err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL,
 -                              (unsigned long)ka->sa.sa_handler, 1);
 +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 +      if (MSR_TM_ACTIVE(regs->msr)) {
 +              /* The ucontext_t passed to userland points to the second
 +               * ucontext_t (for transactional state) with its uc_link ptr.
 +               */
 +              err |= __put_user(&frame->uc_transact, &frame->uc.uc_link);
 +              err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
 +                                          &frame->uc_transact.uc_mcontext,
 +                                          regs, signr,
 +                                          NULL,
 +                                          (unsigned long)ka->sa.sa_handler);
 +      } else
 +#endif
 +      {
 +              err |= __put_user(0, &frame->uc.uc_link);
 +              err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr,
 +                                      NULL, (unsigned long)ka->sa.sa_handler,
 +                                      1);
 +      }
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
        if (err)
                goto badframe;
@@@ -91,55 -129,19 +91,57 @@@ config S39
        select ARCH_INLINE_WRITE_UNLOCK_BH
        select ARCH_INLINE_WRITE_UNLOCK_IRQ
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 -      select HAVE_UID16 if 32BIT
 +      select ARCH_SAVE_PAGE_KEYS if HIBERNATION
        select ARCH_WANT_IPC_PARSE_VERSION
 -      select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
 +      select BUILDTIME_EXTABLE_SORT
 +      select CLONE_BACKWARDS2
 +      select GENERIC_CLOCKEVENTS
 +      select GENERIC_CPU_DEVICES if !SMP
 +      select GENERIC_KERNEL_THREAD
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL_OLD
 -      select GENERIC_CLOCKEVENTS
 -      select KTIME_SCALAR if 32BIT
 +      select HAVE_ALIGNED_STRUCT_PAGE if SLUB
 +      select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
 +      select HAVE_ARCH_MUTEX_CPU_RELAX
        select HAVE_ARCH_SECCOMP_FILTER
 +      select HAVE_ARCH_TRACEHOOK
 +      select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
 +      select HAVE_BPF_JIT if 64BIT && PACK_STACK
 +      select HAVE_CMPXCHG_DOUBLE
 +      select HAVE_CMPXCHG_LOCAL
 +      select HAVE_C_RECORDMCOUNT
 +      select HAVE_DEBUG_KMEMLEAK
 +      select HAVE_DYNAMIC_FTRACE
 +      select HAVE_FTRACE_MCOUNT_RECORD
 +      select HAVE_FUNCTION_GRAPH_TRACER
 +      select HAVE_FUNCTION_TRACER
 +      select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 +      select HAVE_KERNEL_BZIP2
 +      select HAVE_KERNEL_GZIP
 +      select HAVE_KERNEL_LZMA
 +      select HAVE_KERNEL_LZO
 +      select HAVE_KERNEL_XZ
 +      select HAVE_KPROBES
 +      select HAVE_KRETPROBES
 +      select HAVE_KVM if 64BIT
 +      select HAVE_MEMBLOCK
 +      select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_MOD_ARCH_SPECIFIC
 +      select HAVE_OPROFILE
 +      select HAVE_PERF_EVENTS
 +      select HAVE_REGS_AND_STACK_ACCESS_API
 +      select HAVE_SYSCALL_TRACEPOINTS
 +      select HAVE_SYSCALL_WRAPPERS
 +      select HAVE_UID16 if 32BIT
 +      select HAVE_VIRT_CPU_ACCOUNTING
 +      select INIT_ALL_POSSIBLE
 +      select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
 -      select CLONE_BACKWARDS2
+       select OLD_SIGSUSPEND3
+       select OLD_SIGACTION
 +      select SYSCTL_EXCEPTION_TRACE
 +      select USE_GENERIC_SMP_HELPERS if SMP
 +      select VIRT_CPU_ACCOUNTING
  
  config SCHED_OMIT_FRAME_POINTER
        def_bool y
diff --cc arch/sh/Kconfig
Simple merge
Simple merge
@@@ -115,8 -113,9 +115,10 @@@ config X8
        select MODULES_USE_ELF_REL if X86_32
        select MODULES_USE_ELF_RELA if X86_64
        select CLONE_BACKWARDS if X86_32
-       select GENERIC_SIGALTSTACK
 +      select ARCH_USE_BUILTIN_BSWAP
+       select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
+       select OLD_SIGACTION if X86_32
+       select COMPAT_OLD_SIGACTION if IA32_EMULATION
  
  config INSTRUCTION_DECODER
        def_bool y
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc kernel/compat.c
Simple merge
Simple merge
diff --cc kernel/signal.c
Simple merge