Port-i386 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kernel faults on iret



The i386 kernel can fault on the 'iret' instruction during return
to userspace (it can also fault in userspace slightly later,
but that isn't relevant here).

When this happens the kernel stack contains (deepest at the top):
        user -> kernel trap frame (user stack ptr and pc)
        kernel trap frame (for the fault) (pc of iret)
        registers saved by kernel (these are the user registers)
        call into trap() and its locals

Note that unlike a fault loading any of the segment registers, the
saved registers from the original user -> kernel trap are no
longer on the stack. The current code (lines 410+ of i386/trap.c)
incorrectly treats these two different faults the same way - which
is all wrong.

I've tried to fix things, but it is all rather complex!
My fix is in 3 parts:
1) do not reset tf_ds/es/gs/fs/eip/eflags
2) copy the saved registers down 12 bytes overwriting the
   kernel trap frame
3) call (jump) directly back into vector.S so that the %esp
   can be reset to the start of the saved registers and then
   restored as usual.

The intended effect is to make it look like a trap from user
mode when we start restoring the registers.
Part of the reason for deleting the middle of the stack (rather
than just letting the two iret instructions execute is a worry
about how the signal handler might try to modify the registers.

Unfortunately it isn't working the way I expect!
In ddb I can't get any breakpoints triggered after the call
to trapsignal - which should queue the sigsegv.

Possibly this is all borked because the 'iret' is failing because
the stack isn't executable (or rather because the segment limit
for %cs excludes the stack).

Or am I missing something about the contents of the kernel
stack during signal delivery?

        David

-- 
David Laight: david%l8s.co.uk@localhost


Home | Main Index | Thread Index | Old Index