[PATCH] i386: Fix places where using %gs changes the usermode ABI
There are a few places where the change in struct pt_regs and the use of %gs affect the userspace ABI. These are primarily debugging interfaces where thread state can be inspected or extracted. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Chuck Ebbert <76306.1226@compuserve.com> Cc: Zachary Amsden <zach@vmware.com> Cc: Jan Beulich <jbeulich@novell.com> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org>
This commit is contained in:
parent
f95d47caae
commit
66e10a44d7
4 changed files with 11 additions and 16 deletions
|
@ -315,8 +315,8 @@ void show_regs(struct pt_regs * regs)
|
|||
regs->eax,regs->ebx,regs->ecx,regs->edx);
|
||||
printk("ESI: %08lx EDI: %08lx EBP: %08lx",
|
||||
regs->esi, regs->edi, regs->ebp);
|
||||
printk(" DS: %04x ES: %04x\n",
|
||||
0xffff & regs->xds,0xffff & regs->xes);
|
||||
printk(" DS: %04x ES: %04x GS: %04x\n",
|
||||
0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
|
||||
|
||||
cr0 = read_cr0();
|
||||
cr2 = read_cr2();
|
||||
|
@ -509,7 +509,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
|
|||
dump->regs.ds = regs->xds;
|
||||
dump->regs.es = regs->xes;
|
||||
savesegment(fs,dump->regs.fs);
|
||||
savesegment(gs,dump->regs.gs);
|
||||
dump->regs.gs = regs->xgs;
|
||||
dump->regs.orig_eax = regs->orig_eax;
|
||||
dump->regs.eip = regs->eip;
|
||||
dump->regs.cs = regs->xcs;
|
||||
|
|
|
@ -94,13 +94,9 @@ static int putreg(struct task_struct *child,
|
|||
return -EIO;
|
||||
child->thread.fs = value;
|
||||
return 0;
|
||||
case GS:
|
||||
if (value && (value & 3) != 3)
|
||||
return -EIO;
|
||||
child->thread.gs = value;
|
||||
return 0;
|
||||
case DS:
|
||||
case ES:
|
||||
case GS:
|
||||
if (value && (value & 3) != 3)
|
||||
return -EIO;
|
||||
value &= 0xffff;
|
||||
|
@ -116,8 +112,8 @@ static int putreg(struct task_struct *child,
|
|||
value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
|
||||
break;
|
||||
}
|
||||
if (regno > GS*4)
|
||||
regno -= 2*4;
|
||||
if (regno > ES*4)
|
||||
regno -= 1*4;
|
||||
put_stack_long(child, regno - sizeof(struct pt_regs), value);
|
||||
return 0;
|
||||
}
|
||||
|
@ -131,18 +127,16 @@ static unsigned long getreg(struct task_struct *child,
|
|||
case FS:
|
||||
retval = child->thread.fs;
|
||||
break;
|
||||
case GS:
|
||||
retval = child->thread.gs;
|
||||
break;
|
||||
case DS:
|
||||
case ES:
|
||||
case GS:
|
||||
case SS:
|
||||
case CS:
|
||||
retval = 0xffff;
|
||||
/* fall through */
|
||||
default:
|
||||
if (regno > GS*4)
|
||||
regno -= 2*4;
|
||||
if (regno > ES*4)
|
||||
regno -= 1*4;
|
||||
regno = regno - sizeof(struct pt_regs);
|
||||
retval &= get_stack_long(child, regno);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
|
|||
pr_reg[7] = regs->xds; \
|
||||
pr_reg[8] = regs->xes; \
|
||||
savesegment(fs,pr_reg[9]); \
|
||||
savesegment(gs,pr_reg[10]); \
|
||||
pr_reg[10] = regs->xgs; \
|
||||
pr_reg[11] = regs->orig_eax; \
|
||||
pr_reg[12] = regs->eip; \
|
||||
pr_reg[13] = regs->xcs; \
|
||||
|
|
|
@ -71,6 +71,7 @@ static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
|
|||
info->regs.xss = __KERNEL_DS;
|
||||
info->regs.xds = __USER_DS;
|
||||
info->regs.xes = __USER_DS;
|
||||
info->regs.xgs = __KERNEL_PDA;
|
||||
}
|
||||
|
||||
extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
|
||||
|
|
Loading…
Reference in a new issue