User Stack Trace

Stone, Joshua I joshua.i.stone@intel.com
Wed Apr 18 18:08:00 GMT 2007


grundy wrote:
> On Tue, Apr 17, 2007 at 03:39:58PM -0400, Frank Ch. Eigler wrote:
>> Or containing corrupt/malicious stack data?
> Now this is interesting. One would have to corrupt return address prior
> to the syscall we're tracing. They would have to know exactly what we're
> tracing (possible) because once that call started to return it would
> turn left into the lake (if we weren't probing that call).

The left turn can be avoided by simply not returning. :)  A malicious 
program might look something like:

int main() {
	...
	// Do whatever tricks to munge up the return address..
	...
	// Loop for a while, making calls that we hope get probed...
	...
	exit(0);
}

Then the stack walk is corrupted, but the program won't ever see it.

Or, for that matter, the program could just restore the correct return 
address before it returns...

> I don't think there is an execution vulnerability, we just record the
> address. There is a chance of someone setting up a loop. Fake the second
> return address to point at the first return address which points at the
> second. 

Are there checks to make sure the addresses are reasonable?  I wonder if 
a malicious program could also lead your stack walk astray -- perhaps 
tricking you into printing a data value from some sensitive kernel area.

It looks like _stp_copy_from_user will make the right checks to make 
sure that the address is within the user's address space.  Your first 
print in the loop reads head->ret directly though, where head = 
nregs->ebp -- what if I faked my %ebp to point to kernel memory?

Or a more direct concern, even for non-malicious programs, what if the 
memory at %ebp is paged out?  This is unlikely, but it's still possible, 
right?  I think this first access to %ebp must be protected by a 
_stp_copy_from_user as well.

I'm not sure how much this potential kernel-pointer problem needs to be 
a concern though, as that compromised value is only returned to the 
person running the script (who already has root access, and could 
already write a script to access that value directly).

> In the jprobe code I based this on, I set an arbitrary depth limit of
> 20. Once you hit that bang out. So something like set a maximum depth
> variable to 20 or 30 and add this to the loop:
> while (--depth && head->ebp);

This is a must, to maintain our general SystemTap promise that scripts 
will never get trapped in an infinite loop.


Josh



More information about the Systemtap mailing list