Figure 103 Frame on the User Mode stack

User Mil* tart ih^na ha ndli prelum ad dries Signal kandlirt panmeter viiq If: Ptmhs hardware hdil»!! : rating-point register! Blacked ri.i -lime signal:. &igEEturn() imocatian

Jr?wioui iottcoiitinu.

The setup_frame( ) function starts by invoking get_sigframe( ) to compute the first memory location of the frame. That memory location is usually^4! in the User Mode stack, so the function returns the value:

[4] Linux allows processes to specify an alternate stack for their signal handlers by invoking the sigaltstack( ) system call;

this feature is also requested by the X/Open standard. When an alternate stack is present, the get_sigframe( ) function returns an address inside that stack. We don't discuss this feature further, since it is conceptually similar to regular signal handling.

(regs->esp - sizeof(struct sigframe)) & 0xfffffff8

Since stacks grow toward lower addresses, the initial address of the frame is obtained by subtracting its size from the address of the current stack top and aligning the result to a multiple of 8.

The returned address is then verified by means of the access_ok macro; if it is valid, the function repeatedly invokes _ _put_user( ) to fill all the fields of the frame. Once this is done, it modifies the regs area of the Kernel Mode stack, thus ensuring that control is transferred to the signal handler when current resumes its execution in User Mode:

regs->esp = (unsigned long) frame;

regs->eip = (unsigned long) ka-> handler;

The setup_frame( ) function terminates by resetting the segmentation registers saved on the Kernel Mode stack to their default value. Now the information needed by the signal handler is on the top of the User Mode stack.

The setup_rt_frame( ) function is very similar to setup_frame( ), but it puts on the User Mode stack an extended frame (stored in the rt_sigframe data structure) that also includes the content of the siginfo_t table associated with the signal. Evaluating the signal flags

After setting up the User Mode stack, the handle_signal( ) function checks the values of the flags associated with the signal.

If the received signal has the sa_oneshot flag set, it must be reset to its default action so that further occurrences of the same signal will not trigger the execution of the signal handler:

if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL;

Moreover, if the signal does not have the sa_nodefer flag set, the signals in the sa mask field of the sigaction table must be blocked during the execution of the signal handler:

spin lock irq(&current->sigmask lock);

sigorsets(&current->blocked, &current->blocked, &ka-> mask);

sigaddset(&current->blocked, sig);

recalc sigpending(current);

spin unlock irq(&current->sigmask lock);

As described earlier, the recalc_sigpending( ) function checks whether the process has nonblocked pending signals and sets its sigpending field accordingly.

The function returns then to do_signal( ), which also returns immediately. Starting the signal handler

When do_signal( ) returns, the current process resumes its execution in User Mode. Because of the preparation by setup_frame( ) described earlier, the eip register points to the first instruction of the signal handler, while esp points to the first memory location of the frame that has been pushed on top of the User Mode stack. As a result, the signal handler is executed. Terminating the signal handler

When the signal handler terminates, the return address on top of the stack points to the code in the retcode field of the frame. For signals without siginfo_t table, the code is equivalent to the following assembly language instructions:

popl %eax movl $ NR sigreturn, %eax int $0x80

Therefore, the signal number (that is, the sig field of the frame) is discarded from the stack, and the sigreturn( ) system call is then invoked.

The sys_sigreturn( ) function computes the address of the pt_regs data structure regs, which contains the hardware context of the User Mode process (see Section 9.2.3).

From the value stored in the esp field, it can thus derive and check the frame address inside the User Mode stack:

frame = (struct sigframe *)(regs.esp - 8); if (verify_area(VERIFY_READ, frame, sizeof(*frame)) { force_sig(SIGSEGV, current); return 0;

Then the function copies the bit array of signals that were blocked before invoking the signal handler from the sc field of the frame to the blocked field of current. As a result, all signals that have been masked for the execution of the signal handler are unblocked. The recalc_sigpending( ) function is then invoked.

The sys_sigreturn( ) function must at this point copy the process hardware context from the sc field of the frame to the Kernel Mode stack and remove the frame from the User Mode stack; it performs these two tasks by invoking the restore_sigcontext( ) function.

If the signal was sent by a system call like rt_sigqueueinfo( ) that required a siginfo_t table to be associated to the signal, the mechanism is very similar. The return code in the retcode field of the extended frame invokes the rt_sigreturn( ) system call; the corresponding sys_rt_sigreturn( ) service routine copies the process hardware context from the extended frame to the Kernel Mode stack and restores the original User Mode stack content by removing the extended frame from it.

Continue reading here: Reexecution of System Calls

Was this article helpful?

0 0