From: Al Viro task_pt_regs() needs the same offset-by-8 to match copy_thread() Signed-off-by: Al Viro Signed-off-by: Andrew Morton --- arch/i386/kernel/process.c | 20 ++------------------ arch/i386/kernel/smpboot.c | 3 +-- include/asm-i386/processor.h | 12 +++++++++++- 3 files changed, 14 insertions(+), 21 deletions(-) diff -puN arch/i386/kernel/process.c~i386-fix-task_pt_regs arch/i386/kernel/process.c --- devel/arch/i386/kernel/process.c~i386-fix-task_pt_regs 2006-01-04 22:01:52.000000000 -0800 +++ devel-akpm/arch/i386/kernel/process.c 2006-01-04 22:01:52.000000000 -0800 @@ -424,18 +424,7 @@ int copy_thread(int nr, unsigned long cl struct task_struct *tsk; int err; - childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; - /* - * The below -8 is to reserve 8 bytes on top of the ring0 stack. - * This is necessary to guarantee that the entire "struct pt_regs" - * is accessable even if the CPU haven't stored the SS/ESP registers - * on the stack (interrupt gate does not save these registers - * when switching to the same priv ring). - * Therefore beware: accessing the xss/esp fields of the - * "struct pt_regs" is possible, but they may contain the - * completely wrong values. - */ - childregs = (struct pt_regs *) ((unsigned long) childregs - 8); + childregs = task_pt_regs(p); *childregs = *regs; childregs->eax = 0; childregs->esp = esp; @@ -540,12 +529,7 @@ EXPORT_SYMBOL(dump_thread); */ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) { - struct pt_regs ptregs; - - ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info + - /* see comments in copy_thread() about -8 */ - THREAD_SIZE - sizeof(ptregs) - 8); + struct pt_regs ptregs = *task_pt_regs(tsk); ptregs.xcs &= 0xffff; ptregs.xds &= 0xffff; ptregs.xes &= 0xffff; diff -puN arch/i386/kernel/smpboot.c~i386-fix-task_pt_regs arch/i386/kernel/smpboot.c --- devel/arch/i386/kernel/smpboot.c~i386-fix-task_pt_regs 2006-01-04 22:01:52.000000000 -0800 +++ devel-akpm/arch/i386/kernel/smpboot.c 2006-01-04 22:01:52.000000000 -0800 @@ -875,8 +875,7 @@ static inline struct task_struct * alloc /* initialize thread_struct. we really want to avoid destroy * idle tread */ - idle->thread.esp = (unsigned long)(((struct pt_regs *) - (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1); + idle->thread.esp = (unsigned long)task_pt_regs(idle); init_idle(idle, cpu); return idle; } diff -puN include/asm-i386/processor.h~i386-fix-task_pt_regs include/asm-i386/processor.h --- devel/include/asm-i386/processor.h~i386-fix-task_pt_regs 2006-01-04 22:01:52.000000000 -0800 +++ devel-akpm/include/asm-i386/processor.h 2006-01-04 22:01:52.000000000 -0800 @@ -561,10 +561,20 @@ unsigned long get_wchan(struct task_stru (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ }) +/* + * The below -8 is to reserve 8 bytes on top of the ring0 stack. + * This is necessary to guarantee that the entire "struct pt_regs" + * is accessable even if the CPU haven't stored the SS/ESP registers + * on the stack (interrupt gate does not save these registers + * when switching to the same priv ring). + * Therefore beware: accessing the xss/esp fields of the + * "struct pt_regs" is possible, but they may contain the + * completely wrong values. + */ #define task_pt_regs(task) \ ({ \ struct pt_regs *__regs__; \ - __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info); \ + __regs__ = (struct pt_regs *)(KSTK_TOP((task)->thread_info)-8); \ __regs__ - 1; \ }) _