Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Dec 1999 09:13:04 +1100
From:      Peter Jeremy <jeremyp@gsmx07.alcatel.com.au>
To:        David Gilbert <dgilbert@velocet.ca>
Cc:        stable@FreeBSD.ORG
Subject:   Re: Stack/i386-type ugh question.
Message-ID:  <99Dec1.090547est.40328@border.alcanet.com.au>
In-Reply-To: <14404.9723.200774.823194@trooper.velocet.net>
References:  <14404.9723.200774.823194@trooper.velocet.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On 1999-Dec-01 06:31:07 +1100, David Gilbert wrote:
>Ok... chasing down some memory corruption in FreeBSD's new vinum
>code.  I have the following:
...
>  So.  Which of those registers is the program counter?
As a full address, the PC is %cs:%eip (tf_cs and tf_eif in the trap frame).

>  I need to find the stack frame #6,
>basically... but I suppose I need to know a few things...
>
>Is frame #6 > or < the address of frame #5?

An i386 function call looks like:
        pushl   argN
        ...
        pushl   arg2
        pushl   arg1
        call    func
        addl    #...,%esp

Note that the `addl' can be deferred to improve speed (see -fno-defer-pop),
but the effect remains the same.

And a normal function looks like:
func:   pushl   %ebp
        movl    %esp,%ebp
        subl    #locals_size,%esp
...
        movl    %ebp,%esp
        popl    %ebp
        ret

There are also enter and leave instructions which handle the prologue
and epilogue, but the above code shows the linkage more clearly.  It
is also possible to disable the linked frame generation, but this isn't
done by default (see -fomit-frame-pointer).

Assuming a function in frame M calls frame (M-1), this gives a stack
frame as follows:

|                |  high memory
|----------------|
|      argN	 |
|      ... 	 |
|      arg2	 |
|      arg1	 |
|----------------|                    Frame M
| return address |
|----------------|
| previous frame |<+
|----------------| |
| local vars	 | |
|----------------| |  -------------------------
|      argN	 | |
|      ... 	 | |
|      arg2	 | |
|      arg1	 | |                  Frame M-1
|----------------| |
| return address | |
|----------------| |
| previous frame |-+  <-- %ebp
|----------------|
| local vars	 |
|----------------|    <-- %esp
|                |
|                |  low memory


gdb and ddb normally rely on the frame pointer (%ebp) to work out
the stack frames during a backtrace.  The problem here is that it
looks like there has been a buffer overflow within a local variable
which has trashed the saved frame pointer and return address.

It should be possible to locate a stack by rummaging through kernel
memory looking for the {previous frame},{return address} pairs, where
{previous frame} can be recognised by being an int aligned memory
address slightly higher (between 8 and ~200 bytes) than the current
address, which points to another {previous frame}.  {return address}
can be recognised as being within the kernel text segment.  (Finding
the correct stack will be more difficult).

If you are in a process context, then you should be able to find the
kernel stack associated with the active process (though I can't
remember how).

Peter


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?99Dec1.090547est.40328>