linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* How to detect STACKOVEFLOW on mips
@ 2010-06-30  5:59 Adam Jiang
  2010-06-30 14:27 ` Phil Staub
  2010-06-30 14:50 ` Ralf Baechle
  0 siblings, 2 replies; 11+ messages in thread
From: Adam Jiang @ 2010-06-30  5:59 UTC (permalink / raw)
  To: linux-mips

Hello, list.

I'm having a problem with kernel mode stack on my box. It seems that
STACKOVERFLOW happened to Linux kernel. However, I can't prove it
because the lack of any detection in __do_IRQ() function just like on
the other architectures. If you know something about, please help me
on following two questions.
- Is there any possible to do this on MIPS?
- or, more simple question, how could I get the address $sp pointed by
asm() notation in C?

Any suggestion from you will be appreciated.

Best regards,
/Adam

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30  5:59 How to detect STACKOVEFLOW on mips Adam Jiang
@ 2010-06-30 14:27 ` Phil Staub
  2010-06-30 14:57   ` Ralf Baechle
  2010-06-30 18:16   ` David VomLehn
  2010-06-30 14:50 ` Ralf Baechle
  1 sibling, 2 replies; 11+ messages in thread
From: Phil Staub @ 2010-06-30 14:27 UTC (permalink / raw)
  To: Adam Jiang; +Cc: linux-mips

On 06/29/2010 10:59 PM, Adam Jiang wrote:
> Hello, list.
>
> I'm having a problem with kernel mode stack on my box. It seems that
> STACKOVERFLOW happened to Linux kernel. However, I can't prove it
> because the lack of any detection in __do_IRQ() function just like on
> the other architectures. If you know something about, please help me
> on following two questions.
> - Is there any possible to do this on MIPS?

The mechanisms I know about for detecting stack overflow include:

1. Use of the MMU - stack ends at a page boundary, adjacent page is
either unmapped or mapped read-only and causes an exception if violated.

2. Hooks inserted into toolchain to cause any stack decrement to be
first tested against a limit.

3. Fill entire stack with a recognizable pattern before first
use. After suspected stack overflow, check to see if the pattern has
been disturbed in the area of the stack limit.

(Disclaimer: I've used all of these in some form on other OSes, but
not on Linux. Someone else may have a more directly relevant answer.)

> - or, more simple question, how could I get the address $sp pointed by
> asm() notation in C?

How about something like:

{
	long x;
	...
	asm("move %0,$29":"=g"(x));
	...
}

Phil

>
> Any suggestion from you will be appreciated.
>
> Best regards,
> /Adam
>
>


-- 
Phil Staub, Senior Member of Technical Staff, Wind River
Direct: 702.290.0470 Fax: 702.982.0085

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30  5:59 How to detect STACKOVEFLOW on mips Adam Jiang
  2010-06-30 14:27 ` Phil Staub
@ 2010-06-30 14:50 ` Ralf Baechle
  2010-06-30 21:57   ` Matt Fleming
  1 sibling, 1 reply; 11+ messages in thread
From: Ralf Baechle @ 2010-06-30 14:50 UTC (permalink / raw)
  To: Adam Jiang; +Cc: linux-mips

On Wed, Jun 30, 2010 at 02:59:42PM +0900, Adam Jiang wrote:

> I'm having a problem with kernel mode stack on my box. It seems that
> STACKOVERFLOW happened to Linux kernel. However, I can't prove it
> because the lack of any detection in __do_IRQ() function just like on
> the other architectures. If you know something about, please help me
> on following two questions.
> - Is there any possible to do this on MIPS?
> - or, more simple question, how could I get the address $sp pointed by
> asm() notation in C?

Due to the large register frame on MIPS the stack is 8kB on 32-bit, 16kB
on 64-bit or PAGE_SIZE, whatever is larger.  This is should be hard to
overflow by accident unless doing something outrageously stupid.

To access the stackpointer include <linux/thread_info.h>.  The function
current_thread_info() will return the pointer to the struct thread_info
of the current thread.  This structure is located at the bottom of the
stack.  With something like

  register void *stackp __asm__("$29");

you then can access the stack pointer as the stackp variable.  You
obviously need to maintain the relation

  current_thread_info() + 1 < stackp

at all times - and you better have a bit of extra space available just for
peace of mind.

There used to be some code for other architectures that zeros the stack
page and counts how much of that has been overwritten by the stack.  That
was never ported to MIPS.

Another helper to find functions that do excessive static allocations is
"make checkstack".

  Ralf

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30 14:27 ` Phil Staub
@ 2010-06-30 14:57   ` Ralf Baechle
  2010-06-30 18:16   ` David VomLehn
  1 sibling, 0 replies; 11+ messages in thread
