aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-01-15 19:03:33 -0500
committerEric W. Biederman <ebiederm@xmission.com>2018-01-15 20:56:20 -0500
commitea64d5acc8f033cd586182ae31531246cdeaea73 (patch)
tree41aee8a256ce268d0ad463390fccc22d4e2b8f5c /arch/mips/kernel
parenteb5346c379cb272eca77f63473de09103a22ebee (diff)
signal: Unify and correct copy_siginfo_to_user32
Among the existing architecture specific versions of copy_siginfo_to_user32 there are several different implementation problems. Some architectures fail to handle all of the cases in in the siginfo union. Some architectures perform a blind copy of the siginfo union when the si_code is negative. A blind copy suggests the data is expected to be in 32bit siginfo format, which means that receiving such a signal via signalfd won't work, or that the data is in 64bit siginfo and the code is copying nonsense to userspace. Create a single instance of copy_siginfo_to_user32 that all of the architectures can share, and teach it to handle all of the cases in the siginfo union correctly, with the assumption that siginfo is stored internally to the kernel is 64bit siginfo format. A special case is made for x86 x32 format. This is needed as presence of both x32 and ia32 on x86_64 results in two different 32bit signal formats. By allowing this small special case there winds up being exactly one code base that needs to be maintained between all of the architectures. Vastly increasing the testing base and the chances of finding bugs. As the x86 copy of copy_siginfo_to_user32 the call of the x86 signal_compat_build_tests were moved into sigaction_compat_abi, so that they will keep running. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/signal32.c57
1 files changed, 0 insertions, 57 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 500b5e4634ea..c4db910a8794 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -76,60 +76,3 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *,
76 76
77 return ret; 77 return ret;
78} 78}
79
80int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
81{
82 int err;
83
84 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
85 return -EFAULT;
86
87 /* If you change siginfo_t structure, please be sure
88 this code is fixed accordingly.
89 It should never copy any pad contained in the structure
90 to avoid security leaks, but must copy the generic
91 3 ints plus the relevant union member.
92 This routine must convert siginfo from 64bit to 32bit as well
93 at the same time. */
94 err = __put_user(from->si_signo, &to->si_signo);
95 err |= __put_user(from->si_errno, &to->si_errno);
96 err |= __put_user(from->si_code, &to->si_code);
97 if (from->si_code < 0)
98 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
99 else {
100 switch (siginfo_layout(from->si_signo, from->si_code)) {
101 case SIL_TIMER:
102 err |= __put_user(from->si_tid, &to->si_tid);
103 err |= __put_user(from->si_overrun, &to->si_overrun);
104 err |= __put_user(from->si_int, &to->si_int);
105 break;
106 case SIL_CHLD:
107 err |= __put_user(from->si_utime, &to->si_utime);
108 err |= __put_user(from->si_stime, &to->si_stime);
109 err |= __put_user(from->si_status, &to->si_status);
110 case SIL_KILL:
111 err |= __put_user(from->si_pid, &to->si_pid);
112 err |= __put_user(from->si_uid, &to->si_uid);
113 break;
114 case SIL_FAULT:
115 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
116 break;
117 case SIL_POLL:
118 err |= __put_user(from->si_band, &to->si_band);
119 err |= __put_user(from->si_fd, &to->si_fd);
120 break;
121 case SIL_RT:
122 err |= __put_user(from->si_pid, &to->si_pid);
123 err |= __put_user(from->si_uid, &to->si_uid);
124 err |= __put_user(from->si_int, &to->si_int);
125 break;
126 case SIL_SYS:
127 err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
128 sizeof(compat_uptr_t));
129 err |= __put_user(from->si_syscall, &to->si_syscall);
130 err |= __put_user(from->si_arch, &to->si_arch);
131 break;
132 }
133 }
134 return err;
135}