WinExperements wrote:i am trying to implement the POSIX signal handling for userspace programs. And i have some questions about it. So my current realization successfully calls the corespondending registred handler, but as soon as i call any kind of system call i got #PF because of scheduler stack corruption.
There be dragons!
You want to handle the signal on the user stack, so if you're corrupting your scheduler stack, you have bigger problems.
When you want the user level to handle a signal, you generally do the following:
- Arrange for the user signal handler to run upon return to user mode - This involves changing the return address on the kernel stack to point to the user level signal code.
- Also push extra information on the user stack that the user level signal code will use to restore the previous context.
- Return to user space, which invokes the user level code in the signal handler.
Traditionally, the kernel would push code onto the stack to handle the restoration of user context, then push the return address to the on-stack code, then context information and arguments to the signal handler, then finally arrange to return to the signal handler. The signal handler does its stuff, returns to the on-stack code, which restores the user context using sigreturn system call or similar.
An example of the on-stack code that does this return can be found here:
http://bxr.su/NetBSD/lib/libc/compat/ar ... igtramp1.S
This is complicated (or I would argue simplified) by non-executable stacks in modern systems, which preclude the use of on-stack code, and instead the libc passes the address of a function to replace the on-stack code (search for SA_RESTORER in the sigaction(2) manpage for Linux.) This restorer is responsible for calling sigreturn.
Sigreturn itself takes the context pushed onto the stack when the kernel was setting up the signal, and restores that context. The context would include the general purpose registers, signal mask, basically everything the kernel would preserve and restore on entry/exit from user space.
WinExperements wrote:
So my question is: Did i need to create a separate stack for signal processing?
In all of this, there is no requirement for a separate user stack, the signal handling code can use the same user stack so long as there is sufficient space.
WinExperements wrote:
If yes, did i need to push into it the return value for ret instruction where the process is stopped?
You need more than just the return address . You also need to save the whole user context. Signals can be delivered asynchronously, interrupting the user code, so you need to restore all the user CPU state.
WinExperements wrote:
Or how to correctly fix stack corruption?
No idea. You'd need to describe what this stack is. User scheduler, kernel scheduler?