From: Ralf Baechle @ 2010-06-30 14:57 UTC (permalink / raw)
  To: Phil Staub; +Cc: Adam Jiang, linux-mips

On Wed, Jun 30, 2010 at 07:27:10AM -0700, Phil Staub wrote:

> >I'm having a problem with kernel mode stack on my box. It seems that
> >STACKOVERFLOW happened to Linux kernel. However, I can't prove it
> >because the lack of any detection in __do_IRQ() function just like on
> >the other architectures. If you know something about, please help me
> >on following two questions.
> >- Is there any possible to do this on MIPS?
> 
> The mechanisms I know about for detecting stack overflow include:
> 
> 1. Use of the MMU - stack ends at a page boundary, adjacent page is
> either unmapped or mapped read-only and causes an exception if violated.

Won't easily work on MIPS as the stack is allocated in KSEG0 / XKPHYS
which are unmapped segments.  It would be necessary to relocate the stack
into a mapped space.

Ultra-ancient Linux/MIPS kernels actually used to do that but that code
may well even predate everything that still exists on linux-mips.org.

> 2. Hooks inserted into toolchain to cause any stack decrement to be
> first tested against a limit.
> 
> 3. Fill entire stack with a recognizable pattern before first
> use. After suspected stack overflow, check to see if the pattern has
> been disturbed in the area of the stack limit.

This was afaik never ported to MIPS though that'd be easy.

> (Disclaimer: I've used all of these in some form on other OSes, but
> not on Linux. Someone else may have a more directly relevant answer.)
> 
> >- or, more simple question, how could I get the address $sp pointed by
> >asm() notation in C?
> 
> How about something like:
> 
> {
> 	long x;
> 	...
> 	asm("move %0,$29":"=g"(x));
> 	...
> }

That will do.  Or even something portable like:

{
	unsigned long foo;

	return &foo;
}

which used to work (GNU alloca and others were using this) but I'm sure
GCC has learned how to optimize this to shreds.

  Ralf

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30 14:27 ` Phil Staub
  2010-06-30 14:57   ` Ralf Baechle
@ 2010-06-30 18:16   ` David VomLehn
  2010-06-30 22:13     ` Maciej W. Rozycki
  1 sibling, 1 reply; 11+ messages in thread
From: David VomLehn @ 2010-06-30 18:16 UTC (permalink / raw)
  To: Phil Staub; +Cc: Adam Jiang, linux-mips

On Wed, Jun 30, 2010 at 09:27:10AM -0500, Phil Staub wrote:
> On 06/29/2010 10:59 PM, Adam Jiang wrote:
> > Hello, list.
> >
> > I'm having a problem with kernel mode stack on my box. It seems that
> > STACKOVERFLOW happened to Linux kernel. However, I can't prove it
> > because the lack of any detection in __do_IRQ() function just like on
> > the other architectures. If you know something about, please help me
> > on following two questions.
> > - Is there any possible to do this on MIPS?
> 
> The mechanisms I know about for detecting stack overflow include:
> 
> 1. Use of the MMU - stack ends at a page boundary, adjacent page is
> either unmapped or mapped read-only and causes an exception if violated.

Kernel stacks are allocated in kseg0, which is direct mapped. This means
conversions from virtual to physical addresses don't use the TLBs, so
this strategy doesn't work on MIPS.

> 2. Hooks inserted into toolchain to cause any stack decrement to be
> first tested against a limit.

I don't know of MIPS hooks for this but there may be some. It would have
to be tuned specifically for the kernel because of the way you need to get
the stack bounds (see below).

> 3. Fill entire stack with a recognizable pattern before first
> use. After suspected stack overflow, check to see if the pattern has
> been disturbed in the area of the stack limit.

This one pretty much always works. The only exception is if you allocate
a big array on the stack and don't use enough of it to alter memory in
the area at which you are looking.  Allocating big arrays on the stack
is a kernel no-no, so you should be in good shape here.

To implement this, you have to know the stack bounds. Start by getting
getting current_thread_info(), which is a pointer to a struct
thread_info. The struct thread_info is at the low address part of the
memory allocated for a task stack, which is given by union thread_union.
So, you can cast current_thread_info to a union thread_union* and put
the result in, say, p. Then the valid stack space is from
(char*)(&p->thread_info + 1) to ((char *)p + THREAD_SIZE/sizeof(long)).

