.. | .. |
---|
25 | 25 | #include <linux/user-return-notifier.h> |
---|
26 | 26 | #include <linux/uprobes.h> |
---|
27 | 27 | #include <linux/context_tracking.h> |
---|
| 28 | +#include <linux/entry-common.h> |
---|
28 | 29 | #include <linux/syscalls.h> |
---|
29 | 30 | |
---|
30 | 31 | #include <asm/processor.h> |
---|
.. | .. |
---|
37 | 38 | #include <asm/vm86.h> |
---|
38 | 39 | |
---|
39 | 40 | #ifdef CONFIG_X86_64 |
---|
| 41 | +#include <linux/compat.h> |
---|
40 | 42 | #include <asm/proto.h> |
---|
41 | 43 | #include <asm/ia32_unistd.h> |
---|
42 | 44 | #endif /* CONFIG_X86_64 */ |
---|
43 | 45 | |
---|
44 | 46 | #include <asm/syscall.h> |
---|
45 | | -#include <asm/syscalls.h> |
---|
46 | | - |
---|
47 | 47 | #include <asm/sigframe.h> |
---|
48 | 48 | #include <asm/signal.h> |
---|
49 | | - |
---|
50 | | -#define COPY(x) do { \ |
---|
51 | | - get_user_ex(regs->x, &sc->x); \ |
---|
52 | | -} while (0) |
---|
53 | | - |
---|
54 | | -#define GET_SEG(seg) ({ \ |
---|
55 | | - unsigned short tmp; \ |
---|
56 | | - get_user_ex(tmp, &sc->seg); \ |
---|
57 | | - tmp; \ |
---|
58 | | -}) |
---|
59 | | - |
---|
60 | | -#define COPY_SEG(seg) do { \ |
---|
61 | | - regs->seg = GET_SEG(seg); \ |
---|
62 | | -} while (0) |
---|
63 | | - |
---|
64 | | -#define COPY_SEG_CPL3(seg) do { \ |
---|
65 | | - regs->seg = GET_SEG(seg) | 3; \ |
---|
66 | | -} while (0) |
---|
67 | 49 | |
---|
68 | 50 | #ifdef CONFIG_X86_64 |
---|
69 | 51 | /* |
---|
.. | .. |
---|
92 | 74 | ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN)) |
---|
93 | 75 | regs->ss = __USER_DS; |
---|
94 | 76 | } |
---|
| 77 | +# define CONTEXT_COPY_SIZE offsetof(struct sigcontext, reserved1) |
---|
| 78 | +#else |
---|
| 79 | +# define CONTEXT_COPY_SIZE sizeof(struct sigcontext) |
---|
95 | 80 | #endif |
---|
96 | 81 | |
---|
97 | 82 | static int restore_sigcontext(struct pt_regs *regs, |
---|
98 | | - struct sigcontext __user *sc, |
---|
| 83 | + struct sigcontext __user *usc, |
---|
99 | 84 | unsigned long uc_flags) |
---|
100 | 85 | { |
---|
101 | | - unsigned long buf_val; |
---|
102 | | - void __user *buf; |
---|
103 | | - unsigned int tmpflags; |
---|
104 | | - unsigned int err = 0; |
---|
| 86 | + struct sigcontext sc; |
---|
105 | 87 | |
---|
106 | 88 | /* Always make any pending restarted system calls return -EINTR */ |
---|
107 | 89 | current->restart_block.fn = do_no_restart_syscall; |
---|
108 | 90 | |
---|
109 | | - get_user_try { |
---|
| 91 | + if (copy_from_user(&sc, usc, CONTEXT_COPY_SIZE)) |
---|
| 92 | + return -EFAULT; |
---|
110 | 93 | |
---|
111 | 94 | #ifdef CONFIG_X86_32 |
---|
112 | | - set_user_gs(regs, GET_SEG(gs)); |
---|
113 | | - COPY_SEG(fs); |
---|
114 | | - COPY_SEG(es); |
---|
115 | | - COPY_SEG(ds); |
---|
| 95 | + set_user_gs(regs, sc.gs); |
---|
| 96 | + regs->fs = sc.fs; |
---|
| 97 | + regs->es = sc.es; |
---|
| 98 | + regs->ds = sc.ds; |
---|
116 | 99 | #endif /* CONFIG_X86_32 */ |
---|
117 | 100 | |
---|
118 | | - COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
---|
119 | | - COPY(dx); COPY(cx); COPY(ip); COPY(ax); |
---|
| 101 | + regs->bx = sc.bx; |
---|
| 102 | + regs->cx = sc.cx; |
---|
| 103 | + regs->dx = sc.dx; |
---|
| 104 | + regs->si = sc.si; |
---|
| 105 | + regs->di = sc.di; |
---|
| 106 | + regs->bp = sc.bp; |
---|
| 107 | + regs->ax = sc.ax; |
---|
| 108 | + regs->sp = sc.sp; |
---|
| 109 | + regs->ip = sc.ip; |
---|
120 | 110 | |
---|
121 | 111 | #ifdef CONFIG_X86_64 |
---|
122 | | - COPY(r8); |
---|
123 | | - COPY(r9); |
---|
124 | | - COPY(r10); |
---|
125 | | - COPY(r11); |
---|
126 | | - COPY(r12); |
---|
127 | | - COPY(r13); |
---|
128 | | - COPY(r14); |
---|
129 | | - COPY(r15); |
---|
| 112 | + regs->r8 = sc.r8; |
---|
| 113 | + regs->r9 = sc.r9; |
---|
| 114 | + regs->r10 = sc.r10; |
---|
| 115 | + regs->r11 = sc.r11; |
---|
| 116 | + regs->r12 = sc.r12; |
---|
| 117 | + regs->r13 = sc.r13; |
---|
| 118 | + regs->r14 = sc.r14; |
---|
| 119 | + regs->r15 = sc.r15; |
---|
130 | 120 | #endif /* CONFIG_X86_64 */ |
---|
131 | 121 | |
---|
132 | | - COPY_SEG_CPL3(cs); |
---|
133 | | - COPY_SEG_CPL3(ss); |
---|
| 122 | + /* Get CS/SS and force CPL3 */ |
---|
| 123 | + regs->cs = sc.cs | 0x03; |
---|
| 124 | + regs->ss = sc.ss | 0x03; |
---|
134 | 125 | |
---|
135 | | - get_user_ex(tmpflags, &sc->flags); |
---|
136 | | - regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
---|
137 | | - regs->orig_ax = -1; /* disable syscall checks */ |
---|
138 | | - |
---|
139 | | - get_user_ex(buf_val, &sc->fpstate); |
---|
140 | | - buf = (void __user *)buf_val; |
---|
141 | | - } get_user_catch(err); |
---|
| 126 | + regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS); |
---|
| 127 | + /* disable syscall checks */ |
---|
| 128 | + regs->orig_ax = -1; |
---|
142 | 129 | |
---|
143 | 130 | #ifdef CONFIG_X86_64 |
---|
144 | 131 | /* |
---|
.. | .. |
---|
149 | 136 | force_valid_ss(regs); |
---|
150 | 137 | #endif |
---|
151 | 138 | |
---|
152 | | - err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32)); |
---|
153 | | - |
---|
154 | | - force_iret(); |
---|
155 | | - |
---|
156 | | - return err; |
---|
| 139 | + return fpu__restore_sig((void __user *)sc.fpstate, |
---|
| 140 | + IS_ENABLED(CONFIG_X86_32)); |
---|
157 | 141 | } |
---|
158 | 142 | |
---|
159 | | -int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, |
---|
| 143 | +static __always_inline int |
---|
| 144 | +__unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, |
---|
160 | 145 | struct pt_regs *regs, unsigned long mask) |
---|
161 | 146 | { |
---|
162 | | - int err = 0; |
---|
163 | | - |
---|
164 | | - put_user_try { |
---|
165 | | - |
---|
166 | 147 | #ifdef CONFIG_X86_32 |
---|
167 | | - put_user_ex(get_user_gs(regs), (unsigned int __user *)&sc->gs); |
---|
168 | | - put_user_ex(regs->fs, (unsigned int __user *)&sc->fs); |
---|
169 | | - put_user_ex(regs->es, (unsigned int __user *)&sc->es); |
---|
170 | | - put_user_ex(regs->ds, (unsigned int __user *)&sc->ds); |
---|
| 148 | + unsafe_put_user(get_user_gs(regs), |
---|
| 149 | + (unsigned int __user *)&sc->gs, Efault); |
---|
| 150 | + unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault); |
---|
| 151 | + unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault); |
---|
| 152 | + unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault); |
---|
171 | 153 | #endif /* CONFIG_X86_32 */ |
---|
172 | 154 | |
---|
173 | | - put_user_ex(regs->di, &sc->di); |
---|
174 | | - put_user_ex(regs->si, &sc->si); |
---|
175 | | - put_user_ex(regs->bp, &sc->bp); |
---|
176 | | - put_user_ex(regs->sp, &sc->sp); |
---|
177 | | - put_user_ex(regs->bx, &sc->bx); |
---|
178 | | - put_user_ex(regs->dx, &sc->dx); |
---|
179 | | - put_user_ex(regs->cx, &sc->cx); |
---|
180 | | - put_user_ex(regs->ax, &sc->ax); |
---|
| 155 | + unsafe_put_user(regs->di, &sc->di, Efault); |
---|
| 156 | + unsafe_put_user(regs->si, &sc->si, Efault); |
---|
| 157 | + unsafe_put_user(regs->bp, &sc->bp, Efault); |
---|
| 158 | + unsafe_put_user(regs->sp, &sc->sp, Efault); |
---|
| 159 | + unsafe_put_user(regs->bx, &sc->bx, Efault); |
---|
| 160 | + unsafe_put_user(regs->dx, &sc->dx, Efault); |
---|
| 161 | + unsafe_put_user(regs->cx, &sc->cx, Efault); |
---|
| 162 | + unsafe_put_user(regs->ax, &sc->ax, Efault); |
---|
181 | 163 | #ifdef CONFIG_X86_64 |
---|
182 | | - put_user_ex(regs->r8, &sc->r8); |
---|
183 | | - put_user_ex(regs->r9, &sc->r9); |
---|
184 | | - put_user_ex(regs->r10, &sc->r10); |
---|
185 | | - put_user_ex(regs->r11, &sc->r11); |
---|
186 | | - put_user_ex(regs->r12, &sc->r12); |
---|
187 | | - put_user_ex(regs->r13, &sc->r13); |
---|
188 | | - put_user_ex(regs->r14, &sc->r14); |
---|
189 | | - put_user_ex(regs->r15, &sc->r15); |
---|
| 164 | + unsafe_put_user(regs->r8, &sc->r8, Efault); |
---|
| 165 | + unsafe_put_user(regs->r9, &sc->r9, Efault); |
---|
| 166 | + unsafe_put_user(regs->r10, &sc->r10, Efault); |
---|
| 167 | + unsafe_put_user(regs->r11, &sc->r11, Efault); |
---|
| 168 | + unsafe_put_user(regs->r12, &sc->r12, Efault); |
---|
| 169 | + unsafe_put_user(regs->r13, &sc->r13, Efault); |
---|
| 170 | + unsafe_put_user(regs->r14, &sc->r14, Efault); |
---|
| 171 | + unsafe_put_user(regs->r15, &sc->r15, Efault); |
---|
190 | 172 | #endif /* CONFIG_X86_64 */ |
---|
191 | 173 | |
---|
192 | | - put_user_ex(current->thread.trap_nr, &sc->trapno); |
---|
193 | | - put_user_ex(current->thread.error_code, &sc->err); |
---|
194 | | - put_user_ex(regs->ip, &sc->ip); |
---|
| 174 | + unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault); |
---|
| 175 | + unsafe_put_user(current->thread.error_code, &sc->err, Efault); |
---|
| 176 | + unsafe_put_user(regs->ip, &sc->ip, Efault); |
---|
195 | 177 | #ifdef CONFIG_X86_32 |
---|
196 | | - put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); |
---|
197 | | - put_user_ex(regs->flags, &sc->flags); |
---|
198 | | - put_user_ex(regs->sp, &sc->sp_at_signal); |
---|
199 | | - put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); |
---|
| 178 | + unsafe_put_user(regs->cs, (unsigned int __user *)&sc->cs, Efault); |
---|
| 179 | + unsafe_put_user(regs->flags, &sc->flags, Efault); |
---|
| 180 | + unsafe_put_user(regs->sp, &sc->sp_at_signal, Efault); |
---|
| 181 | + unsafe_put_user(regs->ss, (unsigned int __user *)&sc->ss, Efault); |
---|
200 | 182 | #else /* !CONFIG_X86_32 */ |
---|
201 | | - put_user_ex(regs->flags, &sc->flags); |
---|
202 | | - put_user_ex(regs->cs, &sc->cs); |
---|
203 | | - put_user_ex(0, &sc->gs); |
---|
204 | | - put_user_ex(0, &sc->fs); |
---|
205 | | - put_user_ex(regs->ss, &sc->ss); |
---|
| 183 | + unsafe_put_user(regs->flags, &sc->flags, Efault); |
---|
| 184 | + unsafe_put_user(regs->cs, &sc->cs, Efault); |
---|
| 185 | + unsafe_put_user(0, &sc->gs, Efault); |
---|
| 186 | + unsafe_put_user(0, &sc->fs, Efault); |
---|
| 187 | + unsafe_put_user(regs->ss, &sc->ss, Efault); |
---|
206 | 188 | #endif /* CONFIG_X86_32 */ |
---|
207 | 189 | |
---|
208 | | - put_user_ex(fpstate, &sc->fpstate); |
---|
| 190 | + unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault); |
---|
209 | 191 | |
---|
210 | | - /* non-iBCS2 extensions.. */ |
---|
211 | | - put_user_ex(mask, &sc->oldmask); |
---|
212 | | - put_user_ex(current->thread.cr2, &sc->cr2); |
---|
213 | | - } put_user_catch(err); |
---|
214 | | - |
---|
215 | | - return err; |
---|
| 192 | + /* non-iBCS2 extensions.. */ |
---|
| 193 | + unsafe_put_user(mask, &sc->oldmask, Efault); |
---|
| 194 | + unsafe_put_user(current->thread.cr2, &sc->cr2, Efault); |
---|
| 195 | + return 0; |
---|
| 196 | +Efault: |
---|
| 197 | + return -EFAULT; |
---|
216 | 198 | } |
---|
| 199 | + |
---|
| 200 | +#define unsafe_put_sigcontext(sc, fp, regs, set, label) \ |
---|
| 201 | +do { \ |
---|
| 202 | + if (__unsafe_setup_sigcontext(sc, fp, regs, set->sig[0])) \ |
---|
| 203 | + goto label; \ |
---|
| 204 | +} while(0); |
---|
| 205 | + |
---|
| 206 | +#define unsafe_put_sigmask(set, frame, label) \ |
---|
| 207 | + unsafe_put_user(*(__u64 *)(set), \ |
---|
| 208 | + (__u64 __user *)&(frame)->uc.uc_sigmask, \ |
---|
| 209 | + label) |
---|
217 | 210 | |
---|
218 | 211 | /* |
---|
219 | 212 | * Set up a signal frame. |
---|
.. | .. |
---|
241 | 234 | void __user **fpstate) |
---|
242 | 235 | { |
---|
243 | 236 | /* Default to using normal stack */ |
---|
| 237 | + bool nested_altstack = on_sig_stack(regs->sp); |
---|
| 238 | + bool entering_altstack = false; |
---|
244 | 239 | unsigned long math_size = 0; |
---|
245 | 240 | unsigned long sp = regs->sp; |
---|
246 | 241 | unsigned long buf_fx = 0; |
---|
247 | | - int onsigstack = on_sig_stack(sp); |
---|
248 | | - struct fpu *fpu = ¤t->thread.fpu; |
---|
| 242 | + int ret; |
---|
249 | 243 | |
---|
250 | 244 | /* redzone */ |
---|
251 | 245 | if (IS_ENABLED(CONFIG_X86_64)) |
---|
.. | .. |
---|
253 | 247 | |
---|
254 | 248 | /* This is the X/Open sanctioned signal stack switching. */ |
---|
255 | 249 | if (ka->sa.sa_flags & SA_ONSTACK) { |
---|
256 | | - if (sas_ss_flags(sp) == 0) |
---|
| 250 | + /* |
---|
| 251 | + * This checks nested_altstack via sas_ss_flags(). Sensible |
---|
| 252 | + * programs use SS_AUTODISARM, which disables that check, and |
---|
| 253 | + * programs that don't use SS_AUTODISARM get compatible. |
---|
| 254 | + */ |
---|
| 255 | + if (sas_ss_flags(sp) == 0) { |
---|
257 | 256 | sp = current->sas_ss_sp + current->sas_ss_size; |
---|
| 257 | + entering_altstack = true; |
---|
| 258 | + } |
---|
258 | 259 | } else if (IS_ENABLED(CONFIG_X86_32) && |
---|
259 | | - !onsigstack && |
---|
| 260 | + !nested_altstack && |
---|
260 | 261 | regs->ss != __USER_DS && |
---|
261 | 262 | !(ka->sa.sa_flags & SA_RESTORER) && |
---|
262 | 263 | ka->sa.sa_restorer) { |
---|
263 | 264 | /* This is the legacy signal stack switching. */ |
---|
264 | 265 | sp = (unsigned long) ka->sa.sa_restorer; |
---|
| 266 | + entering_altstack = true; |
---|
265 | 267 | } |
---|
266 | 268 | |
---|
267 | | - if (fpu->initialized) { |
---|
268 | | - sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32), |
---|
269 | | - &buf_fx, &math_size); |
---|
270 | | - *fpstate = (void __user *)sp; |
---|
271 | | - } |
---|
| 269 | + sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32), |
---|
| 270 | + &buf_fx, &math_size); |
---|
| 271 | + *fpstate = (void __user *)sp; |
---|
272 | 272 | |
---|
273 | 273 | sp = align_sigframe(sp - frame_size); |
---|
274 | 274 | |
---|
.. | .. |
---|
276 | 276 | * If we are on the alternate signal stack and would overflow it, don't. |
---|
277 | 277 | * Return an always-bogus address instead so we will die with SIGSEGV. |
---|
278 | 278 | */ |
---|
279 | | - if (onsigstack && !likely(on_sig_stack(sp))) |
---|
| 279 | + if (unlikely((nested_altstack || entering_altstack) && |
---|
| 280 | + !__on_sig_stack(sp))) { |
---|
| 281 | + |
---|
| 282 | + if (show_unhandled_signals && printk_ratelimit()) |
---|
| 283 | + pr_info("%s[%d] overflowed sigaltstack\n", |
---|
| 284 | + current->comm, task_pid_nr(current)); |
---|
| 285 | + |
---|
280 | 286 | return (void __user *)-1L; |
---|
| 287 | + } |
---|
281 | 288 | |
---|
282 | 289 | /* save i387 and extended state */ |
---|
283 | | - if (fpu->initialized && |
---|
284 | | - copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size) < 0) |
---|
| 290 | + ret = copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size); |
---|
| 291 | + if (ret < 0) |
---|
285 | 292 | return (void __user *)-1L; |
---|
286 | 293 | |
---|
287 | 294 | return (void __user *)sp; |
---|
.. | .. |
---|
316 | 323 | { |
---|
317 | 324 | struct sigframe __user *frame; |
---|
318 | 325 | void __user *restorer; |
---|
319 | | - int err = 0; |
---|
320 | | - void __user *fpstate = NULL; |
---|
| 326 | + void __user *fp = NULL; |
---|
321 | 327 | |
---|
322 | | - frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); |
---|
| 328 | + frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp); |
---|
323 | 329 | |
---|
324 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
| 330 | + if (!user_access_begin(frame, sizeof(*frame))) |
---|
325 | 331 | return -EFAULT; |
---|
326 | 332 | |
---|
327 | | - if (__put_user(sig, &frame->sig)) |
---|
328 | | - return -EFAULT; |
---|
329 | | - |
---|
330 | | - if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) |
---|
331 | | - return -EFAULT; |
---|
332 | | - |
---|
333 | | - if (_NSIG_WORDS > 1) { |
---|
334 | | - if (__copy_to_user(&frame->extramask, &set->sig[1], |
---|
335 | | - sizeof(frame->extramask))) |
---|
336 | | - return -EFAULT; |
---|
337 | | - } |
---|
338 | | - |
---|
| 333 | + unsafe_put_user(sig, &frame->sig, Efault); |
---|
| 334 | + unsafe_put_sigcontext(&frame->sc, fp, regs, set, Efault); |
---|
| 335 | + unsafe_put_user(set->sig[1], &frame->extramask[0], Efault); |
---|
339 | 336 | if (current->mm->context.vdso) |
---|
340 | 337 | restorer = current->mm->context.vdso + |
---|
341 | 338 | vdso_image_32.sym___kernel_sigreturn; |
---|
.. | .. |
---|
345 | 342 | restorer = ksig->ka.sa.sa_restorer; |
---|
346 | 343 | |
---|
347 | 344 | /* Set up to return from userspace. */ |
---|
348 | | - err |= __put_user(restorer, &frame->pretcode); |
---|
| 345 | + unsafe_put_user(restorer, &frame->pretcode, Efault); |
---|
349 | 346 | |
---|
350 | 347 | /* |
---|
351 | 348 | * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80 |
---|
.. | .. |
---|
354 | 351 | * reasons and because gdb uses it as a signature to notice |
---|
355 | 352 | * signal handler stack frames. |
---|
356 | 353 | */ |
---|
357 | | - err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode); |
---|
358 | | - |
---|
359 | | - if (err) |
---|
360 | | - return -EFAULT; |
---|
| 354 | + unsafe_put_user(*((u64 *)&retcode), (u64 *)frame->retcode, Efault); |
---|
| 355 | + user_access_end(); |
---|
361 | 356 | |
---|
362 | 357 | /* Set up registers for signal handler */ |
---|
363 | 358 | regs->sp = (unsigned long)frame; |
---|
.. | .. |
---|
372 | 367 | regs->cs = __USER_CS; |
---|
373 | 368 | |
---|
374 | 369 | return 0; |
---|
| 370 | + |
---|
| 371 | +Efault: |
---|
| 372 | + user_access_end(); |
---|
| 373 | + return -EFAULT; |
---|
375 | 374 | } |
---|
376 | 375 | |
---|
377 | 376 | static int __setup_rt_frame(int sig, struct ksignal *ksig, |
---|
.. | .. |
---|
379 | 378 | { |
---|
380 | 379 | struct rt_sigframe __user *frame; |
---|
381 | 380 | void __user *restorer; |
---|
382 | | - int err = 0; |
---|
383 | | - void __user *fpstate = NULL; |
---|
| 381 | + void __user *fp = NULL; |
---|
384 | 382 | |
---|
385 | | - frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); |
---|
| 383 | + frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp); |
---|
386 | 384 | |
---|
387 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
| 385 | + if (!user_access_begin(frame, sizeof(*frame))) |
---|
388 | 386 | return -EFAULT; |
---|
389 | 387 | |
---|
390 | | - put_user_try { |
---|
391 | | - put_user_ex(sig, &frame->sig); |
---|
392 | | - put_user_ex(&frame->info, &frame->pinfo); |
---|
393 | | - put_user_ex(&frame->uc, &frame->puc); |
---|
| 388 | + unsafe_put_user(sig, &frame->sig, Efault); |
---|
| 389 | + unsafe_put_user(&frame->info, &frame->pinfo, Efault); |
---|
| 390 | + unsafe_put_user(&frame->uc, &frame->puc, Efault); |
---|
394 | 391 | |
---|
395 | | - /* Create the ucontext. */ |
---|
396 | | - if (boot_cpu_has(X86_FEATURE_XSAVE)) |
---|
397 | | - put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); |
---|
398 | | - else |
---|
399 | | - put_user_ex(0, &frame->uc.uc_flags); |
---|
400 | | - put_user_ex(0, &frame->uc.uc_link); |
---|
401 | | - save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
---|
| 392 | + /* Create the ucontext. */ |
---|
| 393 | + if (static_cpu_has(X86_FEATURE_XSAVE)) |
---|
| 394 | + unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault); |
---|
| 395 | + else |
---|
| 396 | + unsafe_put_user(0, &frame->uc.uc_flags, Efault); |
---|
| 397 | + unsafe_put_user(0, &frame->uc.uc_link, Efault); |
---|
| 398 | + unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); |
---|
402 | 399 | |
---|
403 | | - /* Set up to return from userspace. */ |
---|
404 | | - restorer = current->mm->context.vdso + |
---|
405 | | - vdso_image_32.sym___kernel_rt_sigreturn; |
---|
406 | | - if (ksig->ka.sa.sa_flags & SA_RESTORER) |
---|
407 | | - restorer = ksig->ka.sa.sa_restorer; |
---|
408 | | - put_user_ex(restorer, &frame->pretcode); |
---|
| 400 | + /* Set up to return from userspace. */ |
---|
| 401 | + restorer = current->mm->context.vdso + |
---|
| 402 | + vdso_image_32.sym___kernel_rt_sigreturn; |
---|
| 403 | + if (ksig->ka.sa.sa_flags & SA_RESTORER) |
---|
| 404 | + restorer = ksig->ka.sa.sa_restorer; |
---|
| 405 | + unsafe_put_user(restorer, &frame->pretcode, Efault); |
---|
409 | 406 | |
---|
410 | | - /* |
---|
411 | | - * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 |
---|
412 | | - * |
---|
413 | | - * WE DO NOT USE IT ANY MORE! It's only left here for historical |
---|
414 | | - * reasons and because gdb uses it as a signature to notice |
---|
415 | | - * signal handler stack frames. |
---|
416 | | - */ |
---|
417 | | - put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); |
---|
418 | | - } put_user_catch(err); |
---|
| 407 | + /* |
---|
| 408 | + * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 |
---|
| 409 | + * |
---|
| 410 | + * WE DO NOT USE IT ANY MORE! It's only left here for historical |
---|
| 411 | + * reasons and because gdb uses it as a signature to notice |
---|
| 412 | + * signal handler stack frames. |
---|
| 413 | + */ |
---|
| 414 | + unsafe_put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode, Efault); |
---|
| 415 | + unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); |
---|
| 416 | + unsafe_put_sigmask(set, frame, Efault); |
---|
| 417 | + user_access_end(); |
---|
419 | 418 | |
---|
420 | | - err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
---|
421 | | - err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
---|
422 | | - regs, set->sig[0]); |
---|
423 | | - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
---|
424 | | - |
---|
425 | | - if (err) |
---|
| 419 | + if (copy_siginfo_to_user(&frame->info, &ksig->info)) |
---|
426 | 420 | return -EFAULT; |
---|
427 | 421 | |
---|
428 | 422 | /* Set up registers for signal handler */ |
---|
.. | .. |
---|
438 | 432 | regs->cs = __USER_CS; |
---|
439 | 433 | |
---|
440 | 434 | return 0; |
---|
| 435 | +Efault: |
---|
| 436 | + user_access_end(); |
---|
| 437 | + return -EFAULT; |
---|
441 | 438 | } |
---|
442 | 439 | #else /* !CONFIG_X86_32 */ |
---|
443 | 440 | static unsigned long frame_uc_flags(struct pt_regs *regs) |
---|
.. | .. |
---|
461 | 458 | struct rt_sigframe __user *frame; |
---|
462 | 459 | void __user *fp = NULL; |
---|
463 | 460 | unsigned long uc_flags; |
---|
464 | | - int err = 0; |
---|
| 461 | + |
---|
| 462 | + /* x86-64 should always use SA_RESTORER. */ |
---|
| 463 | + if (!(ksig->ka.sa.sa_flags & SA_RESTORER)) |
---|
| 464 | + return -EFAULT; |
---|
465 | 465 | |
---|
466 | 466 | frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp); |
---|
| 467 | + uc_flags = frame_uc_flags(regs); |
---|
467 | 468 | |
---|
468 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
| 469 | + if (!user_access_begin(frame, sizeof(*frame))) |
---|
469 | 470 | return -EFAULT; |
---|
| 471 | + |
---|
| 472 | + /* Create the ucontext. */ |
---|
| 473 | + unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault); |
---|
| 474 | + unsafe_put_user(0, &frame->uc.uc_link, Efault); |
---|
| 475 | + unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); |
---|
| 476 | + |
---|
| 477 | + /* Set up to return from userspace. If provided, use a stub |
---|
| 478 | + already in userspace. */ |
---|
| 479 | + unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault); |
---|
| 480 | + unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); |
---|
| 481 | + unsafe_put_sigmask(set, frame, Efault); |
---|
| 482 | + user_access_end(); |
---|
470 | 483 | |
---|
471 | 484 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
---|
472 | 485 | if (copy_siginfo_to_user(&frame->info, &ksig->info)) |
---|
473 | 486 | return -EFAULT; |
---|
474 | 487 | } |
---|
475 | | - |
---|
476 | | - uc_flags = frame_uc_flags(regs); |
---|
477 | | - |
---|
478 | | - put_user_try { |
---|
479 | | - /* Create the ucontext. */ |
---|
480 | | - put_user_ex(uc_flags, &frame->uc.uc_flags); |
---|
481 | | - put_user_ex(0, &frame->uc.uc_link); |
---|
482 | | - save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
---|
483 | | - |
---|
484 | | - /* Set up to return from userspace. If provided, use a stub |
---|
485 | | - already in userspace. */ |
---|
486 | | - /* x86-64 should always use SA_RESTORER. */ |
---|
487 | | - if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
---|
488 | | - put_user_ex(ksig->ka.sa.sa_restorer, &frame->pretcode); |
---|
489 | | - } else { |
---|
490 | | - /* could use a vstub here */ |
---|
491 | | - err |= -EFAULT; |
---|
492 | | - } |
---|
493 | | - } put_user_catch(err); |
---|
494 | | - |
---|
495 | | - err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); |
---|
496 | | - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
---|
497 | | - |
---|
498 | | - if (err) |
---|
499 | | - return -EFAULT; |
---|
500 | 488 | |
---|
501 | 489 | /* Set up registers for signal handler */ |
---|
502 | 490 | regs->di = sig; |
---|
.. | .. |
---|
534 | 522 | force_valid_ss(regs); |
---|
535 | 523 | |
---|
536 | 524 | return 0; |
---|
| 525 | + |
---|
| 526 | +Efault: |
---|
| 527 | + user_access_end(); |
---|
| 528 | + return -EFAULT; |
---|
537 | 529 | } |
---|
538 | 530 | #endif /* CONFIG_X86_32 */ |
---|
| 531 | + |
---|
| 532 | +#ifdef CONFIG_X86_X32_ABI |
---|
| 533 | +static int x32_copy_siginfo_to_user(struct compat_siginfo __user *to, |
---|
| 534 | + const struct kernel_siginfo *from) |
---|
| 535 | +{ |
---|
| 536 | + struct compat_siginfo new; |
---|
| 537 | + |
---|
| 538 | + copy_siginfo_to_external32(&new, from); |
---|
| 539 | + if (from->si_signo == SIGCHLD) { |
---|
| 540 | + new._sifields._sigchld_x32._utime = from->si_utime; |
---|
| 541 | + new._sifields._sigchld_x32._stime = from->si_stime; |
---|
| 542 | + } |
---|
| 543 | + if (copy_to_user(to, &new, sizeof(struct compat_siginfo))) |
---|
| 544 | + return -EFAULT; |
---|
| 545 | + return 0; |
---|
| 546 | +} |
---|
| 547 | + |
---|
| 548 | +int copy_siginfo_to_user32(struct compat_siginfo __user *to, |
---|
| 549 | + const struct kernel_siginfo *from) |
---|
| 550 | +{ |
---|
| 551 | + if (in_x32_syscall()) |
---|
| 552 | + return x32_copy_siginfo_to_user(to, from); |
---|
| 553 | + return __copy_siginfo_to_user32(to, from); |
---|
| 554 | +} |
---|
| 555 | +#endif /* CONFIG_X86_X32_ABI */ |
---|
539 | 556 | |
---|
540 | 557 | static int x32_setup_rt_frame(struct ksignal *ksig, |
---|
541 | 558 | compat_sigset_t *set, |
---|
.. | .. |
---|
545 | 562 | struct rt_sigframe_x32 __user *frame; |
---|
546 | 563 | unsigned long uc_flags; |
---|
547 | 564 | void __user *restorer; |
---|
548 | | - int err = 0; |
---|
549 | | - void __user *fpstate = NULL; |
---|
| 565 | + void __user *fp = NULL; |
---|
550 | 566 | |
---|
551 | | - frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); |
---|
552 | | - |
---|
553 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
| 567 | + if (!(ksig->ka.sa.sa_flags & SA_RESTORER)) |
---|
554 | 568 | return -EFAULT; |
---|
555 | 569 | |
---|
556 | | - if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
---|
557 | | - if (__copy_siginfo_to_user32(&frame->info, &ksig->info, true)) |
---|
558 | | - return -EFAULT; |
---|
559 | | - } |
---|
| 570 | + frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp); |
---|
560 | 571 | |
---|
561 | 572 | uc_flags = frame_uc_flags(regs); |
---|
562 | 573 | |
---|
563 | | - put_user_try { |
---|
564 | | - /* Create the ucontext. */ |
---|
565 | | - put_user_ex(uc_flags, &frame->uc.uc_flags); |
---|
566 | | - put_user_ex(0, &frame->uc.uc_link); |
---|
567 | | - compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
---|
568 | | - put_user_ex(0, &frame->uc.uc__pad0); |
---|
569 | | - |
---|
570 | | - if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
---|
571 | | - restorer = ksig->ka.sa.sa_restorer; |
---|
572 | | - } else { |
---|
573 | | - /* could use a vstub here */ |
---|
574 | | - restorer = NULL; |
---|
575 | | - err |= -EFAULT; |
---|
576 | | - } |
---|
577 | | - put_user_ex(restorer, &frame->pretcode); |
---|
578 | | - } put_user_catch(err); |
---|
579 | | - |
---|
580 | | - err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
---|
581 | | - regs, set->sig[0]); |
---|
582 | | - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
---|
583 | | - |
---|
584 | | - if (err) |
---|
| 574 | + if (!user_access_begin(frame, sizeof(*frame))) |
---|
585 | 575 | return -EFAULT; |
---|
| 576 | + |
---|
| 577 | + /* Create the ucontext. */ |
---|
| 578 | + unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault); |
---|
| 579 | + unsafe_put_user(0, &frame->uc.uc_link, Efault); |
---|
| 580 | + unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault); |
---|
| 581 | + unsafe_put_user(0, &frame->uc.uc__pad0, Efault); |
---|
| 582 | + restorer = ksig->ka.sa.sa_restorer; |
---|
| 583 | + unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault); |
---|
| 584 | + unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); |
---|
| 585 | + unsafe_put_sigmask(set, frame, Efault); |
---|
| 586 | + user_access_end(); |
---|
| 587 | + |
---|
| 588 | + if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
---|
| 589 | + if (x32_copy_siginfo_to_user(&frame->info, &ksig->info)) |
---|
| 590 | + return -EFAULT; |
---|
| 591 | + } |
---|
586 | 592 | |
---|
587 | 593 | /* Set up registers for signal handler */ |
---|
588 | 594 | regs->sp = (unsigned long) frame; |
---|
.. | .. |
---|
601 | 607 | #endif /* CONFIG_X86_X32_ABI */ |
---|
602 | 608 | |
---|
603 | 609 | return 0; |
---|
| 610 | +#ifdef CONFIG_X86_X32_ABI |
---|
| 611 | +Efault: |
---|
| 612 | + user_access_end(); |
---|
| 613 | + return -EFAULT; |
---|
| 614 | +#endif |
---|
604 | 615 | } |
---|
605 | 616 | |
---|
606 | 617 | /* |
---|
.. | .. |
---|
615 | 626 | |
---|
616 | 627 | frame = (struct sigframe __user *)(regs->sp - 8); |
---|
617 | 628 | |
---|
618 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 629 | + if (!access_ok(frame, sizeof(*frame))) |
---|
619 | 630 | goto badframe; |
---|
620 | | - if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 |
---|
621 | | - && __copy_from_user(&set.sig[1], &frame->extramask, |
---|
622 | | - sizeof(frame->extramask)))) |
---|
| 631 | + if (__get_user(set.sig[0], &frame->sc.oldmask) || |
---|
| 632 | + __get_user(set.sig[1], &frame->extramask[0])) |
---|
623 | 633 | goto badframe; |
---|
624 | 634 | |
---|
625 | 635 | set_current_blocked(&set); |
---|
.. | .. |
---|
647 | 657 | unsigned long uc_flags; |
---|
648 | 658 | |
---|
649 | 659 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); |
---|
650 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 660 | + if (!access_ok(frame, sizeof(*frame))) |
---|
651 | 661 | goto badframe; |
---|
652 | | - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
---|
| 662 | + if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask)) |
---|
653 | 663 | goto badframe; |
---|
654 | 664 | if (__get_user(uc_flags, &frame->uc.uc_flags)) |
---|
655 | 665 | goto badframe; |
---|
.. | .. |
---|
693 | 703 | sigset_t *set = sigmask_to_save(); |
---|
694 | 704 | compat_sigset_t *cset = (compat_sigset_t *) set; |
---|
695 | 705 | |
---|
696 | | - /* |
---|
697 | | - * Increment event counter and perform fixup for the pre-signal |
---|
698 | | - * frame. |
---|
699 | | - */ |
---|
| 706 | + /* Perform fixup for the pre-signal frame. */ |
---|
700 | 707 | rseq_signal_deliver(ksig, regs); |
---|
701 | 708 | |
---|
702 | 709 | /* Set up the stack frame */ |
---|
.. | .. |
---|
735 | 742 | regs->ax = -EINTR; |
---|
736 | 743 | break; |
---|
737 | 744 | } |
---|
738 | | - /* fallthrough */ |
---|
| 745 | + fallthrough; |
---|
739 | 746 | case -ERESTARTNOINTR: |
---|
740 | 747 | regs->ax = regs->orig_ax; |
---|
741 | 748 | regs->ip -= 2; |
---|
.. | .. |
---|
768 | 775 | /* |
---|
769 | 776 | * Ensure the signal handler starts with the new fpu state. |
---|
770 | 777 | */ |
---|
771 | | - if (fpu->initialized) |
---|
772 | | - fpu__clear(fpu); |
---|
| 778 | + fpu__clear_user_states(fpu); |
---|
773 | 779 | } |
---|
774 | 780 | signal_setup_done(failed, ksig, stepping); |
---|
775 | 781 | } |
---|
.. | .. |
---|
792 | 798 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
---|
793 | 799 | * mistake. |
---|
794 | 800 | */ |
---|
795 | | -void do_signal(struct pt_regs *regs) |
---|
| 801 | +void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal) |
---|
796 | 802 | { |
---|
797 | 803 | struct ksignal ksig; |
---|
798 | 804 | |
---|
799 | | - if (get_signal(&ksig)) { |
---|
| 805 | + if (has_signal && get_signal(&ksig)) { |
---|
800 | 806 | /* Whee! Actually deliver the signal. */ |
---|
801 | 807 | handle_signal(&ksig, regs); |
---|
802 | 808 | return; |
---|
.. | .. |
---|
841 | 847 | pr_cont("\n"); |
---|
842 | 848 | } |
---|
843 | 849 | |
---|
844 | | - force_sig(SIGSEGV, me); |
---|
| 850 | + force_sig(SIGSEGV); |
---|
845 | 851 | } |
---|
846 | 852 | |
---|
847 | 853 | #ifdef CONFIG_X86_X32_ABI |
---|
848 | | -asmlinkage long sys32_x32_rt_sigreturn(void) |
---|
| 854 | +COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn) |
---|
849 | 855 | { |
---|
850 | 856 | struct pt_regs *regs = current_pt_regs(); |
---|
851 | 857 | struct rt_sigframe_x32 __user *frame; |
---|
.. | .. |
---|
854 | 860 | |
---|
855 | 861 | frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8); |
---|
856 | 862 | |
---|
857 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 863 | + if (!access_ok(frame, sizeof(*frame))) |
---|
858 | 864 | goto badframe; |
---|
859 | | - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
---|
| 865 | + if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask)) |
---|
860 | 866 | goto badframe; |
---|
861 | 867 | if (__get_user(uc_flags, &frame->uc.uc_flags)) |
---|
862 | 868 | goto badframe; |
---|