Date: Tue, 9 Dec 2003 10:55:27 -0800 (PST) From: Matthew Dillon <dillon@apollo.backplane.com> To: "Luoqi Chen" <lchen@briontech.com> Cc: stable@freebsd.org Subject: RE: Bug in i386/i386/trap.c %gs handling on stable Message-ID: <200312091855.hB9ItR6C074504@apollo.backplane.com> References: <AHEKICEOIHLOGINAFIINCEGMCBAA.lchen@briontech.com>
next in thread | previous in thread | raw e-mail | index | archive | help
: :> 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. :.. :-lq 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. -Matt Matthew Dillon <dillon@backplane.com>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200312091855.hB9ItR6C074504>