aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r--arch/x86/kernel/signal_32.c45
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
182badframe:
183 return 1;
184} 170}
185 171
186asmlinkage unsigned long sys_sigreturn(unsigned long __unused) 172asmlinkage 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 */
264static int 250static int
265setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, 251setup_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 */
308static inline void __user * 294static inline void __user *
309get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 295get_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)