]> git.itanic.dy.fi Git - linux-stable/commitdiff
signal: Correct the offset of si_pkey and si_lower in struct siginfo on m68k
authorEric W. Biederman <ebiederm@xmission.com>
Mon, 2 Apr 2018 19:45:42 +0000 (14:45 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Apr 2018 12:29:52 +0000 (14:29 +0200)
commit 8420f71943ae96dcd78da5bd4a5c2827419d340c upstream.

The change moving addr_lsb into the _sigfault union failed to take
into account that _sigfault._addr_bnd._lower being a pointer forced
the entire union to have pointer alignment.  The fix for
_sigfault._addr_bnd._lower having pointer alignment failed to take
into account that m68k has a pointer alignment less than the size
of a pointer.  So simply making the padding members pointers changed
the location of later members in the structure.

Fix this by directly computing the needed size of the padding members,
and making the padding members char arrays of the needed size.  AKA
if __alignof__(void *) is 1 sizeof(short) otherwise __alignof__(void *).
Which should be exactly the same rules the compiler whould have
used when computing the padding.

I have tested this change by adding BUILD_BUG_ONs to m68k to verify
the offset of every member of struct siginfo, and with those testing
that the offsets of the fields in struct siginfo is the same before
I changed the generic _sigfault member and after the correction
to the _sigfault member.

I have also verified that the x86 with it's own BUILD_BUG_ONs to verify
the offsets of the siginfo members also compiles cleanly.

Cc: stable@vger.kernel.org
Reported-by: Eugene Syromiatnikov <esyr@redhat.com>
Fixes: 859d880cf544 ("signal: Correct the offset of si_pkey in struct siginfo")
Fixes: b68a68d3dcc1 ("signal: Move addr_lsb into the _sigfault union for clarity")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/compat.h
include/uapi/asm-generic/siginfo.h

index 16c3027074a22f6aea08e0157a5848f824e08afd..6970e7922c69d00e74b7a8866232a6a52f57585f 100644 (file)
@@ -222,6 +222,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
@@ -230,13 +232,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 99c902e460c2534609c6c385543e527adc36fa57..65d405770b95f2f9b3bd1fcced4d7e9f22f5d941 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;
                        };