Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Apr 2018 03:33:38 +0000 (20:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Apr 2018 03:33:38 +0000 (20:33 -0700)
Pull siginfo updates from Eric Biederman:
 "The work on cleaning up and getting the bugs out of siginfo generation
  was largely stalled this round. The progress that was made was the
  definition of FPE_FLTUNK. Which is usable to fix many of the cases
  where siginfo generation is erroneously generating SI_USER by setting
  si_code to 0, that has recently been tagged as FPE_FIXME.

  You already have the change by way of the arm64 tree as that
  definition was pulled into the arm64 tree to allow fixing the problem
  there.

  What remains is the second round of fixing for what I thought was a
  trivial change to the struct siginfo when put the union in _sigfault
  where it belongs. Do to historical reasons 32bit m68k only ensures
  that pointers are 2 byte aligned. So I have added a m68k test case
  made of BUILD_BUG_ONs to verify I have this fix correct and possibly
  catch problems, and I have computed the number of bytes of padding
  needed for the _addr_bnd and _addr_pkey cases and just use an array of
  characters that size.

  For pure paranoia I have written the code so if there is an
  architecture out there that does not perform any alignment of
  structures it should still work.

  With the removal of all of the stale arechitectures this cycle future
  work on cleaning up struct siginfo should be much easier. Almost all
  of the conflicting si_code definitions have been removed with the
  removal of (blackfin, tile, and frv). Plus some of the most difficult
  to test cases have simply been removed from the tree.

  Which means that with a little luck copy_siginfo_to_user can become a
  light weight wrapper around copy_to_user in the next cycle"

* 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  m68k: Verify the offsets in struct siginfo never change.
  signal: Correct the offset of si_pkey and si_lower in struct siginfo on m68k

arch/m68k/kernel/signal.c
include/linux/compat.h
include/uapi/asm-generic/siginfo.h

index e79421f5b9cd936020d41799ca79501f79e8b3c3..f7cd5ecfacd3b9465fcaec40eeee7e7ff1b23689 100644 (file)
@@ -574,6 +574,66 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *
 
 #endif /* CONFIG_FPU */
 
+static inline void siginfo_build_tests(void)
+{
+       /* This needs to be tested on m68k as it has a lesser
+        * alignment requirment than x86 and that can cause surprises.
+        */
+
+       /* This is part of the ABI and can never change in size: */
+       BUILD_BUG_ON(sizeof(siginfo_t) != 128);
+
+       /* Ensure the know fields never change in location */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_signo) != 0);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_errno) != 4);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_code)  != 8);
+
+       /* _kill */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_pid) != 0x0C);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_uid) != 0x10);
+
+       /* _timer */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_tid)     != 0x0C);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_overrun) != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_value)   != 0x14);
+
+       /* _rt */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_pid)   != 0x0C);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_uid)   != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_value) != 0x14);
+
+       /* _sigchld */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_pid)    != 0x0C);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_uid)    != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_status) != 0x14);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_utime)  != 0x18);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_stime)  != 0x1C);
+
+       /* _sigfault */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x0C);
+
+       /* _sigfault._mcerr */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_addr_lsb) != 0x10);
+
+       /* _sigfault._addr_bnd */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_lower) != 0x12);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_upper) != 0x16);
+
+       /* _sigfault._addr_pkey */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x12);
+
+       /* _sigpoll */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_band)   != 0x0C);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_fd)     != 0x10);
+
+       /* _sigsys */
+       BUILD_BUG_ON(offsetof(siginfo_t, si_call_addr) != 0x0C);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_syscall)   != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_arch)      != 0x14);
+
+       /* any new si_fields should be added here */
+}
+
 static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
                               void __user *fp)
 {
@@ -635,6 +695,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
        struct sigcontext context;
        int err = 0;
 
+       siginfo_build_tests();
+
        /* Always make any pending restarted system calls return -EINTR */
        current->restart_block.fn = do_no_restart_syscall;
 
index 9847c5a013c3c230e025008463c164922230ac7d..f188eab10570584f0dd7267e7f071292bb5f629c 100644 (file)
@@ -226,6 +226,8 @@ typedef struct compat_siginfo {
 #ifdef __ARCH_SI_TRAPNO
                        int _trapno;    /* TRAP # which caused the signal */
 #endif
+#define __COMPAT_ADDR_BND_PKEY_PAD  (__alignof__(compat_uptr_t) < sizeof(short) ? \
+                                    sizeof(short) : __alignof__(compat_uptr_t))
                        union {
                                /*
                                 * used when si_code=BUS_MCEERR_AR or
@@ -234,13 +236,13 @@ typedef struct compat_siginfo {
                                short int _addr_lsb;    /* Valid LSB of the reported address. */
                                /* used when si_code=SEGV_BNDERR */
                                struct {
-                                       compat_uptr_t _dummy_bnd;
+                                       char _dummy_bnd[__COMPAT_ADDR_BND_PKEY_PAD];
                                        compat_uptr_t _lower;
                                        compat_uptr_t _upper;
                                } _addr_bnd;
                                /* used when si_code=SEGV_PKUERR */
                                struct {
-                                       compat_uptr_t _dummy_pkey;
+                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
                                        u32 _pkey;
                                } _addr_pkey;
                        };
index 6088bca899179cc3ebf2f88a5200eee879823f7c..544208fd3db17a84938b2cea1ca94cc2ac579fbf 100644 (file)
@@ -94,6 +94,9 @@ typedef struct siginfo {
                        unsigned int _flags;    /* see ia64 si_flags */
                        unsigned long _isr;     /* isr */
 #endif
+
+#define __ADDR_BND_PKEY_PAD  (__alignof__(void *) < sizeof(short) ? \
+                             sizeof(short) : __alignof__(void *))
                        union {
                                /*
                                 * used when si_code=BUS_MCEERR_AR or
@@ -102,13 +105,13 @@ typedef struct siginfo {
                                short _addr_lsb; /* LSB of the reported address */
                                /* used when si_code=SEGV_BNDERR */
                                struct {
-                                       void *_dummy_bnd;
+                                       char _dummy_bnd[__ADDR_BND_PKEY_PAD];
                                        void __user *_lower;
                                        void __user *_upper;
                                } _addr_bnd;
                                /* used when si_code=SEGV_PKUERR */
                                struct {
-                                       void *_dummy_pkey;
+                                       char _dummy_pkey[__ADDR_BND_PKEY_PAD];
                                        __u32 _pkey;
                                } _addr_pkey;
                        };