Reputation: 113
When my page fault handler interrupt gets called (it is supposed to hang the system), there are some variables pushed to the stack before it is called. I have virtual memory enabled and when I set up an invalid stack pointer (esp) and the int14 handler gets called it immediately causes another page fault and so on and so on. How should I resolve this situation?
My int14 code:
isr14:
; interrupt handler for isr14
jmp $
iretd
The code that causes it to break:
mov esp, 0x1000 ; 0x1000 is not mapped in the VM directory
push dword 'A'
jmp $
Section of my IDT table:
irq14:
dw isr14
dw 0x0008
db 0x00
db 10101110b
dw 0x0000
irq15:
........
Upvotes: 1
Views: 616
Reputation: 37222
How should I resolve this situation?
I'd resolve the situation by using avoidance - don't let kernel have a dodgy stack pointer in the first place (and don't let kernel stack be sent to swap space, don't use page fault for "auto-growing kernel stack", etc). Note that CPU will automatically switch to kernel stack if a page fault happens in user-space (at CPL=3) so it doesn't matter if user-space has a dodgy stack pointer.
Alternatives are:
force a kernel stack switch when kernel code (CPL=0) causes a page fault. This can be done using hardware task switch (protected mode) or the IST mechanism (long mode) for the page fault exception handler. This would be the best option for recovery (e.g. makes it easier to figure out what the problem was, fix it, then return).
force a kernel stack switch when kernel code (CPL=0) causes a double fault. This can be done using hardware task switch (protected mode) or the IST mechanism (long mode) for the double fault exception handler. This would be the best option for performance (no added overhead for normal page faults).
Note 1: Be warned that neither hardware task switching/task gates nor IST are re-entrant. For hardware task switching, if a second page fault occurs while you're handling the first page fault you'll get a general protection fault (because the "page fault task" is busy); and for IST, if a second page fault occurs while you're handling the first page fault the second page fault will trash/overwrite the first page fault's stack and make it impossible to recover. In theory, you can mitigate these problems by switching to a different task or different stack as soon as possible, but that's complicated/messy and likely to cause even more problems.
Note 2: You'll probably end up with a combination of avoidance and double fault using hardware task switch or IST; with the double fault handler doing "freeze system and dump info/panic" as a generic fallback for catastrophic kernel failures (that were supposed to be avoided but weren't).
Note 3: If you want to support "auto-growing kernel stacks"; you can use "stack probes" instead - basically, just do dummy read/s (in function epilogues) from "future stack" before using the memory for stack, so that the page fault occurs when there's still enough kernel stack left for the page fault handler.
Upvotes: 6