> (Disclaimer: I've used all of these in some form on other OSes, but
> not on Linux. Someone else may have a more directly relevant answer.)
> 
> > - or, more simple question, how could I get the address $sp pointed by
> > asm() notation in C?
> 
> How about something like:
> 
> {
> 	long x;
> 	...
> 	asm("move %0,$29":"=g"(x));
> 	...
> }

Depending on the version of gcc you are using, you should also be able
to use __builtin_frame_address(), though I haven't tried this in the kernel.

> Phil
> 
> > Best regards,
> > /Adam

-- 
David VL

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30 14:50 ` Ralf Baechle
@ 2010-06-30 21:57   ` Matt Fleming
  2010-07-05 10:56     ` Ralf Baechle
  0 siblings, 1 reply; 11+ messages in thread
From: Matt Fleming @ 2010-06-30 21:57 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, Adam Jiang

On Wed, 30 Jun 2010 15:50:06 +0100, Ralf Baechle <ralf@linux-mips.org> wrote:
> 
> There used to be some code for other architectures that zeros the stack
> page and counts how much of that has been overwritten by the stack.  That
> was never ported to MIPS.
> 
> Another helper to find functions that do excessive static allocations is
> "make checkstack".

Both SH and sparc use the mcount function (enabled with the -pg switch
to gcc) to check the stack has not overflowed. The relevant code is in
arch/{sh,sparc}/lib/mcount.S. This checks the stack pointer value on
every function call. Yeah, it's heavy-weight, but an implementation for
MIPS should be able to catch almost the exact point at which stack
overflow occurs.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30 18:16   ` David VomLehn
@ 2010-06-30 22:13     ` Maciej W. Rozycki
  0 siblings, 0 replies; 11+ messages in thread
From: Maciej W. Rozycki @ 2010-06-30 22:13 UTC (permalink / raw)
  To: David VomLehn; +Cc: Phil Staub, Adam Jiang, linux-mips

On Wed, 30 Jun 2010, David VomLehn wrote:

> > How about something like:
> > 
> > {
> > 	long x;
> > 	...
> > 	asm("move %0,$29":"=g"(x));
> > 	...
> > }
> 
> Depending on the version of gcc you are using, you should also be able
> to use __builtin_frame_address(), though I haven't tried this in the kernel.

 It works just fine with a zero argument; the usual restrictions apply to 
non-zero arguments.  Or alternatively an explicit register variable will 
do as suggested by Ralf.  Both approaches result in a bit better code than 
an explicit move; the former is portable to other platforms even. :)

  Maciej

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-06-30 21:57   ` Matt Fleming
@ 2010-07-05 10:56     ` Ralf Baechle
  2010-07-05 13:09       ` Matt Fleming
  0 siblings, 1 reply; 11+ messages in thread
From: Ralf Baechle @ 2010-07-05 10:56 UTC (permalink / raw)
  To: Matt Fleming; +Cc: linux-mips, Adam Jiang

On Wed, Jun 30, 2010 at 10:57:41PM +0100, Matt Fleming wrote:

> On Wed, 30 Jun 2010 15:50:06 +0100, Ralf Baechle <ralf@linux-mips.org> wrote:
> > 
> > There used to be some code for other architectures that zeros the stack
> > page and counts how much of that has been overwritten by the stack.  That
> > was never ported to MIPS.
> > 
> > Another helper to find functions that do excessive static allocations is
> > "make checkstack".
> 
> Both SH and sparc use the mcount function (enabled with the -pg switch
> to gcc) to check the stack has not overflowed. The relevant code is in
> arch/{sh,sparc}/lib/mcount.S. This checks the stack pointer value on
> every function call. Yeah, it's heavy-weight, but an implementation for
> MIPS should be able to catch almost the exact point at which stack
> overflow occurs.

