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

Luoqi Chen lchen at briontech.com
Mon Dec 8 11:34:57 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.

> FreeBSD-5.x has already moved this check to outside the nesting 
> level test.
> It may also be possible that %fs can cause the same problem to occur in
> 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.
>     if (intr_nesting_level == 0) {
> 	    /*
> 	     * Invalid %fs's and %gs's can be created using
> 	     * procfs or PT_SETREGS or by invalidating the
> 	     * underlying LDT entry.  This causes a fault
> 	     * in kernel mode when the kernel attempts to
> 	     * switch contexts.  Lose the bad context
> 	     * (XXX) so that we can continue, and generate
> 	     * a signal.
> 	     */
> 	    if (frame.tf_eip == (int)cpu_switch_load_gs) {   	<<< WRONG
> 		    curpcb->pcb_gs = 0;   			<<<
> 		    psignal(p, SIGBUS);				<<<
> 		    return;					<<<
> 	    }
> 	    MAYBE_DORETI_FAULT(doreti_iret,
> 			       doreti_iret_fault);


More information about the freebsd-stable mailing list