Commit 07b047fc2466249aff7cdb23fa0b0955a7a00d48
Committed by
Linus Torvalds
1 parent
06b425d80f
Exists in
master
and in
7 other branches
[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>
Showing 3 changed files with 14 additions and 21 deletions Side-by-side Diff
arch/i386/kernel/process.c
... | ... | @@ -424,18 +424,7 @@ |
424 | 424 | struct task_struct *tsk; |
425 | 425 | int err; |
426 | 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); | |
427 | + childregs = task_pt_regs(p); | |
439 | 428 | *childregs = *regs; |
440 | 429 | childregs->eax = 0; |
441 | 430 | childregs->esp = esp; |
... | ... | @@ -540,12 +529,7 @@ |
540 | 529 | */ |
541 | 530 | int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) |
542 | 531 | { |
543 | - struct pt_regs ptregs; | |
544 | - | |
545 | - ptregs = *(struct pt_regs *) | |
546 | - ((unsigned long)tsk->thread_info + | |
547 | - /* see comments in copy_thread() about -8 */ | |
548 | - THREAD_SIZE - sizeof(ptregs) - 8); | |
532 | + struct pt_regs ptregs = *task_pt_regs(tsk); | |
549 | 533 | ptregs.xcs &= 0xffff; |
550 | 534 | ptregs.xds &= 0xffff; |
551 | 535 | ptregs.xes &= 0xffff; |
arch/i386/kernel/smpboot.c
... | ... | @@ -875,8 +875,7 @@ |
875 | 875 | /* initialize thread_struct. we really want to avoid destroy |
876 | 876 | * idle tread |
877 | 877 | */ |
878 | - idle->thread.esp = (unsigned long)(((struct pt_regs *) | |
879 | - (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1); | |
878 | + idle->thread.esp = (unsigned long)task_pt_regs(idle); | |
880 | 879 | init_idle(idle, cpu); |
881 | 880 | return idle; |
882 | 881 | } |
include/asm-i386/processor.h
... | ... | @@ -561,10 +561,20 @@ |
561 | 561 | (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ |
562 | 562 | }) |
563 | 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 | + */ | |
564 | 574 | #define task_pt_regs(task) \ |
565 | 575 | ({ \ |
566 | 576 | struct pt_regs *__regs__; \ |
567 | - __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info); \ | |
577 | + __regs__ = (struct pt_regs *)(KSTK_TOP((task)->thread_info)-8); \ | |
568 | 578 | __regs__ - 1; \ |
569 | 579 | }) |
570 | 580 |