Commit 07b047fc authored by akpm@osdl.org's avatar akpm@osdl.org Committed by Linus Torvalds
Browse files

[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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 06b425d8
...@@ -424,18 +424,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ...@@ -424,18 +424,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
struct task_struct *tsk; struct task_struct *tsk;
int err; int err;
childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; childregs = task_pt_regs(p);
/*
* 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 = *regs; *childregs = *regs;
childregs->eax = 0; childregs->eax = 0;
childregs->esp = esp; childregs->esp = esp;
...@@ -540,12 +529,7 @@ EXPORT_SYMBOL(dump_thread); ...@@ -540,12 +529,7 @@ EXPORT_SYMBOL(dump_thread);
*/ */
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
{ {
struct pt_regs ptregs; struct pt_regs ptregs = *task_pt_regs(tsk);
ptregs = *(struct pt_regs *)
((unsigned long)tsk->thread_info +
/* see comments in copy_thread() about -8 */
THREAD_SIZE - sizeof(ptregs) - 8);
ptregs.xcs &= 0xffff; ptregs.xcs &= 0xffff;
ptregs.xds &= 0xffff; ptregs.xds &= 0xffff;
ptregs.xes &= 0xffff; ptregs.xes &= 0xffff;
......
...@@ -875,8 +875,7 @@ static inline struct task_struct * alloc_idle_task(int cpu) ...@@ -875,8 +875,7 @@ static inline struct task_struct * alloc_idle_task(int cpu)
/* initialize thread_struct. we really want to avoid destroy /* initialize thread_struct. we really want to avoid destroy
* idle tread * idle tread
*/ */
idle->thread.esp = (unsigned long)(((struct pt_regs *) idle->thread.esp = (unsigned long)task_pt_regs(idle);
(THREAD_SIZE + (unsigned long) idle->thread_info)) - 1);
init_idle(idle, cpu); init_idle(idle, cpu);
return idle; return idle;
} }
......
...@@ -561,10 +561,20 @@ unsigned long get_wchan(struct task_struct *p); ...@@ -561,10 +561,20 @@ unsigned long get_wchan(struct task_struct *p);
(unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ (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) \ #define task_pt_regs(task) \
({ \ ({ \
struct pt_regs *__regs__; \ 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; \ __regs__ - 1; \
}) })
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment