From nobody@FreeBSD.org  Wed Apr  3 16:20:53 2002
Return-Path: <nobody@FreeBSD.org>
Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21])
	by hub.freebsd.org (Postfix) with ESMTP id 1178337B405
	for <freebsd-gnats-submit@FreeBSD.org>; Wed,  3 Apr 2002 16:20:53 -0800 (PST)
Received: (from nobody@localhost)
	by freefall.freebsd.org (8.11.6/8.11.6) id g340Krh31684;
	Wed, 3 Apr 2002 16:20:53 -0800 (PST)
	(envelope-from nobody)
Message-Id: <200204040020.g340Krh31684@freefall.freebsd.org>
Date: Wed, 3 Apr 2002 16:20:53 -0800 (PST)
From: David Xu <davidx@viasoft.com.cn>
To: freebsd-gnats-submit@FreeBSD.org
Subject: possible privilege level check bug in /sys/i386/isa/ipl.s
X-Send-Pr-Version: www-1.0

>Number:         36710
>Category:       i386
>Synopsis:       possible privilege level check bug in /sys/i386/isa/ipl.s
>Confidential:   no
>Severity:       critical
>Priority:       low
>Responsible:    bde
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Apr 03 16:30:00 PST 2002
>Closed-Date:    Thu May 16 09:12:31 PDT 2002
>Last-Modified:  Thu May 16 09:12:31 PDT 2002
>Originator:     David Xu
>Release:        FreeBSD 4.4-stable
>Organization:
Viatech
>Environment:
gulala
>Description:
in file /sys/i386/isa/ipl.s, when system checks if code selector on trap frame is coming from USER level or V86 mode, it first check if it is coming from USER level, this is wrong, it should first check if it is coming from V86 mode, because V86 mode code selector hasn't any privilege level information, checking its privilege level in selector has random value. I have the patch for this bug.
>How-To-Repeat:
      
>Fix:
--- ipl.s.orig	Thu Apr  4 07:37:13 2002
+++ ipl.s	Thu Apr  4 07:57:46 2002
@@ -128,12 +128,14 @@
 	/* Check for ASTs that can be handled now. */
 	testl	$AST_PENDING,_astpending
 	je	doreti_exit
-	testb	$SEL_RPL_MASK,TF_CS(%esp)
-	jne	doreti_ast
 	testl	$PSL_VM,TF_EFLAGS(%esp)
-	je	doreti_exit
+	jz	doreti_UPL
 	cmpl	$1,_in_vm86call
 	jne	doreti_ast
