stack size limit on ppc/ppc64
Anton Blanchard
anton at samba.org
Wed Nov 5 13:24:43 EST 2003
Hi Anil,
> I have code which shouldn't work, working under ppc64 linux.
Sounds like a feature to me :)
> Theoretically, above code should cause segmentation violation. But on ppc64
> linux, it puts variable 'p ' in stack segment, I looked at /proc/pid/maps,
> and there was huge memory area from 0x50000000 ---> 0xFFFFF000.
I guess technically its a bug, Paul has fixed it in ppc32. I attached
the relevant parts of his fix (it comes from arch/ppc/kernel/fault.c)
There are a few things to change for ppc64:
- add the 64bit versions of the store with update instructions
- keep in mind the 64bit ABI allows space below the sp to be used (it
looks like the 2048 constant will cover this)
Does anyone feel in the mood to work on this?
Anton
/*
* Check whether the instruction at regs->nip is a store using
* an update addressing form which will update r1.
*/
static int store_updates_sp(struct pt_regs *regs)
{
unsigned int inst;
if (get_user(inst, (unsigned int *)regs->nip))
return 0;
/* check for 1 in the rA field */
if (((inst >> 16) & 0x1f) != 1)
return 0;
/* check major opcode */
switch (inst >> 26) {
case 37: /* stwu */
case 39: /* stbu */
case 45: /* sthu */
case 53: /* stfsu */
case 55: /* stfdu */
return 1;
case 31:
/* check minor opcode */
switch ((inst >> 1) & 0x3ff) {
case 183: /* stwux */
case 247: /* stbux */
case 439: /* sthux */
case 695: /* stfsux */
case 759: /* stfdux */
return 1;
}
}
return 0;
}
void do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code)
{
...
/*
* A user-mode access to an address a long way below
* the stack pointer is only valid if the instruction
* is one which would update the stack pointer to the
* address accessed if the instruction completed,
* i.e. either stwu rs,n(r1) or stwux rs,r1,rb
* (or the byte, halfword, float or double forms).
*
* If we don't check this then any write to the area
* between the last mapped region and the stack will
* expand the stack rather than segfaulting.
*/
if (address + 2048 < uregs->gpr[1]
&& (!user_mode(regs) || !store_updates_sp(regs)))
goto bad_area;
}
** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc64-dev
mailing list