[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);
|
regs->eax,regs->ebx,regs->ecx,regs->edx);
|
||||||
printk("ESI: %08lx EDI: %08lx EBP: %08lx",
|
printk("ESI: %08lx EDI: %08lx EBP: %08lx",
|
||||||
regs->esi, regs->edi, regs->ebp);
|
regs->esi, regs->edi, regs->ebp);
|
||||||
printk(" DS: %04x ES: %04x\n",
|
printk(" DS: %04x ES: %04x GS: %04x\n",
|
||||||
0xffff & regs->xds,0xffff & regs->xes);
|
0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
|
||||||
|
|
||||||
cr0 = read_cr0();
|
cr0 = read_cr0();
|
||||||
cr2 = read_cr2();
|
cr2 = read_cr2();
|
||||||
|
@ -509,7 +509,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
|
||||||
dump->regs.ds = regs->xds;
|
dump->regs.ds = regs->xds;
|
||||||
dump->regs.es = regs->xes;
|
dump->regs.es = regs->xes;
|
||||||
savesegment(fs,dump->regs.fs);
|
savesegment(fs,dump->regs.fs);
|
||||||
savesegment(gs,dump->regs.gs);
|
dump->regs.gs = regs->xgs;
|
||||||
dump->regs.orig_eax = regs->orig_eax;
|
dump->regs.orig_eax = regs->orig_eax;
|
||||||
dump->regs.eip = regs->eip;
|
dump->regs.eip = regs->eip;
|
||||||
dump->regs.cs = regs->xcs;
|
dump->regs.cs = regs->xcs;
|
||||||
|
|
|
@ -94,13 +94,9 @@ static int putreg(struct task_struct *child,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
child->thread.fs = value;
|
child->thread.fs = value;
|
||||||
return 0;
|
return 0;
|
||||||
case GS:
|
|
||||||
if (value && (value & 3) != 3)
|
|
||||||
return -EIO;
|
|
||||||
child->thread.gs = value;
|
|
||||||
return 0;
|
|
||||||
case DS:
|
case DS:
|
||||||
case ES:
|
case ES:
|
||||||
|
case GS:
|
||||||
if (value && (value & 3) != 3)
|
if (value && (value & 3) != 3)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
value &= 0xffff;
|
value &= 0xffff;
|
||||||
|
@ -116,8 +112,8 @@ static int putreg(struct task_struct *child,
|
||||||
value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
|
value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (regno > GS*4)
|
if (regno > ES*4)
|
||||||
regno -= 2*4;
|
regno -= 1*4;
|
||||||
put_stack_long(child, regno - sizeof(struct pt_regs), value);
|
put_stack_long(child, regno - sizeof(struct pt_regs), value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -131,18 +127,16 @@ static unsigned long getreg(struct task_struct *child,
|
||||||
case FS:
|
case FS:
|
||||||
retval = child->thread.fs;
|
retval = child->thread.fs;
|
||||||
break;
|
break;
|
||||||
case GS:
|
|
||||||
retval = child->thread.gs;
|
|
||||||
break;
|
|
||||||
case DS:
|
case DS:
|
||||||
case ES:
|
case ES:
|
||||||
|
case GS:
|
||||||
case SS:
|
case SS:
|
||||||
case CS:
|
case CS:
|
||||||
retval = 0xffff;
|
retval = 0xffff;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
if (regno > GS*4)
|
if (regno > ES*4)
|
||||||
regno -= 2*4;
|
regno -= 1*4;
|
||||||
regno = regno - sizeof(struct pt_regs);
|
regno = regno - sizeof(struct pt_regs);
|
||||||
retval &= get_stack_long(child, regno);
|
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[7] = regs->xds; \
|
||||||
pr_reg[8] = regs->xes; \
|
pr_reg[8] = regs->xes; \
|
||||||
savesegment(fs,pr_reg[9]); \
|
savesegment(fs,pr_reg[9]); \
|
||||||
savesegment(gs,pr_reg[10]); \
|
pr_reg[10] = regs->xgs; \
|
||||||
pr_reg[11] = regs->orig_eax; \
|
pr_reg[11] = regs->orig_eax; \
|
||||||
pr_reg[12] = regs->eip; \
|
pr_reg[12] = regs->eip; \
|
||||||
pr_reg[13] = regs->xcs; \
|
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.xss = __KERNEL_DS;
|
||||||
info->regs.xds = __USER_DS;
|
info->regs.xds = __USER_DS;
|
||||||
info->regs.xes = __USER_DS;
|
info->regs.xes = __USER_DS;
|
||||||
|
info->regs.xgs = __KERNEL_PDA;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
|
extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
|
||||||
|
|
Loading…
Reference in a new issue