Bug in i386/i386/trap.c %gs handling on stable

Matthew Dillon dillon at apollo.backplane.com
Tue Dec 9 10:55:38 PST 2003

:> In i386/i386/trap.c if %gs is invalid... for example, a process with a 
:> USER_LDT takes an interrupt while exiting, or if %gs is set 
:> through procfs,
:> the fault check must occur regardless of the interrupt nesting 
:> level because
:> mainline code does not push and load a %gs for the kernel. 
:I don't quite get it. There'll be fault only when the kernel tries to
:load an invalid %gs. And there's only one place that the kernel would
:load a new %gs: during a context switch, which could not take place in
:an interrupt context.

    Hmm.  I think you are right.  In FreeBSD-5 a context can occur at any
    time which presumably is why the %gs test was moved to outside the
    interrupt nesting level check.

    In FreeBSD-4 a context switch will only occur outside of an interrupt
    so I guess it can't happen.  Well, that isn't entirely true... a 
    context switch has been known to happen inside interrupts in 4.x
    but those are considered to be bugs :-).

    In DragonFly an interrupt preemption causes a context switch, then
    another switch back after the interrupt code finishes or blocks, which
    is why the problem occured in DFly.

:> the situation with a process takes an interrupt while exiting and %fs is
:> set to a USER_LDT entry.  I have not checked this, but if it is 
:> true it would
:> be a problem in both -current and -stable for the exiting case.
:It's different for %fs, it holds a valid kernel segment at all time
:inside the kernel.

    Hmm.  But it still must save and restore %fs.   If a user program
    sets up a user LDT, loads %fs with a valid value, and then deletes the
    user LDT, %fs will be bad.

    The only thing that saves us in 4.x is the fact that the interrupt
    nesting level will be 0 when the first interrupt restores %fs.  That is,
    it will have already decremented intr_nesting_level.  It will take
    the fault but properly deal with the consequences, and a nested interrupt
    will be saving and restoring the kernel %fs that the first interrupt
    loaded up.

    In 5.x it looks a lot more fragile but I guess the same thing applies,
    just barely.

					Matthew Dillon 
					<dillon at backplane.com>

More information about the freebsd-stable mailing list