diff options
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r-- | arch/x86/kernel/signal_32.c | 45 |
1 files changed, 21 insertions, 24 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd893..0f98d69fbdb 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -159,28 +159,14 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
159 | } | 159 | } |
160 | 160 | ||
161 | { | 161 | { |
162 | struct _fpstate __user *buf; | 162 | void __user *buf; |
163 | 163 | ||
164 | err |= __get_user(buf, &sc->fpstate); | 164 | err |= __get_user(buf, &sc->fpstate); |
165 | if (buf) { | 165 | err |= restore_i387_xstate(buf); |
166 | if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) | ||
167 | goto badframe; | ||
168 | err |= restore_i387(buf); | ||
169 | } else { | ||
170 | struct task_struct *me = current; | ||
171 | |||
172 | if (used_math()) { | ||
173 | clear_fpu(me); | ||
174 | clear_used_math(); | ||
175 | } | ||
176 | } | ||
177 | } | 166 | } |
178 | 167 | ||
179 | err |= __get_user(*pax, &sc->ax); | 168 | err |= __get_user(*pax, &sc->ax); |
180 | return err; | 169 | return err; |
181 | |||
182 | badframe: | ||
183 | return 1; | ||
184 | } | 170 | } |
185 | 171 | ||
186 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) | 172 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) |
@@ -262,7 +248,7 @@ badframe: | |||
262 | * Set up a signal frame. | 248 | * Set up a signal frame. |
263 | */ | 249 | */ |
264 | static int | 250 | static int |
265 | setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | 251 | setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, |
266 | struct pt_regs *regs, unsigned long mask) | 252 | struct pt_regs *regs, unsigned long mask) |
267 | { | 253 | { |
268 | int tmp, err = 0; | 254 | int tmp, err = 0; |
@@ -289,7 +275,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
289 | err |= __put_user(regs->sp, &sc->sp_at_signal); | 275 | err |= __put_user(regs->sp, &sc->sp_at_signal); |
290 | err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); | 276 | err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); |
291 | 277 | ||
292 | tmp = save_i387(fpstate); | 278 | tmp = save_i387_xstate(fpstate); |
293 | if (tmp < 0) | 279 | if (tmp < 0) |
294 | err = 1; | 280 | err = 1; |
295 | else | 281 | else |
@@ -306,7 +292,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
306 | * Determine which stack to use.. | 292 | * Determine which stack to use.. |
307 | */ | 293 | */ |
308 | static inline void __user * | 294 | static inline void __user * |
309 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | 295 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, |
296 | void **fpstate) | ||
310 | { | 297 | { |
311 | unsigned long sp; | 298 | unsigned long sp; |
312 | 299 | ||
@@ -332,6 +319,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
332 | sp = (unsigned long) ka->sa.sa_restorer; | 319 | sp = (unsigned long) ka->sa.sa_restorer; |
333 | } | 320 | } |
334 | 321 | ||
322 | if (used_math()) { | ||
323 | sp = sp - sig_xstate_size; | ||
324 | *fpstate = (struct _fpstate *) sp; | ||
325 | } | ||
326 | |||
335 | sp -= frame_size; | 327 | sp -= frame_size; |
336 | /* | 328 | /* |
337 | * Align the stack pointer according to the i386 ABI, | 329 | * Align the stack pointer according to the i386 ABI, |
@@ -350,8 +342,9 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
350 | void __user *restorer; | 342 | void __user *restorer; |
351 | int err = 0; | 343 | int err = 0; |
352 | int usig; | 344 | int usig; |
345 | void __user *fpstate = NULL; | ||
353 | 346 | ||
354 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 347 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
355 | 348 | ||
356 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 349 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
357 | goto give_sigsegv; | 350 | goto give_sigsegv; |
@@ -366,7 +359,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
366 | if (err) | 359 | if (err) |
367 | goto give_sigsegv; | 360 | goto give_sigsegv; |
368 | 361 | ||
369 | err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); | 362 | err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); |
370 | if (err) | 363 | if (err) |
371 | goto give_sigsegv; | 364 | goto give_sigsegv; |
372 | 365 | ||
@@ -427,8 +420,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
427 | void __user *restorer; | 420 | void __user *restorer; |
428 | int err = 0; | 421 | int err = 0; |
429 | int usig; | 422 | int usig; |
423 | void __user *fpstate = NULL; | ||
430 | 424 | ||
431 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 425 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
432 | 426 | ||
433 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 427 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
434 | goto give_sigsegv; | 428 | goto give_sigsegv; |
@@ -447,13 +441,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
447 | goto give_sigsegv; | 441 | goto give_sigsegv; |
448 | 442 | ||
449 | /* Create the ucontext. */ | 443 | /* Create the ucontext. */ |
450 | err |= __put_user(0, &frame->uc.uc_flags); | 444 | if (cpu_has_xsave) |
445 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
446 | else | ||
447 | err |= __put_user(0, &frame->uc.uc_flags); | ||
451 | err |= __put_user(0, &frame->uc.uc_link); | 448 | err |= __put_user(0, &frame->uc.uc_link); |
452 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 449 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
453 | err |= __put_user(sas_ss_flags(regs->sp), | 450 | err |= __put_user(sas_ss_flags(regs->sp), |
454 | &frame->uc.uc_stack.ss_flags); | 451 | &frame->uc.uc_stack.ss_flags); |
455 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 452 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
456 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 453 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
457 | regs, set->sig[0]); | 454 | regs, set->sig[0]); |
458 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 455 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
459 | if (err) | 456 | if (err) |