[PATCH] i386: fix task_pt_regs()

)

From: Al Viro <viro@ftp.linux.org.uk>

task_pt_regs() needs the same offset-by-8 to match copy_thread()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by akpm@osdl.org and committed by Linus Torvalds 07b047fc 06b425d8

+14 -21
+2 -18
arch/i386/kernel/process.c
··· 424 struct task_struct *tsk; 425 int err; 426 427 - childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; 428 - /* 429 - * The below -8 is to reserve 8 bytes on top of the ring0 stack. 430 - * This is necessary to guarantee that the entire "struct pt_regs" 431 - * is accessable even if the CPU haven't stored the SS/ESP registers 432 - * on the stack (interrupt gate does not save these registers 433 - * when switching to the same priv ring). 434 - * Therefore beware: accessing the xss/esp fields of the 435 - * "struct pt_regs" is possible, but they may contain the 436 - * completely wrong values. 437 - */ 438 - childregs = (struct pt_regs *) ((unsigned long) childregs - 8); 439 *childregs = *regs; 440 childregs->eax = 0; 441 childregs->esp = esp; ··· 529 */ 530 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) 531 { 532 - struct pt_regs ptregs; 533 - 534 - ptregs = *(struct pt_regs *) 535 - ((unsigned long)tsk->thread_info + 536 - /* see comments in copy_thread() about -8 */ 537 - THREAD_SIZE - sizeof(ptregs) - 8); 538 ptregs.xcs &= 0xffff; 539 ptregs.xds &= 0xffff; 540 ptregs.xes &= 0xffff;
··· 424 struct task_struct *tsk; 425 int err; 426 427 + childregs = task_pt_regs(p); 428 *childregs = *regs; 429 childregs->eax = 0; 430 childregs->esp = esp; ··· 540 */ 541 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) 542 { 543 + struct pt_regs ptregs = *task_pt_regs(tsk); 544 ptregs.xcs &= 0xffff; 545 ptregs.xds &= 0xffff; 546 ptregs.xes &= 0xffff;
+1 -2
arch/i386/kernel/smpboot.c
··· 875 /* initialize thread_struct. we really want to avoid destroy 876 * idle tread 877 */ 878 - idle->thread.esp = (unsigned long)(((struct pt_regs *) 879 - (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1); 880 init_idle(idle, cpu); 881 return idle; 882 }
··· 875 /* initialize thread_struct. we really want to avoid destroy 876 * idle tread 877 */ 878 + idle->thread.esp = (unsigned long)task_pt_regs(idle); 879 init_idle(idle, cpu); 880 return idle; 881 }
+11 -1
include/asm-i386/processor.h
··· 561 (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ 562 }) 563 564 #define task_pt_regs(task) \ 565 ({ \ 566 struct pt_regs *__regs__; \ 567 - __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info); \ 568 __regs__ - 1; \ 569 }) 570
··· 561 (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ 562 }) 563 564 + /* 565 + * The below -8 is to reserve 8 bytes on top of the ring0 stack. 566 + * This is necessary to guarantee that the entire "struct pt_regs" 567 + * is accessable even if the CPU haven't stored the SS/ESP registers 568 + * on the stack (interrupt gate does not save these registers 569 + * when switching to the same priv ring). 570 + * Therefore beware: accessing the xss/esp fields of the 571 + * "struct pt_regs" is possible, but they may contain the 572 + * completely wrong values. 573 + */ 574 #define task_pt_regs(task) \ 575 ({ \ 576 struct pt_regs *__regs__; \ 577 + __regs__ = (struct pt_regs *)(KSTK_TOP((task)->thread_info)-8); \ 578 __regs__ - 1; \ 579 }) 580