Subject: signal delivering and stack frame
To: None <tech-kern@netbsd.org>
From: Emmanuel Dreyfus <p99dreyf@criens.u-psud.fr>
List: tech-kern
Date: 01/12/2001 13:44:59
In order to fix a few bugs in signal handling on COMPAT_LINUX for
PowerPC, I need to better understand what's going on during signal
handler invocation. The only documentation I have about this is design &
implementation of 4.4BSD, and the book says roughly that it is machine
dependent.

So here is what I understood, please correct me if there is something
wrong.

The process makes a system call. It creates a trapframe on the stack,
and enters the kernel.

The kernel sees that there is a pending signal, so prior to process
return to user mode, it modify the trapframe on the stack, so that the
process will jump to the signal handler on return to userland. It also
sets up a signal frame, which contains the trampoline code (used to do
the actual jump to the signal handler), and other information.

First question: what is the signal stack? I assume this must be an
alternate stack used to do the signal deleivering, but why it is used?
Is it a way of avoiding stack execution (and therefore avoid a class of
buffer overflow problems by setting stack pages as unexecutables)?

Before returning, as far as I understood, the stack looks like this:
(upper addresses are on bottom)

                   lower addresses
                  | nothing      |
stack pointer --->|--------------|
                  | signal frame |
frame ----------->|--------------|   (X)
                  | trap frame   |
                  |--------------|  
                  higher addresses

(The frame pointer is used in the sendsig function)

Another question about LINUX_COMPAT: In the alpha and i386 versions, the
trapframe is assumed to be BSD style. I expected it to be Linux style,
since it is the Linux executable that did set it up. Why is it BSD
style?

The signal frame has to be Linux style for Linux binaries, since it is
used by the binary.

When the signal handler returns, it returns to the trampoline code,
which in turns calls the sig_return system call. This system call
restores registers according to what was saved in the signal frame, and
it reset the stack pointer to the (X) on the above picture, which is
where the frame pointer points.

Is that right?

Last question: in Linux/PowerPC, the signal frame is setup like this
(upper addresses on the bottom)

- one or more blocks of (struct sigcontext, a gap of 64 bytes)
- a sigcontext structure.

Does anyone have an idea of why there could be more than one sigcontext
stored here? Does it have something to do with interupted system calls?
And how does NetBSD works with interupted system calls?

Thank you for your help...

-- 
Emmanuel Dreyfus.  
Pas de processeur Intel, pas de logiciels Microsoft:
Des programmes sains dans un ordinateur sain.
p99dreyf@criens.u-psud.fr