* [PATCH 01/20] compat: Add generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 02/20] compat: Add generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (19 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
This matches the normal siginfo_t as closely as possible, unlike
some architecture-specific versions which are missing some fields.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/arm64/include/asm/compat.h | 2 ++
arch/mips/include/asm/compat.h | 1 +
arch/parisc/include/asm/compat.h | 2 ++
arch/powerpc/include/asm/compat.h | 1 +
arch/s390/include/asm/compat.h | 2 ++
arch/sparc/include/asm/compat.h | 1 +
arch/tile/include/asm/compat.h | 1 +
arch/x86/include/asm/compat.h | 2 ++
include/linux/compat.h | 66 ++++++++++++++++++++++++++++++++++++++-
9 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 7fbed69..ff4e294 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -155,6 +155,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
+
typedef struct compat_siginfo {
int si_signo;
int si_errno;
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index c4bd54a..5f1f816 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -130,6 +130,7 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index 94710cf..e0be05f 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -134,6 +134,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
+
typedef struct compat_siginfo {
int si_signo;
int si_errno;
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 4f2df58..75b25ff 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -124,6 +124,7 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index d350ed9..ac73ac7 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -192,6 +192,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
+
typedef struct compat_siginfo {
int si_signo;
int si_errno;
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 830502fe..0c80f59 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -153,6 +153,7 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index c14e36f..f9bba8d 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -115,6 +115,7 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
#define COMPAT_SI_PAD_SIZE (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index acdee09..69176b4 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -130,6 +130,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define HAVE_ARCH_COMPAT_SIGINFO_T
+
typedef struct compat_siginfo {
int si_signo;
int si_errno;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index a76c917..9c88b86 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -196,7 +196,71 @@ struct compat_rusage {
extern int put_compat_rusage(const struct rusage *,
struct compat_rusage __user *);
-struct compat_siginfo;
+#ifndef HAVE_ARCH_COMPAT_SIGINFO_T
+typedef struct compat_siginfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+
+ union {
+ int _pad[128 / sizeof(int) - 3];
+
+ /* kill() */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ compat_uid_t _uid; /* sender's uid */
+ } _kill;
+
+ /* POSIX.1b timers */
+ struct {
+ compat_timer_t _tid; /* timer id */
+ int _overrun; /* overrun count */
+ compat_sigval_t _sigval; /* same as below */
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ compat_uid_t _uid; /* sender's uid */
+ compat_sigval_t _sigval;
+ } _rt;
+
+ /* SIGCHLD */
+ struct {
+ compat_pid_t _pid; /* which child */
+ compat_uid_t _uid; /* sender's uid */
+ int _status; /* exit code */
+ compat_clock_t _utime;
+ compat_clock_t _stime;
+ } _sigchld;
+
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ struct {
+ compat_uptr_t _addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+ int _trapno; /* TRAP # which caused the signal */
+#endif
+ short _addr_lsb; /* LSB of the reported address */
+ struct {
+ compat_uptr_t _lower;
+ compat_uptr_t _upper;
+ } _addr_bnd;
+ } _sigfault;
+
+ /* SIGPOLL */
+ struct {
+ compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ int _fd;
+ } _sigpoll;
+
+ struct {
+ compat_uptr_t _call_addr; /* calling insn */
+ int _syscall; /* triggering system call number */
+ compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
+ } _sifields;
+} compat_siginfo_t;
+#endif
extern asmlinkage long compat_sys_waitid(int, compat_pid_t,
struct compat_siginfo __user *, int,
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 02/20] compat: Add generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 01/20] compat: Add generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 03/20] x86: Update compat_siginfo_t to be closer to the generic version Amanieu d'Antras
` (18 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
These routines try to match the behavior of native 32-bit kernels
as closely as possible. They will replace architecture-specific
versions that are missing support for some fields.
The only problematic situation is when sending a si_ptr from a
32-bit process to a 64-bit process or vice-versa, but this has
never worked correctly in the past anyways.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/arm64/include/asm/compat.h | 2 +
arch/mips/include/asm/compat.h | 2 +
arch/parisc/include/asm/compat.h | 2 +
arch/powerpc/include/asm/compat.h | 2 +
arch/s390/include/asm/compat.h | 2 +
arch/sparc/include/asm/compat.h | 2 +
arch/tile/include/asm/compat.h | 2 +
arch/x86/include/asm/compat.h | 2 +
kernel/compat.c | 204 ++++++++++++++++++++++++++++++++++++++
kernel/signal.c | 12 ++-
10 files changed, 227 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index ff4e294..5eae749 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -156,6 +156,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
typedef struct compat_siginfo {
int si_signo;
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index 5f1f816..1e5ba38 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -131,6 +131,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index e0be05f..46a0a8a 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -135,6 +135,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
typedef struct compat_siginfo {
int si_signo;
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 75b25ff..cdc8638 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -125,6 +125,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index ac73ac7..497af62 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -193,6 +193,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
typedef struct compat_siginfo {
int si_signo;
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 0c80f59..9357014 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -154,6 +154,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index f9bba8d..e0c61da 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -116,6 +116,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
#define COMPAT_SI_PAD_SIZE (128/sizeof(int) - 3)
typedef struct compat_siginfo {
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 69176b4..c6b58b1 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -131,6 +131,8 @@ typedef union compat_sigval {
} compat_sigval_t;
#define HAVE_ARCH_COMPAT_SIGINFO_T
+#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
+#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
typedef struct compat_siginfo {
int si_signo;
diff --git a/kernel/compat.c b/kernel/compat.c
index 333d364..7af6d52 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1174,3 +1174,207 @@ void __user *compat_alloc_user_space(unsigned long len)
return ptr;
}
EXPORT_SYMBOL_GPL(compat_alloc_user_space);
+
+#ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER32
+int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
+{
+ int err, si_code;
+
+ if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
+ return -EFAULT;
+
+ /*
+ * Get the user-visible si_code by hiding the top 16 bits if this is a
+ * kernel-generated signal.
+ */
+ si_code = from->si_code < 0 ? from->si_code : (short)from->si_code;
+
+ /*
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
+ */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user(si_code, &to->si_code);
+ if (from->si_code < 0) {
+ err |= __copy_to_user(to->_sifields._pad, from->_sifields._pad, SI_PAD_SIZE * sizeof(int))
+ ? -EFAULT : 0;
+ return err;
+ }
+ switch (from->si_code & __SI_MASK) {
+ case __SI_KILL:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ case __SI_TIMER:
+ err |= __put_user(from->si_tid, &to->si_tid);
+ err |= __put_user(from->si_overrun, &to->si_overrun);
+ /*
+ * Get the sigval from si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ case __SI_POLL:
+ err |= __put_user(from->si_band, &to->si_band);
+ err |= __put_user(from->si_fd, &to->si_fd);
+ break;
+ case __SI_FAULT:
+ err |= __put_user(ptr_to_compat(from->si_addr), &to->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+ err |= __put_user(from->si_trapno, &to->si_trapno);
+#endif
+#ifdef BUS_MCEERR_AO
+ /*
+ * Other callers might not initialize the si_lsb field,
+ * so check explicitly for the right codes here.
+ */
+ if (from->si_signo == SIGBUS &&
+ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
+ err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
+#ifdef SEGV_BNDERR
+ if (from->si_signo == SIGSEGV && from->si_code == SEGV_BNDERR) {
+ err |= __put_user(ptr_to_compat(from->si_lower), &to->si_lower);
+ err |= __put_user(ptr_to_compat(from->si_upper), &to->si_upper);
+ }
+#endif
+ break;
+ case __SI_CHLD:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_status, &to->si_status);
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ: /* But this is */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ /*
+ * Get the sigval from si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS:
+ err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr);
+ err |= __put_user(from->si_syscall, &to->si_syscall);
+ err |= __put_user(from->si_arch, &to->si_arch);
+ break;
+#endif
+ default: /* this is just in case for now ... */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ }
+ return err;
+}
+#endif
+
+#ifndef HAVE_ARCH_COPY_SIGINFO_FROM_USER32
+int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
+{
+ int err;
+ compat_uptr_t ptr32;
+
+ if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t)))
+ return -EFAULT;
+
+ /*
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
+ */
+ err = __get_user(to->si_signo, &from->si_signo);
+ err |= __get_user(to->si_errno, &from->si_errno);
+ err |= __get_user(to->si_code, &from->si_code);
+ if (to->si_code < 0) {
+ /*
+ * Note that the compat union may be larger than the normal one due to
+ * alignment. The copying here causes us to lose the last 4 bytes of
+ * data, but this shouldn't be too much of a problem in practice.
+ */
+ err |= __copy_from_user(to->_sifields._pad, from->_sifields._pad, SI_PAD_SIZE * sizeof(int))
+ ? -EFAULT : 0;
+ return err;
+ }
+ switch (to->si_code & __SI_MASK) {
+ case __SI_KILL:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ case __SI_TIMER:
+ err |= __get_user(to->si_tid, &from->si_tid);
+ err |= __get_user(to->si_overrun, &from->si_overrun);
+ /*
+ * Put the sigval in si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ to->si_ptr = 0; /* Avoid uninitialized bits in the union */
+ err |= __get_user(to->si_int, &from->si_int);
+ break;
+ case __SI_POLL:
+ err |= __get_user(to->si_band, &from->si_band);
+ err |= __get_user(to->si_fd, &from->si_fd);
+ break;
+ case __SI_FAULT:
+ err |= __get_user(ptr32, &from->si_addr);
+ to->si_addr = compat_ptr(ptr32);
+#ifdef __ARCH_SI_TRAPNO
+ err |= __get_user(to->si_trapno, &from->si_trapno);
+#endif
+ err |= __get_user(to->si_addr_lsb, &from->si_addr_lsb);
+ err |= __get_user(ptr32, &from->si_lower);
+ to->si_lower = compat_ptr(ptr32);
+ err |= __get_user(ptr32, &from->si_upper);
+ to->si_upper = compat_ptr(ptr32);
+ break;
+ case __SI_CHLD:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ err |= __get_user(to->si_status, &from->si_status);
+ err |= __get_user(to->si_utime, &from->si_utime);
+ err |= __get_user(to->si_stime, &from->si_stime);
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ: /* But this is */
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ /*
+ * Put the sigval in si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ to->si_ptr = 0; /* Avoid uninitialized bits in the union */
+ err |= __get_user(to->si_int, &from->si_int);
+ break;
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS:
+ err |= __get_user(ptr32, &from->si_call_addr);
+ to->si_call_addr = compat_ptr(ptr32);
+ err |= __get_user(to->si_syscall, &from->si_syscall);
+ err |= __get_user(to->si_arch, &from->si_arch);
+ break;
+#endif
+ default: /* this is just in case for now ... */
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ }
+ return err;
+}
+#endif
diff --git a/kernel/signal.c b/kernel/signal.c
index 0f6bbbe..873e8e2 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2713,11 +2713,13 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
return __copy_to_user(to, from, sizeof(siginfo_t))
? -EFAULT : 0;
/*
- * If you change siginfo_t structure, please be sure
- * this code is fixed accordingly.
- * Please remember to update the signalfd_copyinfo() function
- * inside fs/signalfd.c too, in case siginfo_t changes.
- * It should never copy any pad contained in the structure
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
* to avoid security leaks, but must copy the generic
* 3 ints plus the relevant union member.
*/
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 03/20] x86: Update compat_siginfo_t to be closer to the generic version
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 01/20] compat: Add generic compat_siginfo_t Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 02/20] compat: Add generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (17 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
x86 can't use the generic compat_siginfo_t because it needs to
support x32, so we just change it to be closer to the generic
version.
The only significant change is the addition of several fields in
_sigfault that were previously omitted.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/x86/include/asm/compat.h | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index c6b58b1..00964c0 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -130,6 +130,7 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+/* Need special handling for SIGCHLD on x32 */
#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
@@ -140,12 +141,12 @@ typedef struct compat_siginfo {
int si_code;
union {
- int _pad[128/sizeof(int) - 3];
+ int _pad[128 / sizeof(int) - 3];
/* kill() */
struct {
- unsigned int _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
+ compat_pid_t _pid; /* sender's pid */
+ __compat_uid32_t _uid; /* sender's uid */
} _kill;
/* POSIX.1b timers */
@@ -153,21 +154,19 @@ typedef struct compat_siginfo {
compat_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- int _overrun_incr; /* amount to add to overrun */
} _timer;
/* POSIX.1b signals */
struct {
- unsigned int _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
+ compat_pid_t _pid; /* sender's pid */
+ __compat_uid32_t _uid; /* sender's uid */
compat_sigval_t _sigval;
} _rt;
/* SIGCHLD */
struct {
- unsigned int _pid; /* which child */
- unsigned int _uid; /* sender's uid */
+ compat_pid_t _pid; /* which child */
+ __compat_uid32_t _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
@@ -175,7 +174,7 @@ typedef struct compat_siginfo {
/* SIGCHLD (x32 version) */
struct {
- unsigned int _pid; /* which child */
+ compat_pid_t _pid; /* which child */
unsigned int _uid; /* sender's uid */
int _status; /* exit code */
compat_s64 _utime;
@@ -184,19 +183,27 @@ typedef struct compat_siginfo {
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
- unsigned int _addr; /* faulting insn/memory ref. */
+ compat_uptr_t _addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+ int _trapno; /* TRAP # which caused the signal */
+#endif
+ short _addr_lsb; /* LSB of the reported address */
+ struct {
+ compat_uptr_t _lower;
+ compat_uptr_t _upper;
+ } _addr_bnd;
} _sigfault;
/* SIGPOLL */
struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
struct {
- unsigned int _call_addr; /* calling insn */
+ compat_uptr_t _call_addr; /* calling insn */
int _syscall; /* triggering system call number */
- unsigned int _arch; /* AUDIT_ARCH_* of syscall */
+ compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
} _sigsys;
} _sifields;
} compat_siginfo_t;
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (2 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 03/20] x86: Update compat_siginfo_t to be closer to the generic version Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 22:47 ` kbuild test robot
2015-10-15 18:41 ` Oleg Nesterov
2015-10-14 20:59 ` [PATCH 05/20] mips: Clean up compat_siginfo_t Amanieu d'Antras
` (16 subsequent siblings)
20 siblings, 2 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
x86 can't use the generic versions because it needs to support
x32, so we replace the ad-hoc implementations with something
that is closer to the generic versions.
Unlike the previous implementation, this one guarantees that the
compat behavior is identical to that of a 32-bit kernel.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/x86/kernel/signal_compat.c | 269 +++++++++++++++++++++++++++++-----------
1 file changed, 194 insertions(+), 75 deletions(-)
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index dc3c0b1..e6f7e76 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -1,95 +1,214 @@
#include <linux/compat.h>
#include <linux/uaccess.h>
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
+int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
{
- int err = 0;
+ int err, si_code;
bool ia32 = test_thread_flag(TIF_IA32);
- if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
+ if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
return -EFAULT;
- put_user_try {
- /* If you change siginfo_t structure, please make sure that
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member. */
- put_user_ex(from->si_signo, &to->si_signo);
- put_user_ex(from->si_errno, &to->si_errno);
- put_user_ex((short)from->si_code, &to->si_code);
+ /*
+ * Get the user-visible si_code by hiding the top 16 bits if this is a
+ * kernel-generated signal.
+ */
+ si_code = from->si_code < 0 ? from->si_code : (short)from->si_code;
- if (from->si_code < 0) {
- put_user_ex(from->si_pid, &to->si_pid);
- put_user_ex(from->si_uid, &to->si_uid);
- put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
+ /*
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
+ */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user(si_code, &to->si_code);
+ if (from->si_code < 0) {
+ err |= __copy_to_user(to->_sifields._pad, from->_sifields._pad, SI_PAD_SIZE * sizeof(int))
+ ? -EFAULT : 0;
+ return err;
+ }
+ switch (from->si_code & __SI_MASK) {
+ case __SI_KILL:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ case __SI_TIMER:
+ err |= __put_user(from->si_tid, &to->si_tid);
+ err |= __put_user(from->si_overrun, &to->si_overrun);
+ /*
+ * Get the sigval from si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ case __SI_POLL:
+ err |= __put_user(from->si_band, &to->si_band);
+ err |= __put_user(from->si_fd, &to->si_fd);
+ break;
+ case __SI_FAULT:
+ err |= __put_user(ptr_to_compat(from->si_addr), &to->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+ err |= __put_user(from->si_trapno, &to->si_trapno);
+#endif
+#ifdef BUS_MCEERR_AO
+ /*
+ * Other callers might not initialize the si_lsb field,
+ * so check explicitly for the right codes here.
+ */
+ if (from->si_signo == SIGBUS &&
+ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
+ err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
+#ifdef SEGV_BNDERR
+ if (from->si_signo == SIGSEGV && from->si_code == SEGV_BNDERR) {
+ err |= __put_user(ptr_to_compat(from->si_lower), &to->si_lower);
+ err |= __put_user(ptr_to_compat(from->si_upper), &to->si_upper);
+ }
+#endif
+ break;
+ case __SI_CHLD:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_status, &to->si_status);
+ if (ia32) {
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
} else {
- /*
- * First 32bits of unions are always present:
- * si_pid === si_band === si_tid === si_addr(LS half)
- */
- put_user_ex(from->_sifields._pad[0],
- &to->_sifields._pad[0]);
- switch (from->si_code >> 16) {
- case __SI_FAULT >> 16:
- break;
- case __SI_SYS >> 16:
- put_user_ex(from->si_syscall, &to->si_syscall);
- put_user_ex(from->si_arch, &to->si_arch);
- break;
- case __SI_CHLD >> 16:
- if (ia32) {
- put_user_ex(from->si_utime, &to->si_utime);
- put_user_ex(from->si_stime, &to->si_stime);
- } else {
- put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
- put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
- }
- put_user_ex(from->si_status, &to->si_status);
- /* FALL THROUGH */
- default:
- case __SI_KILL >> 16:
- put_user_ex(from->si_uid, &to->si_uid);
- break;
- case __SI_POLL >> 16:
- put_user_ex(from->si_fd, &to->si_fd);
- break;
- case __SI_TIMER >> 16:
- put_user_ex(from->si_overrun, &to->si_overrun);
- put_user_ex(ptr_to_compat(from->si_ptr),
- &to->si_ptr);
- break;
- /* This is not generated by the kernel as of now. */
- case __SI_RT >> 16:
- case __SI_MESGQ >> 16:
- put_user_ex(from->si_uid, &to->si_uid);
- put_user_ex(from->si_int, &to->si_int);
- break;
- }
+ err |= __put_user(from->si_utime, &to->_sifields._sigchld_x32._utime);
+ err |= __put_user(from->si_stime, &to->_sifields._sigchld_x32._stime);
}
- } put_user_catch(err);
-
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ: /* But this is */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ /*
+ * Get the sigval from si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS:
+ err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr);
+ err |= __put_user(from->si_syscall, &to->si_syscall);
+ err |= __put_user(from->si_arch, &to->si_arch);
+ break;
+#endif
+ default: /* this is just in case for now ... */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ }
return err;
}
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
{
- int err = 0;
- u32 ptr32;
+ int err;
+ compat_uptr_t ptr32;
+ bool ia32 = test_thread_flag(TIF_IA32);
- if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
+ if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t)))
return -EFAULT;
- get_user_try {
- get_user_ex(to->si_signo, &from->si_signo);
- get_user_ex(to->si_errno, &from->si_errno);
- get_user_ex(to->si_code, &from->si_code);
-
- get_user_ex(to->si_pid, &from->si_pid);
- get_user_ex(to->si_uid, &from->si_uid);
- get_user_ex(ptr32, &from->si_ptr);
- to->si_ptr = compat_ptr(ptr32);
- } get_user_catch(err);
-
+ /*
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
+ */
+ err = __get_user(to->si_signo, &from->si_signo);
+ err |= __get_user(to->si_errno, &from->si_errno);
+ err |= __get_user(to->si_code, &from->si_code);
+ if (to->si_code < 0) {
+ /*
+ * Note that the compat union may be larger than the normal one due to
+ * alignment. The copying here causes us to lose the last 4 bytes of
+ * data, but this shouldn't be too much of a problem in practice.
+ */
+ err |= __copy_from_user(to->_sifields._pad, from->_sifields._pad, SI_PAD_SIZE * sizeof(int))
+ ? -EFAULT : 0;
+ return err;
+ }
+ switch (to->si_code & __SI_MASK) {
+ case __SI_KILL:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ case __SI_TIMER:
+ err |= __get_user(to->si_tid, &from->si_tid);
+ err |= __get_user(to->si_overrun, &from->si_overrun);
+ /*
+ * Put the sigval in si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ to->si_ptr = 0; /* Avoid uninitialized bits in the union */
+ err |= __get_user(to->si_int, &from->si_int);
+ break;
+ case __SI_POLL:
+ err |= __get_user(to->si_band, &from->si_band);
+ err |= __get_user(to->si_fd, &from->si_fd);
+ break;
+ case __SI_FAULT:
+ err |= __get_user(ptr32, &from->si_addr);
+ to->si_addr = compat_ptr(ptr32);
+#ifdef __ARCH_SI_TRAPNO
+ err |= __get_user(to->si_trapno, &from->si_trapno);
+#endif
+ err |= __get_user(to->si_addr_lsb, &from->si_addr_lsb);
+ err |= __get_user(ptr32, &from->si_lower);
+ to->si_lower = compat_ptr(ptr32);
+ err |= __get_user(ptr32, &from->si_upper);
+ to->si_upper = compat_ptr(ptr32);
+ break;
+ case __SI_CHLD:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ err |= __get_user(to->si_status, &from->si_status);
+ if (ia32) {
+ err |= __get_user(to->si_utime, &from->si_utime);
+ err |= __get_user(to->si_stime, &from->si_stime);
+ } else {
+ err |= __get_user(to->si_utime, &from->_sifields._sigchld_x32._utime);
+ err |= __get_user(to->si_stime, &from->_sifields._sigchld_x32._stime);
+ }
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ: /* But this is */
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ /*
+ * Put the sigval in si_int, which matches the convention
+ * used in get_compat_sigevent.
+ */
+ to->si_ptr = 0; /* Avoid uninitialized bits in the union */
+ err |= __get_user(to->si_int, &from->si_int);
+ break;
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS:
+ err |= __get_user(ptr32, &from->si_call_addr);
+ to->si_call_addr = compat_ptr(ptr32);
+ err |= __get_user(to->si_syscall, &from->si_syscall);
+ err |= __get_user(to->si_arch, &from->si_arch);
+ break;
+#endif
+ default: /* this is just in case for now ... */
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ }
return err;
}
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32
2015-10-14 20:59 ` [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 22:47 ` kbuild test robot
2015-10-15 18:41 ` Oleg Nesterov
1 sibling, 0 replies; 27+ messages in thread
From: kbuild test robot @ 2015-10-14 22:47 UTC (permalink / raw)
To: Amanieu d'Antras
Cc: kbuild-all, linux-kernel, Oleg Nesterov, Andrew Morton,
Paul E. McKenney, x86, Brian Gerst, Amanieu d'Antras
Hi Amanieu,
[auto build test WARNING on arm64/for-next/core -- if it's inappropriate base, please suggest rules for selecting the more suitable base]
url: https://github.com/0day-ci/linux/commits/Amanieu-d-Antras/Fix-handling-of-compat_siginfo_t/20151015-051137
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> arch/x86/kernel/signal_compat.c:158:30: sparse: Using plain integer as NULL pointer
arch/x86/kernel/signal_compat.c:197:30: sparse: Using plain integer as NULL pointer
vim +158 arch/x86/kernel/signal_compat.c
142 err |= __copy_from_user(to->_sifields._pad, from->_sifields._pad, SI_PAD_SIZE * sizeof(int))
143 ? -EFAULT : 0;
144 return err;
145 }
146 switch (to->si_code & __SI_MASK) {
147 case __SI_KILL:
148 err |= __get_user(to->si_pid, &from->si_pid);
149 err |= __get_user(to->si_uid, &from->si_uid);
150 break;
151 case __SI_TIMER:
152 err |= __get_user(to->si_tid, &from->si_tid);
153 err |= __get_user(to->si_overrun, &from->si_overrun);
154 /*
155 * Put the sigval in si_int, which matches the convention
156 * used in get_compat_sigevent.
157 */
> 158 to->si_ptr = 0; /* Avoid uninitialized bits in the union */
159 err |= __get_user(to->si_int, &from->si_int);
160 break;
161 case __SI_POLL:
162 err |= __get_user(to->si_band, &from->si_band);
163 err |= __get_user(to->si_fd, &from->si_fd);
164 break;
165 case __SI_FAULT:
166 err |= __get_user(ptr32, &from->si_addr);
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32
2015-10-14 20:59 ` [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32 Amanieu d'Antras
2015-10-14 22:47 ` kbuild test robot
@ 2015-10-15 18:41 ` Oleg Nesterov
2015-10-15 18:58 ` Amanieu d'Antras
1 sibling, 1 reply; 27+ messages in thread
From: Oleg Nesterov @ 2015-10-15 18:41 UTC (permalink / raw)
To: Amanieu d'Antras
Cc: linux-kernel, Andrew Morton, Paul E. McKenney, x86, Brian Gerst
OOH ;) I'll try to look at this patch and the changes in the generic
code later. A couple of nits right now.
Please CC x86 maintainers, not only x86@kernel.org.
Please do not remove get/put_user_ex from this code. And this reminds
me that we can improve *user_try/*user_catch ...
On 10/14, Amanieu d'Antras wrote:
>
> -int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
> +int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
> {
> - int err = 0;
> + int err, si_code;
> bool ia32 = test_thread_flag(TIF_IA32);
>
> - if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
> + if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
Why? This looks wrong.
> + if (from->si_code < 0) {
> + err |= __copy_to_user(to->_sifields._pad, from->_sifields._pad, SI_PAD_SIZE * sizeof(int))
> + ? -EFAULT : 0;
> + return err;
I think you should split this patch. And this change (don't interpet,
just copy) should go as a separate change.
> + switch (from->si_code & __SI_MASK) {
> + case __SI_KILL:
I agree, this looks better than ">> 16", but I'd suggest a separate
change too.
[...snip...]
the rest looks unreviewable because you didn't split it and because
you removed try/catch ;) The same for copy-from-user.
Please help us to understand these changes and make the more reviewable
patches if possible. Personally I think you have a point.
Oleg.
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32
2015-10-15 18:41 ` Oleg Nesterov
@ 2015-10-15 18:58 ` Amanieu d'Antras
0 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-15 18:58 UTC (permalink / raw)
To: Oleg Nesterov
Cc: linux-kernel, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Ingo Molnar, H. Peter Anvin
On Thu, Oct 15, 2015 at 7:41 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> OOH ;) I'll try to look at this patch and the changes in the generic
> code later. A couple of nits right now.
>
> Please CC x86 maintainers, not only x86@kernel.org.
>
> Please do not remove get/put_user_ex from this code. And this reminds
> me that we can improve *user_try/*user_catch ...
>
> [...snip...]
>
> the rest looks unreviewable because you didn't split it and because
> you removed try/catch ;) The same for copy-from-user.
>
> Please help us to understand these changes and make the more reviewable
> patches if possible. Personally I think you have a point.
What I did here was replace the old x86-specific version with the
generic version, which I then modified to support x32. If you compare
it with the generic version, the only difference is the addition of
the ia32 flag. The intent was to make it as close as possible to the
generic version, which makes it easier to update both at the same time
when a new siginfo_t fields is added.
This is also why I didn't use put_user_try/get_user_try: it would make
the x86 version unnecessarily diverge from the generic version, since
those macros only exist in the x86 architecture.
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 05/20] mips: Clean up compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (3 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 04/20] x86: Rewrite copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 06/20] mips: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (15 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
While mips can't use the generic compat_siginfo_t directly because
its si_code and si_errno are inverted, we can still make it as
close to the generic version as possible. This makes it easier
to update when new members are added to siginfo_t.
The main changes are adding a missing _sigsys union member and
eliminating the unused _irix_sigchld one.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/mips/include/asm/compat.h | 62 ++++++++++++++++++++++--------------------
1 file changed, 33 insertions(+), 29 deletions(-)
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index 1e5ba38..3ccb126 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -130,10 +130,10 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+/* We can't use generic compat_siginfo_t because our si_code and si_errno are swapped */
#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
int si_signo;
@@ -141,57 +141,61 @@ typedef struct compat_siginfo {
int si_errno;
union {
- int _pad[SI_PAD_SIZE32];
+ int _pad[128 / sizeof(int) - 3];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
- __compat_uid_t _uid; /* sender's uid */
+ __compat_uid32_t _uid; /* sender's uid */
} _kill;
+ /* POSIX.1b timers */
+ struct {
+ compat_timer_t _tid; /* timer id */
+ int _overrun; /* overrun count */
+ compat_sigval_t _sigval; /* same as below */
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ __compat_uid32_t _uid; /* sender's uid */
+ compat_sigval_t _sigval;
+ } _rt;
+
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
- __compat_uid_t _uid; /* sender's uid */
+ __compat_uid32_t _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
} _sigchld;
- /* IRIX SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- compat_clock_t _utime;
- int _status; /* exit code */
- compat_clock_t _stime;
- } _irix_sigchld;
-
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
- s32 _addr; /* faulting insn/memory ref. */
+ compat_uptr_t _addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+ int _trapno; /* TRAP # which caused the signal */
+#endif
+ short _addr_lsb; /* LSB of the reported address */
+ struct {
+ compat_uptr_t _lower;
+ compat_uptr_t _upper;
+ } _addr_bnd;
} _sigfault;
- /* SIGPOLL, SIGXFSZ (To do ...) */
+ /* SIGPOLL */
struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
- /* POSIX.1b timers */
- struct {
- timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval;/* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
struct {
- compat_pid_t _pid; /* sender's pid */
- __compat_uid_t _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
+ compat_uptr_t _call_addr; /* calling insn */
+ int _syscall; /* triggering system call number */
+ compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
} _sifields;
} compat_siginfo_t;
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 06/20] mips: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (4 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 05/20] mips: Clean up compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 07/20] arm64: Use generic compat_siginfo_t Amanieu d'Antras
` (14 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/mips/include/asm/compat.h | 2 --
arch/mips/kernel/signal32.c | 62 ------------------------------------------
2 files changed, 64 deletions(-)
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index 3ccb126..3269077 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -132,8 +132,6 @@ typedef union compat_sigval {
/* We can't use generic compat_siginfo_t because our si_code and si_errno are swapped */
#define HAVE_ARCH_COMPAT_SIGINFO_T
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
typedef struct compat_siginfo {
int si_signo;
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index f7e89524..b719aa3 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -181,68 +181,6 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *,
return ret;
}
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
-{
- int err;
-
- if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please be sure
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member.
- This routine must convert siginfo from 64bit to 32bit as well
- at the same time. */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- if (from->si_code < 0)
- err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
- else {
- switch (from->si_code >> 16) {
- case __SI_TIMER >> 16:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- case __SI_CHLD >> 16:
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- err |= __put_user(from->si_status, &to->si_status);
- default:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_FAULT >> 16:
- err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
- break;
- case __SI_POLL >> 16:
- err |= __put_user(from->si_band, &to->si_band);
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- }
- }
- return err;
-}
-
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
-{
- if (copy_from_user(to, from, 3*sizeof(int)) ||
- copy_from_user(to->_sifields._pad,
- from->_sifields._pad, SI_PAD_SIZE32))
- return -EFAULT;
-
- return 0;
-}
-
asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct sigframe32 __user *frame;
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 07/20] arm64: Use generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (5 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 06/20] mips: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 08/20] arm64: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (13 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/arm64/include/asm/compat.h | 60 -----------------------------------------
1 file changed, 60 deletions(-)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 5eae749..dc7cfc1 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -155,69 +155,9 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-typedef struct compat_siginfo {
- int si_signo;
- int si_errno;
- int si_code;
-
- union {
- int _pad[128/sizeof(int) - 3];
-
- /* kill() */
- struct {
- compat_pid_t _pid; /* sender's pid */
- __compat_uid32_t _uid; /* sender's uid */
- } _kill;
-
- /* POSIX.1b timers */
- struct {
- compat_timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- compat_pid_t _pid; /* sender's pid */
- __compat_uid32_t _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- /* SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- __compat_uid32_t _uid; /* sender's uid */
- int _status; /* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- struct {
- compat_uptr_t _addr; /* faulting insn/memory ref. */
- short _addr_lsb; /* LSB of the reported address */
- } _sigfault;
-
- /* SIGPOLL */
- struct {
- compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
-
- /* SIGSYS */
- struct {
- compat_uptr_t _call_addr; /* calling user insn */
- int _syscall; /* triggering system call number */
- compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
- } _sigsys;
- } _sifields;
-} compat_siginfo_t;
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 08/20] arm64: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (6 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 07/20] arm64: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 09/20] parisc: Use generic compat_siginfo_t Amanieu d'Antras
` (12 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/arm64/include/asm/compat.h | 3 --
arch/arm64/kernel/signal32.c | 85 -----------------------------------------
2 files changed, 88 deletions(-)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index dc7cfc1..824be1dd 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -155,9 +155,6 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 71ef6dc..2a69815 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -125,91 +125,6 @@ static inline int get_sigset_t(sigset_t *set,
return 0;
}
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please be sure
- * this code is fixed accordingly.
- * It should never copy any pad contained in the structure
- * to avoid security leaks, but must copy the generic
- * 3 ints plus the relevant union member.
- * This routine must convert siginfo from 64bit to 32bit as well
- * at the same time.
- */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- if (from->si_code < 0)
- err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
- SI_PAD_SIZE);
- else switch (from->si_code & __SI_MASK) {
- case __SI_KILL:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_TIMER:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- case __SI_POLL:
- err |= __put_user(from->si_band, &to->si_band);
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_FAULT:
- err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
- &to->si_addr);
-#ifdef BUS_MCEERR_AO
- /*
- * Other callers might not initialize the si_lsb field,
- * so check explicitely for the right codes here.
- */
- if (from->si_signo == SIGBUS &&
- (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
- err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
-#endif
- break;
- case __SI_CHLD:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_status, &to->si_status);
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- break;
- case __SI_RT: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ: /* But this is */
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- case __SI_SYS:
- err |= __put_user((compat_uptr_t)(unsigned long)
- from->si_call_addr, &to->si_call_addr);
- err |= __put_user(from->si_syscall, &to->si_syscall);
- err |= __put_user(from->si_arch, &to->si_arch);
- break;
- default: /* this is just in case for now ... */
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- }
- return err;
-}
-
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
-{
- if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
- copy_from_user(to->_sifields._pad,
- from->_sifields._pad, SI_PAD_SIZE))
- return -EFAULT;
-
- return 0;
-}
-
/*
* VFP save/restore code.
*
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 09/20] parisc: Use generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (7 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 08/20] arm64: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 10/20] parsic: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (11 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/parisc/include/asm/compat.h | 53 ----------------------------------------
1 file changed, 53 deletions(-)
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index 46a0a8a..6c80ae2 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -134,62 +134,9 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-typedef struct compat_siginfo {
- int si_signo;
- int si_errno;
- int si_code;
-
- union {
- int _pad[128/sizeof(int) - 3];
-
- /* kill() */
- struct {
- unsigned int _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
- } _kill;
-
- /* POSIX.1b timers */
- struct {
- compat_timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- char _pad[sizeof(unsigned int) - sizeof(int)];
- compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- unsigned int _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- /* SIGCHLD */
- struct {
- unsigned int _pid; /* which child */
- unsigned int _uid; /* sender's uid */
- int _status; /* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- struct {
- unsigned int _addr; /* faulting insn/memory ref. */
- } _sigfault;
-
- /* SIGPOLL */
- struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
- } _sifields;
-} compat_siginfo_t;
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 10/20] parsic: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (8 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 09/20] parisc: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 11/20] s390: Use generic compat_siginfo_t Amanieu d'Antras
` (10 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/parisc/include/asm/compat.h | 3 --
arch/parisc/kernel/signal32.c | 102 ---------------------------------------
2 files changed, 105 deletions(-)
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index 6c80ae2..b56188b 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -134,9 +134,6 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index 984abbe..635012f 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -273,105 +273,3 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __
return err;
}
-
-int
-copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
-{
- compat_uptr_t addr;
- int err;
-
- if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
- return -EFAULT;
-
- err = __get_user(to->si_signo, &from->si_signo);
- err |= __get_user(to->si_errno, &from->si_errno);
- err |= __get_user(to->si_code, &from->si_code);
-
- if (to->si_code < 0)
- err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
- else {
- switch (to->si_code >> 16) {
- case __SI_CHLD >> 16:
- err |= __get_user(to->si_utime, &from->si_utime);
- err |= __get_user(to->si_stime, &from->si_stime);
- err |= __get_user(to->si_status, &from->si_status);
- default:
- err |= __get_user(to->si_pid, &from->si_pid);
- err |= __get_user(to->si_uid, &from->si_uid);
- break;
- case __SI_FAULT >> 16:
- err |= __get_user(addr, &from->si_addr);
- to->si_addr = compat_ptr(addr);
- break;
- case __SI_POLL >> 16:
- err |= __get_user(to->si_band, &from->si_band);
- err |= __get_user(to->si_fd, &from->si_fd);
- break;
- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __get_user(to->si_pid, &from->si_pid);
- err |= __get_user(to->si_uid, &from->si_uid);
- err |= __get_user(to->si_int, &from->si_int);
- break;
- }
- }
- return err;
-}
-
-int
-copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
-{
- compat_uptr_t addr;
- compat_int_t val;
- int err;
-
- if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please be sure
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member.
- This routine must convert siginfo from 64bit to 32bit as well
- at the same time. */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- if (from->si_code < 0)
- err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
- else {
- switch (from->si_code >> 16) {
- case __SI_CHLD >> 16:
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- err |= __put_user(from->si_status, &to->si_status);
- default:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_FAULT >> 16:
- addr = ptr_to_compat(from->si_addr);
- err |= __put_user(addr, &to->si_addr);
- break;
- case __SI_POLL >> 16:
- err |= __put_user(from->si_band, &to->si_band);
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_TIMER >> 16:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- val = (compat_int_t)from->si_int;
- err |= __put_user(val, &to->si_int);
- break;
- case __SI_RT >> 16: /* Not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_pid, &to->si_pid);
- val = (compat_int_t)from->si_int;
- err |= __put_user(val, &to->si_int);
- break;
- }
- }
- return err;
-}
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 11/20] s390: Use generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (9 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 10/20] parsic: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 12/20] s390: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (9 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/s390/include/asm/compat.h | 52 ------------------------------------------
1 file changed, 52 deletions(-)
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 497af62..fbb6365 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -192,61 +192,9 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-typedef struct compat_siginfo {
- int si_signo;
- int si_errno;
- int si_code;
-
- union {
- int _pad[128/sizeof(int) - 3];
-
- /* kill() */
- struct {
- pid_t _pid; /* sender's pid */
- uid_t _uid; /* sender's uid */
- } _kill;
-
- /* POSIX.1b timers */
- struct {
- compat_timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- pid_t _pid; /* sender's pid */
- uid_t _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- /* SIGCHLD */
- struct {
- pid_t _pid; /* which child */
- uid_t _uid; /* sender's uid */
- int _status;/* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- struct {
- __u32 _addr; /* faulting insn/memory ref. - pointer */
- } _sigfault;
-
- /* SIGPOLL */
- struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
- } _sifields;
-} compat_siginfo_t;
-
/*
* How these fields are to be accessed.
*/
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 12/20] s390: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (10 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 11/20] s390: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 13/20] powerpc: Use generic compat_siginfo_t Amanieu d'Antras
` (8 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/s390/include/asm/compat.h | 3 --
arch/s390/kernel/compat_signal.c | 102 ---------------------------------------
2 files changed, 105 deletions(-)
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index fbb6365..5b26a92 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -192,9 +192,6 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-
/*
* How these fields are to be accessed.
*/
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index e0f9d27..3dac655 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -61,108 +61,6 @@ static inline void sigset32_to_sigset(compat_sigset_word *set32,
set64[0] = (unsigned long) set32[0] | ((unsigned long) set32[1] << 32);
}
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
-{
- int err;
-
- /* If you change siginfo_t structure, please be sure
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member.
- This routine must convert siginfo from 64bit to 32bit as well
- at the same time. */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- if (from->si_code < 0)
- err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
- else {
- switch (from->si_code >> 16) {
- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __put_user(from->si_int, &to->si_int);
- /* fallthrough */
- case __SI_KILL >> 16:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_CHLD >> 16:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- err |= __put_user(from->si_status, &to->si_status);
- break;
- case __SI_FAULT >> 16:
- err |= __put_user((unsigned long) from->si_addr,
- &to->si_addr);
- break;
- case __SI_POLL >> 16:
- err |= __put_user(from->si_band, &to->si_band);
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_TIMER >> 16:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- default:
- break;
- }
- }
- return err ? -EFAULT : 0;
-}
-
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
-{
- int err;
- u32 tmp;
-
- err = __get_user(to->si_signo, &from->si_signo);
- err |= __get_user(to->si_errno, &from->si_errno);
- err |= __get_user(to->si_code, &from->si_code);
-
- if (to->si_code < 0)
- err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
- else {
- switch (to->si_code >> 16) {
- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __get_user(to->si_int, &from->si_int);
- /* fallthrough */
- case __SI_KILL >> 16:
- err |= __get_user(to->si_pid, &from->si_pid);
- err |= __get_user(to->si_uid, &from->si_uid);
- break;
- case __SI_CHLD >> 16:
- err |= __get_user(to->si_pid, &from->si_pid);
- err |= __get_user(to->si_uid, &from->si_uid);
- err |= __get_user(to->si_utime, &from->si_utime);
- err |= __get_user(to->si_stime, &from->si_stime);
- err |= __get_user(to->si_status, &from->si_status);
- break;
- case __SI_FAULT >> 16:
- err |= __get_user(tmp, &from->si_addr);
- to->si_addr = (void __force __user *)
- (u64) (tmp & PSW32_ADDR_INSN);
- break;
- case __SI_POLL >> 16:
- err |= __get_user(to->si_band, &from->si_band);
- err |= __get_user(to->si_fd, &from->si_fd);
- break;
- case __SI_TIMER >> 16:
- err |= __get_user(to->si_tid, &from->si_tid);
- err |= __get_user(to->si_overrun, &from->si_overrun);
- err |= __get_user(to->si_int, &from->si_int);
- break;
- default:
- break;
- }
- }
- return err ? -EFAULT : 0;
-}
-
/* Store registers needed to create the signal frame */
static void store_sigregs(void)
{
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 13/20] powerpc: Use generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (11 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 12/20] s390: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-16 23:00 ` kbuild test robot
2015-10-14 20:59 ` [PATCH 14/20] powerpc: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (7 subsequent siblings)
20 siblings, 1 reply; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/powerpc/include/asm/compat.h | 60 ---------------------------------------
1 file changed, 60 deletions(-)
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index cdc8638..b4b644d 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -124,68 +124,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
-
-typedef struct compat_siginfo {
- int si_signo;
- int si_errno;
- int si_code;
-
- union {
- int _pad[SI_PAD_SIZE32];
-
- /* kill() */
- struct {
- compat_pid_t _pid; /* sender's pid */
- __compat_uid_t _uid; /* sender's uid */
- } _kill;
-
- /* POSIX.1b timers */
- struct {
- compat_timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- compat_pid_t _pid; /* sender's pid */
- __compat_uid_t _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- /* SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- __compat_uid_t _uid; /* sender's uid */
- int _status; /* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
- struct {
- unsigned int _addr; /* faulting insn/memory ref. */
- } _sigfault;
-
- /* SIGPOLL */
- struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
-
- /* SIGSYS */
- struct {
- unsigned int _call_addr; /* calling insn */
- int _syscall; /* triggering system call number */
- unsigned int _arch; /* AUDIT_ARCH_* of syscall */
- } _sigsys;
- } _sifields;
-} compat_siginfo_t;
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 13/20] powerpc: Use generic compat_siginfo_t
2015-10-14 20:59 ` [PATCH 13/20] powerpc: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-16 23:00 ` kbuild test robot
0 siblings, 0 replies; 27+ messages in thread
From: kbuild test robot @ 2015-10-16 23:00 UTC (permalink / raw)
To: Amanieu d'Antras
Cc: kbuild-all, linux-kernel, Oleg Nesterov, Andrew Morton,
Paul E. McKenney, x86, Brian Gerst, Amanieu d'Antras
[-- Attachment #1: Type: text/plain, Size: 2922 bytes --]
Hi Amanieu,
[auto build test ERROR on arm64/for-next/core -- if it's inappropriate base, please suggest rules for selecting the more suitable base]
url: https://github.com/0day-ci/linux/commits/Amanieu-d-Antras/Fix-handling-of-compat_siginfo_t/20151015-051137
config: powerpc-defconfig (attached as .config)
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc
Note: the linux-review/Amanieu-d-Antras/Fix-handling-of-compat_siginfo_t/20151015-051137 HEAD 041b7d538bec8eec85a60b4a808bbe3959fcd8c3 builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
arch/powerpc/kernel/signal_32.c: In function 'copy_siginfo_to_user32':
>> arch/powerpc/kernel/signal_32.c:930:11: error: 'SI_PAD_SIZE32' undeclared (first use in this function)
SI_PAD_SIZE32);
^
arch/powerpc/kernel/signal_32.c:930:11: note: each undeclared identifier is reported only once for each function it appears in
arch/powerpc/kernel/signal_32.c: In function 'copy_siginfo_from_user32':
arch/powerpc/kernel/signal_32.c:976:29: error: 'SI_PAD_SIZE32' undeclared (first use in this function)
from->_sifields._pad, SI_PAD_SIZE32))
^
vim +/SI_PAD_SIZE32 +930 arch/powerpc/kernel/signal_32.c
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 924 */
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 925 err = __put_user(s->si_signo, &d->si_signo);
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 926 err |= __put_user(s->si_errno, &d->si_errno);
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 927 err |= __put_user((short)s->si_code, &d->si_code);
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 928 if (s->si_code < 0)
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 929 err |= __copy_to_user(&d->_sifields._pad, &s->_sifields._pad,
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 @930 SI_PAD_SIZE32);
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 931 else switch(s->si_code >> 16) {
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 932 case __SI_CHLD >> 16:
^1da177e arch/ppc64/kernel/signal32.c Linus Torvalds 2005-04-16 933 err |= __put_user(s->si_pid, &d->si_pid);
:::::: The code at line 930 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2
:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 21511 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 14/20] powerpc: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (12 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 13/20] powerpc: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 15/20] tile: Use generic compat_siginfo_t Amanieu d'Antras
` (6 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/powerpc/include/asm/compat.h | 3 --
arch/powerpc/kernel/signal_32.c | 72 +--------------------------------------
2 files changed, 1 insertion(+), 74 deletions(-)
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index b4b644d..6d9c7aa 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -124,9 +124,6 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 0dbee46..66c47d0 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -907,78 +907,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
#endif
#ifdef CONFIG_PPC64
-int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s)
-{
- int err;
-
- if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please be sure
- * this code is fixed accordingly.
- * It should never copy any pad contained in the structure
- * to avoid security leaks, but must copy the generic
- * 3 ints plus the relevant union member.
- * This routine must convert siginfo from 64bit to 32bit as well
- * at the same time.
- */
- err = __put_user(s->si_signo, &d->si_signo);
- err |= __put_user(s->si_errno, &d->si_errno);
- err |= __put_user((short)s->si_code, &d->si_code);
- if (s->si_code < 0)
- err |= __copy_to_user(&d->_sifields._pad, &s->_sifields._pad,
- SI_PAD_SIZE32);
- else switch(s->si_code >> 16) {
- case __SI_CHLD >> 16:
- err |= __put_user(s->si_pid, &d->si_pid);
- err |= __put_user(s->si_uid, &d->si_uid);
- err |= __put_user(s->si_utime, &d->si_utime);
- err |= __put_user(s->si_stime, &d->si_stime);
- err |= __put_user(s->si_status, &d->si_status);
- break;
- case __SI_FAULT >> 16:
- err |= __put_user((unsigned int)(unsigned long)s->si_addr,
- &d->si_addr);
- break;
- case __SI_POLL >> 16:
- err |= __put_user(s->si_band, &d->si_band);
- err |= __put_user(s->si_fd, &d->si_fd);
- break;
- case __SI_TIMER >> 16:
- err |= __put_user(s->si_tid, &d->si_tid);
- err |= __put_user(s->si_overrun, &d->si_overrun);
- err |= __put_user(s->si_int, &d->si_int);
- break;
- case __SI_SYS >> 16:
- err |= __put_user(ptr_to_compat(s->si_call_addr), &d->si_call_addr);
- err |= __put_user(s->si_syscall, &d->si_syscall);
- err |= __put_user(s->si_arch, &d->si_arch);
- break;
- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __put_user(s->si_int, &d->si_int);
- /* fallthrough */
- case __SI_KILL >> 16:
- default:
- err |= __put_user(s->si_pid, &d->si_pid);
- err |= __put_user(s->si_uid, &d->si_uid);
- break;
- }
- return err;
-}
-
#define copy_siginfo_to_user copy_siginfo_to_user32
-
-int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
-{
- if (copy_from_user(to, from, 3*sizeof(int)) ||
- copy_from_user(to->_sifields._pad,
- from->_sifields._pad, SI_PAD_SIZE32))
- return -EFAULT;
-
- return 0;
-}
-#endif /* CONFIG_PPC64 */
+#endif
/*
* Set up a signal frame for a "real-time" signal handler
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 15/20] tile: Use generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (13 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 14/20] powerpc: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 16/20] tile: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (5 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/tile/include/asm/compat.h | 57 ------------------------------------------
1 file changed, 57 deletions(-)
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index e0c61da..302a9f5 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -115,65 +115,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-#define COMPAT_SI_PAD_SIZE (128/sizeof(int) - 3)
-
-typedef struct compat_siginfo {
- int si_signo;
- int si_errno;
- int si_code;
-
- union {
- int _pad[COMPAT_SI_PAD_SIZE];
-
- /* kill() */
- struct {
- unsigned int _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
- } _kill;
-
- /* POSIX.1b timers */
- struct {
- compat_timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- int _overrun_incr; /* amount to add to overrun */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- unsigned int _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- /* SIGCHLD */
- struct {
- unsigned int _pid; /* which child */
- unsigned int _uid; /* sender's uid */
- int _status; /* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- struct {
- unsigned int _addr; /* faulting insn/memory ref. */
-#ifdef __ARCH_SI_TRAPNO
- int _trapno; /* TRAP # which caused the signal */
-#endif
- } _sigfault;
-
- /* SIGPOLL */
- struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
- } _sifields;
-} compat_siginfo_t;
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 16/20] tile: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (14 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 15/20] tile: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 17/20] sparc: Use generic compat_siginfo_t Amanieu d'Antras
` (4 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/tile/include/asm/compat.h | 3 --
arch/tile/kernel/compat_signal.c | 75 ----------------------------------------
2 files changed, 78 deletions(-)
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index 302a9f5..74720ce 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -115,9 +115,6 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index c667e10..758a31d 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -49,81 +49,6 @@ struct compat_rt_sigframe {
struct compat_ucontext uc;
};
-int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please make sure that
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member. */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
-
- if (from->si_code < 0) {
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- } else {
- /*
- * First 32bits of unions are always present:
- * si_pid === si_band === si_tid === si_addr(LS half)
- */
- err |= __put_user(from->_sifields._pad[0],
- &to->_sifields._pad[0]);
- switch (from->si_code >> 16) {
- case __SI_FAULT >> 16:
- break;
- case __SI_CHLD >> 16:
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- err |= __put_user(from->si_status, &to->si_status);
- /* FALL THROUGH */
- default:
- case __SI_KILL >> 16:
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_POLL >> 16:
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_TIMER >> 16:
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- /* This is not generated by the kernel as of now. */
- case __SI_RT >> 16:
- case __SI_MESGQ >> 16:
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- }
- }
- return err;
-}
-
-int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
-{
- int err;
-
- if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
- return -EFAULT;
-
- err = __get_user(to->si_signo, &from->si_signo);
- err |= __get_user(to->si_errno, &from->si_errno);
- err |= __get_user(to->si_code, &from->si_code);
-
- err |= __get_user(to->si_pid, &from->si_pid);
- err |= __get_user(to->si_uid, &from->si_uid);
- err |= __get_user(to->si_int, &from->si_int);
-
- return err;
-}
-
/* The assembly shim for this function arranges to ignore the return value. */
long compat_sys_rt_sigreturn(void)
{
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 17/20] sparc: Use generic compat_siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (15 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 16/20] tile: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 18/20] sparc: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
` (3 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/sparc/include/asm/compat.h | 54 -----------------------------------------
1 file changed, 54 deletions(-)
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 9357014..8f85fcd 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -153,62 +153,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COMPAT_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
-
-typedef struct compat_siginfo {
- int si_signo;
- int si_errno;
- int si_code;
-
- union {
- int _pad[SI_PAD_SIZE32];
-
- /* kill() */
- struct {
- compat_pid_t _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
- } _kill;
-
- /* POSIX.1b timers */
- struct {
- compat_timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval; /* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- compat_pid_t _pid; /* sender's pid */
- unsigned int _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- /* SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- unsigned int _uid; /* sender's uid */
- int _status; /* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
- struct {
- u32 _addr; /* faulting insn/memory ref. */
- int _trapno;
- } _sigfault;
-
- /* SIGPOLL */
- struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
- } _sifields;
-} compat_siginfo_t;
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 18/20] sparc: Use generic copy_siginfo_{to,from}_user32
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (16 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 17/20] sparc: Use generic compat_siginfo_t Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 19/20] signalfd: Fix handling of ssi_ptr and ssi_int in signalfd_copyinfo Amanieu d'Antras
` (2 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
arch/sparc/include/asm/compat.h | 3 --
arch/sparc/kernel/signal32.c | 69 -----------------------------------------
2 files changed, 72 deletions(-)
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 8f85fcd..1b4edd1 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -153,9 +153,6 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
-#define HAVE_ARCH_COPY_SIGINFO_TO_USER32
-#define HAVE_ARCH_COPY_SIGINFO_FROM_USER32
-
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 4eed773..d62f60a 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -69,75 +69,6 @@ struct rt_signal_frame32 {
/* __siginfo_rwin_t * */u32 rwin_save;
} __attribute__((aligned(8)));
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please be sure
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member.
- This routine must convert siginfo from 64bit to 32bit as well
- at the same time. */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- if (from->si_code < 0)
- err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
- else {
- switch (from->si_code >> 16) {
- case __SI_TIMER >> 16:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- case __SI_CHLD >> 16:
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- err |= __put_user(from->si_status, &to->si_status);
- default:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_FAULT >> 16:
- err |= __put_user(from->si_trapno, &to->si_trapno);
- err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
- break;
- case __SI_POLL >> 16:
- err |= __put_user(from->si_band, &to->si_band);
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- }
- }
- return err;
-}
-
-/* CAUTION: This is just a very minimalist implementation for the
- * sake of compat_sys_rt_sigqueueinfo()
- */
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
-{
- if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
- return -EFAULT;
-
- if (copy_from_user(to, from, 3*sizeof(int)) ||
- copy_from_user(to->_sifields._pad, from->_sifields._pad,
- SI_PAD_SIZE))
- return -EFAULT;
-
- return 0;
-}
-
void do_sigreturn32(struct pt_regs *regs)
{
struct signal_frame32 __user *sf;
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 19/20] signalfd: Fix handling of ssi_ptr and ssi_int in signalfd_copyinfo
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (17 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 18/20] sparc: Use generic copy_siginfo_{to,from}_user32 Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 21:23 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 19/20] signalfd: Fix some issues " Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 20/20] signal: Remove unnecessary zero-initialization of siginfo_t Amanieu d'Antras
20 siblings, 1 reply; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
There are several issues here:
1) The value of ssi_ptr was incorrect for 32-bit processes. It was
previously copied directly from si_ptr, which contains garbage
on 32-bit processes, especially on big-endian architectures.
2) A SIGSYS would cause various fields to be filled with incorrect
values. SIGSYS fields are not in signalfd_siginfo, and it should
avoid filling in unrelated fields.
3) ssi_ptr and ssi_int should not be filled in for any unrecognized
si_code, but only for those generated by sigqueue. The si_ptr
and si_int fields in siginfo_t may not be initialized otherwise.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
fs/signalfd.c | 42 +++++++++++++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 270221f..4d59de9 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -80,22 +80,43 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait)
static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
siginfo_t const *kinfo)
{
- long err;
+ long err, ssi_ptr;
BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
/*
+ * ssi_ptr for a compat task should be sourced from si_int instead
+ * of si_ptr since that is what copy_siginfo_from_user32 and
+ * get_compat_sigevent use. 32-bit pointer values are sign-extended
+ * to 64 bits when written to ssi_ptr, which matches the behavior of
+ * 32-bit kernels.
+ */
+ ssi_ptr = is_compat_task() ? kinfo->si_int : (long) kinfo->si_ptr;
+
+ /*
* Unused members should be zero ...
*/
err = __clear_user(uinfo, sizeof(*uinfo));
/*
- * If you change siginfo_t structure, please be sure
- * this code is fixed accordingly.
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
*/
err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo);
err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno);
err |= __put_user((short) kinfo->si_code, &uinfo->ssi_code);
+ if (kinfo->si_code < 0) {
+ /* Write ssi_int and ssi_ptr for sigqueue()-generated signals */
+ err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
+ }
switch (kinfo->si_code & __SI_MASK) {
case __SI_KILL:
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
@@ -104,7 +125,7 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
case __SI_TIMER:
err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
- err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;
case __SI_POLL:
@@ -139,21 +160,20 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
case __SI_MESGQ: /* But this is */
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
- err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS: /* SIGSYS fields are not in signalfd_siginfo */
+ break;
+#endif
default:
- /*
- * This case catches also the signals queued by sigqueue().
- */
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
- err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
- err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;
}
- return err ? -EFAULT: sizeof(*uinfo);
+ return err ? -EFAULT : sizeof(*uinfo);
}
static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 19/20] signalfd: Fix handling of ssi_ptr and ssi_int in signalfd_copyinfo
2015-10-14 20:59 ` [PATCH 19/20] signalfd: Fix handling of ssi_ptr and ssi_int in signalfd_copyinfo Amanieu d'Antras
@ 2015-10-14 21:23 ` Amanieu d'Antras
0 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 21:23 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
Sorry, this was an old version of the patch that was accidentally
sent. Please ignore it.
On Wed, Oct 14, 2015 at 9:59 PM, Amanieu d'Antras <amanieu@gmail.com> wrote:
> There are several issues here:
> 1) The value of ssi_ptr was incorrect for 32-bit processes. It was
> previously copied directly from si_ptr, which contains garbage
> on 32-bit processes, especially on big-endian architectures.
>
> 2) A SIGSYS would cause various fields to be filled with incorrect
> values. SIGSYS fields are not in signalfd_siginfo, and it should
> avoid filling in unrelated fields.
>
> 3) ssi_ptr and ssi_int should not be filled in for any unrecognized
> si_code, but only for those generated by sigqueue. The si_ptr
> and si_int fields in siginfo_t may not be initialized otherwise.
>
> Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
> ---
> fs/signalfd.c | 42 +++++++++++++++++++++++++++++++-----------
> 1 file changed, 31 insertions(+), 11 deletions(-)
>
> diff --git a/fs/signalfd.c b/fs/signalfd.c
> index 270221f..4d59de9 100644
> --- a/fs/signalfd.c
> +++ b/fs/signalfd.c
> @@ -80,22 +80,43 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait)
> static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
> siginfo_t const *kinfo)
> {
> - long err;
> + long err, ssi_ptr;
>
> BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
>
> /*
> + * ssi_ptr for a compat task should be sourced from si_int instead
> + * of si_ptr since that is what copy_siginfo_from_user32 and
> + * get_compat_sigevent use. 32-bit pointer values are sign-extended
> + * to 64 bits when written to ssi_ptr, which matches the behavior of
> + * 32-bit kernels.
> + */
> + ssi_ptr = is_compat_task() ? kinfo->si_int : (long) kinfo->si_ptr;
> +
> + /*
> * Unused members should be zero ...
> */
> err = __clear_user(uinfo, sizeof(*uinfo));
>
> /*
> - * If you change siginfo_t structure, please be sure
> - * this code is fixed accordingly.
> + * If you change siginfo_t structure, please be sure that
> + * all these functions are fixed accordingly:
> + * copy_siginfo_to_user
> + * copy_siginfo_to_user32
> + * copy_siginfo_from_user32
> + * signalfd_copyinfo
> + * They should never copy any pad contained in the structure
> + * to avoid security leaks, but must copy the generic
> + * 3 ints plus the relevant union member.
> */
> err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo);
> err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno);
> err |= __put_user((short) kinfo->si_code, &uinfo->ssi_code);
> + if (kinfo->si_code < 0) {
> + /* Write ssi_int and ssi_ptr for sigqueue()-generated signals */
> + err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
> + err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
> + }
> switch (kinfo->si_code & __SI_MASK) {
> case __SI_KILL:
> err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
> @@ -104,7 +125,7 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
> case __SI_TIMER:
> err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
> err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
> - err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
> + err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
> err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
> break;
> case __SI_POLL:
> @@ -139,21 +160,20 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
> case __SI_MESGQ: /* But this is */
> err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
> err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
> - err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
> + err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
> err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
> break;
> +#ifdef __ARCH_SIGSYS
> + case __SI_SYS: /* SIGSYS fields are not in signalfd_siginfo */
> + break;
> +#endif
> default:
> - /*
> - * This case catches also the signals queued by sigqueue().
> - */
> err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
> err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
> - err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
> - err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
> break;
> }
>
> - return err ? -EFAULT: sizeof(*uinfo);
> + return err ? -EFAULT : sizeof(*uinfo);
> }
>
> static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
> --
> 2.6.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 19/20] signalfd: Fix some issues in signalfd_copyinfo
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (18 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 19/20] signalfd: Fix handling of ssi_ptr and ssi_int in signalfd_copyinfo Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
2015-10-14 20:59 ` [PATCH 20/20] signal: Remove unnecessary zero-initialization of siginfo_t Amanieu d'Antras
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
There are several issues here:
1) The value of ssi_ptr was incorrect for compat tasks. It was
previously copied directly from si_ptr, which contains garbage
for 32-bit processes, especially on big-endian architectures.
2) A SIGSYS would cause various fields to be filled with incorrect
values. SIGSYS fields are not in signalfd_siginfo, and it should
avoid filling in unrelated fields.
3) ssi_ptr and ssi_int should not be filled in for any unrecognized
si_code, but only for those generated by sigqueue. The si_ptr
and si_int fields in siginfo_t may not be initialized otherwise.
4) ssi_ptr and ssi_addr values for compat tasks did not match those
generated by 32-bit kernels. The values need to be sign-extended
to 64 bits rather than zero-extended.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
fs/signalfd.c | 58 ++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 42 insertions(+), 16 deletions(-)
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 270221f..08077fd 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -80,39 +80,66 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait)
static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
siginfo_t const *kinfo)
{
- long err;
+ long err, ssi_ptr, ssi_addr;
BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
/*
+ * ssi_ptr for a compat task should be sourced from si_int instead
+ * of si_ptr since that is what copy_siginfo_from_user32 and
+ * get_compat_sigevent use. 32-bit pointer values are sign-extended
+ * to 64 bits when written to ssi_ptr, which matches the behavior of
+ * 32-bit kernels.
+ */
+ ssi_ptr = is_compat_task() ? kinfo->si_int : (long) kinfo->si_ptr;
+
+ /*
* Unused members should be zero ...
*/
err = __clear_user(uinfo, sizeof(*uinfo));
/*
- * If you change siginfo_t structure, please be sure
- * this code is fixed accordingly.
+ * If you change siginfo_t structure, please be sure that
+ * all these functions are fixed accordingly:
+ * copy_siginfo_to_user
+ * copy_siginfo_to_user32
+ * copy_siginfo_from_user32
+ * signalfd_copyinfo
+ * They should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
*/
err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo);
err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno);
err |= __put_user((short) kinfo->si_code, &uinfo->ssi_code);
+ if (kinfo->si_code < 0) {
+ /* Grab some standard fields for sigqueue()-generated signals */
+ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
+ err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
+ return err ? -EFAULT : sizeof(*uinfo);
+ }
switch (kinfo->si_code & __SI_MASK) {
case __SI_KILL:
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
break;
case __SI_TIMER:
- err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
- err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
- err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
- err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
+ err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
+ err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
+ err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;
case __SI_POLL:
err |= __put_user(kinfo->si_band, &uinfo->ssi_band);
err |= __put_user(kinfo->si_fd, &uinfo->ssi_fd);
break;
case __SI_FAULT:
- err |= __put_user((long) kinfo->si_addr, &uinfo->ssi_addr);
+ /* Ensure that ssi_addr is sign-extended to 64 bits */
+ ssi_addr = is_compat_task() ? (int)(long) kinfo->si_addr :
+ (long) kinfo->si_addr;
+ err |= __put_user(ssi_addr, &uinfo->ssi_addr);
#ifdef __ARCH_SI_TRAPNO
err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno);
#endif
@@ -139,21 +166,20 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
case __SI_MESGQ: /* But this is */
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
- err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(ssi_ptr, &uinfo->ssi_ptr);
err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;
- default:
- /*
- * This case catches also the signals queued by sigqueue().
- */
+#ifdef __ARCH_SIGSYS
+ case __SI_SYS: /* SIGSYS fields are not in signalfd_siginfo */
+ break;
+#endif
+ default: /* this is just in case for now ... */
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
- err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
- err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;
}
- return err ? -EFAULT: sizeof(*uinfo);
+ return err ? -EFAULT : sizeof(*uinfo);
}
static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 20/20] signal: Remove unnecessary zero-initialization of siginfo_t
2015-10-14 20:59 [PATCH 00/20] Fix handling of compat_siginfo_t Amanieu d'Antras
` (19 preceding siblings ...)
2015-10-14 20:59 ` [PATCH 19/20] signalfd: Fix some issues " Amanieu d'Antras
@ 2015-10-14 20:59 ` Amanieu d'Antras
20 siblings, 0 replies; 27+ messages in thread
From: Amanieu d'Antras @ 2015-10-14 20:59 UTC (permalink / raw)
To: linux-kernel
Cc: Oleg Nesterov, Andrew Morton, Paul E. McKenney, x86, Brian Gerst,
Amanieu d'Antras
This is no longer required since copy_siginfo_from_user32 now
initializes all siginfo_t fields properly.
Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
---
kernel/ptrace.c | 1 -
kernel/signal.c | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 787320d..3aa383b 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -1147,7 +1147,6 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
break;
case PTRACE_SETSIGINFO:
- memset(&siginfo, 0, sizeof siginfo);
if (copy_siginfo_from_user32(
&siginfo, (struct compat_siginfo __user *) datap))
ret = -EFAULT;
diff --git a/kernel/signal.c b/kernel/signal.c
index 873e8e2..ce992f2 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3022,7 +3022,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo,
int, sig,
struct compat_siginfo __user *, uinfo)
{
- siginfo_t info = {};
+ siginfo_t info;
int ret = copy_siginfo_from_user32(&info, uinfo);
if (unlikely(ret))
return ret;
@@ -3066,7 +3066,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
int, sig,
struct compat_siginfo __user *, uinfo)
{
- siginfo_t info = {};
+ siginfo_t info;
if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT;
--
2.6.1
^ permalink raw reply related [flat|nested] 27+ messages in thread