Which often isn't so helpful.  The alarm gets triggered on the last stack
pointer decrement but according to murphy the overflow has happened 10
levels up in the callchain.

  Ralf

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-07-05 10:56     ` Ralf Baechle
@ 2010-07-05 13:09       ` Matt Fleming
  2010-07-05 13:35         ` Ralf Baechle
  0 siblings, 1 reply; 11+ messages in thread
From: Matt Fleming @ 2010-07-05 13:09 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, Adam Jiang

On Mon, Jul 05, 2010 at 11:56:27AM +0100, Ralf Baechle wrote:
> On Wed, Jun 30, 2010 at 10:57:41PM +0100, Matt Fleming wrote:
> 
> > On Wed, 30 Jun 2010 15:50:06 +0100, Ralf Baechle <ralf@linux-mips.org> wrote:
> > > 
> > > There used to be some code for other architectures that zeros the stack
> > > page and counts how much of that has been overwritten by the stack.  That
> > > was never ported to MIPS.
> > > 
> > > Another helper to find functions that do excessive static allocations is
> > > "make checkstack".
> > 
> > Both SH and sparc use the mcount function (enabled with the -pg switch
> > to gcc) to check the stack has not overflowed. The relevant code is in
> > arch/{sh,sparc}/lib/mcount.S. This checks the stack pointer value on
> > every function call. Yeah, it's heavy-weight, but an implementation for
> > MIPS should be able to catch almost the exact point at which stack
> > overflow occurs.
> 
> Which often isn't so helpful.  The alarm gets triggered on the last stack
> pointer decrement but according to murphy the overflow has happened 10
> levels up in the callchain.

Last decrement? The alarm should be triggered the next time the
function in which the overflow occurs makes a function call. I don't
see how you could go down a level of the callchain and not trigger the
alarm if the overflow has happened?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-07-05 13:09       ` Matt Fleming
@ 2010-07-05 13:35         ` Ralf Baechle
  2010-07-05 14:08           ` Matt Fleming
  0 siblings, 1 reply; 11+ messages in thread
From: Ralf Baechle @ 2010-07-05 13:35 UTC (permalink / raw)
  To: Matt Fleming; +Cc: linux-mips, Adam Jiang

On Mon, Jul 05, 2010 at 02:09:31PM +0100, Matt Fleming wrote:

> > Which often isn't so helpful.  The alarm gets triggered on the last stack
> > pointer decrement but according to murphy the overflow has happened 10
> > levels up in the callchain.
> 
> Last decrement? The alarm should be triggered the next time the
> function in which the overflow occurs makes a function call. I don't
> see how you could go down a level of the callchain and not trigger the
> alarm if the overflow has happened?

guilt()
{
	char array[6000];

	blurb(&array);
}

blurb(void *p)
{
	frob(p);
}

With the deep nesting of the current kernel there is a good chance a
check in mcount will not be triggered in blurb() but possibly in frob
or even further down the callchain.

  Ralf

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to detect STACKOVEFLOW on mips
  2010-07-05 13:35         ` Ralf Baechle
@ 2010-07-05 14:08           ` Matt Fleming
  0 siblings, 0 replies; 11+ messages in thread
From: Matt Fleming @ 2010-07-05 14:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, Adam Jiang

On Mon, Jul 05, 2010 at 02:35:33PM +0100, Ralf Baechle wrote:
> On Mon, Jul 05, 2010 at 02:09:31PM +0100, Matt Fleming wrote:
> 
> > > Which often isn't so helpful.  The alarm gets triggered on the last stack
> > > pointer decrement but according to murphy the overflow has happened 10
> > > levels up in the callchain.
> > 
> > Last decrement? The alarm should be triggered the next time the
> > function in which the overflow occurs makes a function call. I don't
> > see how you could go down a level of the callchain and not trigger the
> > alarm if the overflow has happened?
> 
> guilt()
> {
> 	char array[6000];
> 
> 	blurb(&array);
> }
> 
> blurb(void *p)
> {
> 	frob(p);
> }
> 
> With the deep nesting of the current kernel there is a good chance a
> check in mcount will not be triggered in blurb() but possibly in frob
> or even further down the callchain.

Ah, I think I see what you mean. You're saying that you may not find
the culprit function using the massive amount of stack spac, which
eventually leads to the overflow? Yeah, that's a fair point. I think
if the mcount technique was used in conjunction with
CONFIG_DEBUG_STACK_USAGE it might be more helpful in that situation.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-07-05 14:08 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-30  5:59 How to detect STACKOVEFLOW on mips Adam Jiang
2010-06-30 14:27 ` Phil Staub
2010-06-30 14:57   ` Ralf Baechle
2010-06-30 18:16   ` David VomLehn
2010-06-30 22:13     ` Maciej W. Rozycki
2010-06-30 14:50 ` Ralf Baechle
2010-06-30 21:57   ` Matt Fleming
2010-07-05 10:56     ` Ralf Baechle
2010-07-05 13:09       ` Matt Fleming
2010-07-05 13:35         ` Ralf Baechle
2010-07-05 14:08           ` Matt Fleming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).