+	jmp	doreti_exit	
+doreti_UPL:
+	testb	$SEL_RPL_MASK,TF_CS(%esp)
+	jnz	doreti_ast
 
 	/*
 	 * doreti_exit -	release MP lock, pop registers, iret.

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->bde 
Responsible-Changed-By: bde 
Responsible-Changed-When: Sat Apr 27 07:46:30 PDT 2002 
Responsible-Changed-Why:  
I will handle this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=36710 

From: Bruce Evans <bde@zeta.org.au>
To: David Xu <davidx@viasoft.com.cn>
Cc: freebsd-gnats-submit@FreeBSD.ORG
Subject: Re: i386/36710: possible privilege level check bug in /sys/i386/isa/ipl.s
Date: Sun, 28 Apr 2002 04:18:27 +1000 (EST)

 On Wed, 3 Apr 2002, David Xu wrote:
 
 > >Description:
 > in file /sys/i386/isa/ipl.s, when system checks if code selector on trap frame is coming from USER level or V86 mode, it first check if it is coming from USER level, this is wrong, it should first check if it is coming from V86 mode, because V86 mode code selector hasn't any privilege level information, checking its privilege level in selector has random value. I have the patch for this bug.
 
 Please use lines of length significantly less than 394 characters %-).
 
 > >How-To-Repeat:
 >
 > >Fix:
 > --- ipl.s.orig	Thu Apr  4 07:37:13 2002
 > +++ ipl.s	Thu Apr  4 07:57:46 2002
 > @@ -128,12 +128,14 @@
 >  	/* Check for ASTs that can be handled now. */
 >  	testl	$AST_PENDING,_astpending
 >  	je	doreti_exit
 > -	testb	$SEL_RPL_MASK,TF_CS(%esp)
 > -	jne	doreti_ast
 >  	testl	$PSL_VM,TF_EFLAGS(%esp)
 > -	je	doreti_exit
 > +	jz	doreti_UPL
 >  	cmpl	$1,_in_vm86call
 >  	jne	doreti_ast
 > +	jmp	doreti_exit
 > +doreti_UPL:
 > +	testb	$SEL_RPL_MASK,TF_CS(%esp)
 > +	jnz	doreti_ast
 >
 >  	/*
 >  	 * doreti_exit -	release MP lock, pop registers, iret.
 >
 
 I broke this in rev.1.30 :(
 
 This doesn't seem to have any direct consequences for security.  We
 just misclassify vm86 calls from the kernel as being from userland if
 their %cs is nonzero mod 3.  Then we sometimes do AST handling when
 not about to return to user mode.  The AST handling tends to be fatal
 if and only if it switches contexts (because the process is in a strange
 mode with %cr3 and other things switched in an usual way so that normal
 switching doesn't restore it).
 
 We also misclassify vm86 calls in trap().  Everywhere that checks
 SEL_UPL or invokes TRAPF_USERMODE() is suspect.
 
 Preemptive context switches in -current may also cause problems.  There
 is only accidental locking to prevent context switches (sched_lock is
 strictly required, but Giant was held (from the syscall) and was
 probably sufficient in my test case (kldload of vesa module)).
 
 These bugs seem to be limited in practice only by:
 - we start and finish our kernel vm86 calls with %cs == 0.  Thus we
   don't misclassify them for the initial doreti when starting them or
   the final trap() when finishing them.
 - BIOSes either use %cs's which are 0 mod 3, or don't trap (otherwise
   the misclassification in trap() would cause problems) and don't
   reenable interrupts (otherwise the misclassification in doreti would
   cause problems and the non-classification for preemptive context
   switching would cause problems).
 
 There also seems to a problem with the in_vm86call variable.  It needs
 to be per-CPU, or processes on other CPUs must not go near trap() or
 the context switcher while one CPU is in a vm86 call.  Misclassification
 from in_vm86call being set is relatively harmless in doreti -- it just
 causes AST processing to be delayed, but misclassification from this in
 is harmful in trap().  I think spinlocking of trap() prevents problems
 there except in -current.
 
 Bruce
 

From: "David Xu" <davidx@viasoft.com.cn>
To: "Bruce Evans" <bde@zeta.org.au>
Cc: <freebsd-gnats-submit@FreeBSD.ORG>
Subject: Re: i386/36710: possible privilege level check bug in /sys/i386/isa/ipl.s
Date: Sun, 28 Apr 2002 09:42:33 +0800

 ----- Original Message -----=20
 From: "Bruce Evans" <bde@zeta.org.au>
 To: "David Xu" <davidx@viasoft.com.cn>
 Cc: <freebsd-gnats-submit@FreeBSD.ORG>
 Sent: Sunday, April 28, 2002 2:18 AM
 Subject: Re: i386/36710: possible privilege level check bug in =
 /sys/i386/isa/ipl.s
 
 
 > On Wed, 3 Apr 2002, David Xu wrote:
 >=20
 > > >Description:
 > > in file /sys/i386/isa/ipl.s, when system checks if code selector on =
 trap frame is coming from USER level or V86 mode, it first check if it =
 is coming from USER level, this is wrong, it should first check if it is =
 coming from V86 mode, because V86 mode code selector hasn't any =
 privilege level information, checking its privilege level in selector =
 has random value. I have the patch for this bug.
 >=20
 > Please use lines of length significantly less than 394 characters %-).
 >=20
 
 Sorry,  I have used www.freebsd.org's web page to post this PR,  my =
 brain
 must  be damaged!  my browser does not auto insert a '\n' in  posted =
 data=20
 although it seems it auto wraps long line in edit box!
 
 
 > > >How-To-Repeat:
 > >
 > > >Fix:
 > > --- ipl.s.orig Thu Apr  4 07:37:13 2002
 > > +++ ipl.s Thu Apr  4 07:57:46 2002
 > > @@ -128,12 +128,14 @@
 > >  /* Check for ASTs that can be handled now. */
 > >  testl $AST_PENDING,_astpending
 > >  je doreti_exit
 > > - testb $SEL_RPL_MASK,TF_CS(%esp)
 > > - jne doreti_ast
 > >  testl $PSL_VM,TF_EFLAGS(%esp)
 > > - je doreti_exit
 > > + jz doreti_UPL
 > >  cmpl $1,_in_vm86call
 > >  jne doreti_ast
 > > + jmp doreti_exit
 > > +doreti_UPL:
 > > + testb $SEL_RPL_MASK,TF_CS(%esp)
 > > + jnz doreti_ast
 > >
 > >  /*
 > >  * doreti_exit - release MP lock, pop registers, iret.
 > >
 >=20
 > I broke this in rev.1.30 :(
 >=20
 > This doesn't seem to have any direct consequences for security.  We
 > just misclassify vm86 calls from the kernel as being from userland if
 > their %cs is nonzero mod 3.  Then we sometimes do AST handling when
 > not about to return to user mode.  The AST handling tends to be fatal
 > if and only if it switches contexts (because the process is in a =
 strange
 > mode with %cr3 and other things switched in an usual way so that =
 normal
 > switching doesn't restore it).
 >=20
 > We also misclassify vm86 calls in trap().  Everywhere that checks
 > SEL_UPL or invokes TRAPF_USERMODE() is suspect.
 >=20
 
 Just after posted this PR,  I found this bug! sorry,  I forgot to post =
 another=20
 PR  to point out that the bug is also in trap.c, brain damaged again :(
 
 > Preemptive context switches in -current may also cause problems.  =
 There
 > is only accidental locking to prevent context switches (sched_lock is
 > strictly required, but Giant was held (from the syscall) and was
 > probably sufficient in my test case (kldload of vesa module)).
 >=20
 > These bugs seem to be limited in practice only by:
 > - we start and finish our kernel vm86 calls with %cs =3D=3D 0.  Thus =
 we
 >   don't misclassify them for the initial doreti when starting them or
 >   the final trap() when finishing them.
 > - BIOSes either use %cs's which are 0 mod 3, or don't trap (otherwise
 >   the misclassification in trap() would cause problems) and don't
 >   reenable interrupts (otherwise the misclassification in doreti would
 >   cause problems and the non-classification for preemptive context
 >   switching would cause problems).
 >=20
 > There also seems to a problem with the in_vm86call variable.  It needs
 > to be per-CPU, or processes on other CPUs must not go near trap() or
 > the context switcher while one CPU is in a vm86 call.  =
 Misclassification
 > from in_vm86call being set is relatively harmless in doreti -- it just
 > causes AST processing to be delayed, but misclassification from this =
 in
 > is harmful in trap().  I think spinlocking of trap() prevents problems
 > there except in -current.
 >=20
 > Bruce
 
 use per-cpu in_vm86call is right,  but BIOS maybe not reentrancable, so=20
 use a mutex to protect it is needed before calling BIOS service, may not
 spinlock trap().
 
 David
 
 

From: "David Xu" <davidxu@viatech.com.cn>
To: "Bruce Evans" <bde@zeta.org.au>
Cc: <freebsd-gnats-submit@FreeBSD.ORG>
Subject: Re: i386/36710: possible privilege level check bug in /sys/i386/isa/ipl.s
Date: Sun, 28 Apr 2002 09:50:01 +0800

 ----- Original Message -----=20
 From: "Bruce Evans" <bde@zeta.org.au>
 To: "David Xu" <davidx@viasoft.com.cn>
 Cc: <freebsd-gnats-submit@FreeBSD.ORG>
 Sent: Sunday, April 28, 2002 2:18 AM
 Subject: Re: i386/36710: possible privilege level check bug in =
 /sys/i386/isa/ipl.s
 
 
 > On Wed, 3 Apr 2002, David Xu wrote:
 >=20
 > > >Description:
 > > in file /sys/i386/isa/ipl.s, when system checks if code selector on =
 trap frame is coming from USER level or V86 mode, it first check if it =
 is coming from USER level, this is wrong, it should first check if it is =
 coming from V86 mode, because V86 mode code selector hasn't any =
 privilege level information, checking its privilege level in selector =
 has random value. I have the patch for this bug.
 >=20
 > Please use lines of length significantly less than 394 characters %-).
 >=20
 
 Sorry,  I have used www.freebsd.org's web page to post this PR,  my =
 brain
 must  be damaged!  my browser does not auto insert a '\n' in  posted =
 data=20
 although it seems it auto wraps long line in edit box!
 
 
 > > >How-To-Repeat:
 > >
 > > >Fix:
 > > --- ipl.s.orig Thu Apr  4 07:37:13 2002
 > > +++ ipl.s Thu Apr  4 07:57:46 2002
 > > @@ -128,12 +128,14 @@
 > >  /* Check for ASTs that can be handled now. */
 > >  testl $AST_PENDING,_astpending
 > >  je doreti_exit
 > > - testb $SEL_RPL_MASK,TF_CS(%esp)
 > > - jne doreti_ast
 > >  testl $PSL_VM,TF_EFLAGS(%esp)
 > > - je doreti_exit
 > > + jz doreti_UPL
 > >  cmpl $1,_in_vm86call
 > >  jne doreti_ast
 > > + jmp doreti_exit
 > > +doreti_UPL:
 > > + testb $SEL_RPL_MASK,TF_CS(%esp)
 > > + jnz doreti_ast
 > >
 > >  /*
 > >  * doreti_exit - release MP lock, pop registers, iret.
 > >
 >=20
 > I broke this in rev.1.30 :(
 >=20
 > This doesn't seem to have any direct consequences for security.  We
 > just misclassify vm86 calls from the kernel as being from userland if
 > their %cs is nonzero mod 3.  Then we sometimes do AST handling when
 > not about to return to user mode.  The AST handling tends to be fatal
 > if and only if it switches contexts (because the process is in a =
 strange
 > mode with %cr3 and other things switched in an usual way so that =
 normal
 > switching doesn't restore it).
 >=20
 > We also misclassify vm86 calls in trap().  Everywhere that checks
 > SEL_UPL or invokes TRAPF_USERMODE() is suspect.
 >=20
 
 Just after posted this PR,  I found this bug! sorry,  I forgot to post =
 another=20
 PR  to point out that the bug is also in trap.c, brain damaged again :(
 
 > Preemptive context switches in -current may also cause problems.  =
 There
 > is only accidental locking to prevent context switches (sched_lock is
 > strictly required, but Giant was held (from the syscall) and was
 > probably sufficient in my test case (kldload of vesa module)).
 >=20
 > These bugs seem to be limited in practice only by:
 > - we start and finish our kernel vm86 calls with %cs =3D=3D 0.  Thus =
 we
 >   don't misclassify them for the initial doreti when starting them or
 >   the final trap() when finishing them.
 > - BIOSes either use %cs's which are 0 mod 3, or don't trap (otherwise
 >   the misclassification in trap() would cause problems) and don't
 >   reenable interrupts (otherwise the misclassification in doreti would
 >   cause problems and the non-classification for preemptive context
 >   switching would cause problems).
 >=20
 > There also seems to a problem with the in_vm86call variable.  It needs
 > to be per-CPU, or processes on other CPUs must not go near trap() or
 > the context switcher while one CPU is in a vm86 call.  =
 Misclassification
 > from in_vm86call being set is relatively harmless in doreti -- it just
 > causes AST processing to be delayed, but misclassification from this =
 in
 > is harmful in trap().  I think spinlocking of trap() prevents problems
 > there except in -current.
 >=20
 > Bruce
 
 use per-cpu in_vm86call is right,  but BIOS maybe not reentrancable, so=20
 use a mutex to protect it is needed before calling BIOS service, may not
 spinlock trap().
 
 David
 
 
 
State-Changed-From-To: open->closed 
State-Changed-By: bde 
State-Changed-When: Thu May 16 09:05:43 PDT 2002 
State-Changed-Why:  
Primary bug fixed in rev.1.54 of -current and 1.32.2.3 of RELENG_4. 
I think the fix is not needed in RELENG_4_5 or RELENG_4_4.  Bug not 
in RELENG_3.  I think secondary bugs are covered by subsequent PRs. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=36710 
>Unformatted:
