kernel: SIGINT user-handler delivery + sigreturn (PR 3/3)#334
Merged
Conversation
a02e1f2 to
3a3661a
Compare
66316cd to
904c56d
Compare
9c1c549 to
3ddc088
Compare
Adds full signal() handler delivery: when SIG_DFL/SIG_IGN aren't set and a user-virt handler is registered, the kernel builds a 48-byte sigcontext on the user stack (saved EIP / EFLAGS / ESP / pushad minus its ESP slot), rewrites the IRET frame to enter the handler at ring 3, and clears in_sigint_handler / pending_sigint. Handler ends with 'ret' to a 7-byte vDSO trampoline at user-virt 0x10450 which calls SYS_SYS_SIGRETURN. SYS_SYS_SIGRETURN validates the saved EIP/ESP are in user range, sanitizes EFLAGS (mask 0xDD5 keeps CF/PF/AF/ZF/SF/TF/DF/OF; IF forced on; IOPL/VM/NT/RF/AC dropped), and restores the user register state. EFLAGS sanitization prevents a malicious handler from escalating IOPL via a forged sigcontext on stack. The IRQ-handler dispatch macro is restructured to keep pushad on stack at dispatch time so signal_dispatch_user can capture the interrupted register state into the sigcontext. Every IRQ + syscall handler loses its explicit popad — the macro now owns it. The IRQ 6 (FDC) handler is converted from push/pop eax to pushad/popad to match the new macro contract. Closes the three-PR series: PR 1 was default-kill, PR 2 added SIG_IGN, this PR adds full user-handler delivery. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final PR in the SIGINT-handling stack: completes
signal(SIGINT, handler)so user programs can register a ring-3 handler that's invoked on Ctrl+C, with a clean return path back to the interrupted instruction.Stacks on:
SIG_DFL, basemain)SIG_IGNopt-out + libcsignal()shim (basesigint-1-default-kill)What user-handler delivery means
When a user-virt address is registered via
SYS_SYS_SIGNALand Ctrl+C arrives at the IRET-to-user epilogue:signal_dispatch_userbuilds a 48-byte sigcontext on the user stack capturing the interrupted EIP / EFLAGS / ESP / pushad slots (minus the pushad-ESP slot, which is the kernel ESP and meaningless).in_sigint_handleris set +pending_sigintcleared so a Ctrl+C burst doesn't re-enter the handler.ret, popping the sigcontext's first dword (a vDSO trampoline address at user-virt0x10450) into EIP.mov ah, SYS_SYS_SIGRETURN; int 0x30.signal_resume_after_handlervalidates the sigcontext, restores registers, sanitizes EFLAGS, and iretds back to the original interrupted EIP.Security note: EFLAGS sanitization
The saved EFLAGS in the sigcontext lives on the user stack and is fully writable from ring 3. Without sanitization, a malicious handler could forge a sigcontext with
IOPL=3and gain ring-3 in/out, or setVM=1to enter Virtual-8086 mode, etc.SYS_SYS_SIGRETURNtherefore masks the saved EFLAGS withUSER_EFLAGS_MASK = 0xDD5(whitelisting only CF/PF/AF/ZF/SF/TF/DF/OF) and OR'sEFLAGS_IF_BIT = 0x200so IF is always re-enabled. IOPL (bits 12-13), NT (14), RF (16), VM (17), AC (18), and VIF/VIP/ID (19-21) are all dropped. Mirrors Linux'srestore_sigcontextFIX_EFLAGSrationale.Macro restructure
SIGINT_TAIL_CHECKnow runs before popad, so the pushad slots on the kernel stack are still readable whensignal_dispatch_usercaptures them into the sigcontext. The CS check moves from[esp + 4]to[esp + 36](4 + pushad's 32 bytes), and the macro itself owns the popad in the no-dispatch path.Every IRQ + syscall handler that uses the macro loses its explicit
popad— the macro now owns it. The IRQ 6 (FDC) handler is also upgraded frompush eax / pop eaxtopushad / popadso its dispatch frame matches the new macro contract.Test plan
./make_os.shclean./tests/test_programs.py30/30 (now includessigint_test)./tests/test_asm.py20/20./tests/test_bboefs.py6/6tests/programs/sigint_test.cexercises register, handler runs, sigreturn restores state