Australia's Leading Computer Emergency Response Team

ESB-97.159 -- FreeBSD Security Advisory: FreeBSD-SA-97:06 -- Pentium processors have flaw allowing unpriviledged crashes
Date: 10 December 1997
Original URL: http://www.auscert.org.au/render.html?cid=1&it=296

Click here for PGP verifiable version
-----BEGIN PGP SIGNED MESSAGE-----


===========================================================================
              AUSCERT External Security Bulletin Redistribution

                             
           ESB-97.159 -- FreeBSD Security Advisory: FreeBSD-SA-97:06
          Pentium processors have flaw allowing unpriviledged crashes

                              10 December 1997

===========================================================================

FreeBSD, Inc has released the following advisory concerning a flaw in
Intel Pentium processors which affects their systems.  This problem may
allow unprivileged users to lock up the processor, which requires a hard
reset to correct.

The following security bulletin is provided as a service to AUSCERT's
members.  As AUSCERT did not write this document, AUSCERT has had no
control over its content.  As such, the decision to use any or all of this
information is the responsibility of each user or organisation, and should
be done so in accordance with site policies and procedures.

NOTE: This is only the original release of the security bulletin.  It will
not be updated when the original bulletin is.  If downloading at a later
date, it is recommended that the bulletin is retrieved from the original
authors to ensure that the information is still current.

Contact information for FreeBSD is included in the Security Bulletin
below.  If you have any questions or need further information, please
contact them directly. 

Previous advisories and external security bulletins can be retrieved from:

        http://www.auscert.org.au/information/advisories.html

If you believe that your system has been compromised, contact AUSCERT or your
representative in FIRST (Forum of Incident Response and Security Teams).

Internet Email: auscert@auscert.org.au
Telephone:      (07) 3365 4417 (International: +61 7 3365 4417)
                AUSCERT personnel answer during Queensland business hours
                which are GMT+10:00 (AEST).
                On call after hours for emergencies.
Facsimile:      (07) 3365 7031


- --------------------------BEGIN INCLUDED TEXT--------------------

- -----BEGIN PGP SIGNED MESSAGE-----

=============================================================================
FreeBSD-SA-97:06                                            Security Advisory
                                                                FreeBSD, Inc.
     
Topic:          Pentium processors have flaw allowing unpriviledged crashes

Category:       core
Module:         kern
Announced:      1997-12-09
Affects:        FreeBSD 2.1.*, FreeBSD 2.2.*,
		FreeBSD-stable and FreeBSD-current 
Corrected:      FreeBSD-current as of 1997-12-04
		FreeBSD-stable as of 1997-12-04
FreeBSD only:   no

Patches:        ftp://freebsd.org/pub/CERT/patches/SA-97:06/

=============================================================================

I.   Background

     Intel processors have instruction combiniations that, when
     executed, produce illegal instruction traps.  This is a normal
     part of every cpu manufactured and is how new instructions are
     generally emulated on older hardware.

II.  Problem Description

     A specific sequence of instructions, starting with the byte codes
     F0 0F (hex) cause Pentium processors to lock up.  This lockup
     wedges the entire system, requiring a hard reset to correct.
     Systems that allow users to run arbitrary code are vulnerable to
     this attack.

III. Impact

     An unpriviledged user can crash your system.
     
IV.  Workaround

     None is available.

V.   Solution

     The following patch corrects the problem for FreeBSD-current
     systems before 1997-12-04, for FreeBSD 2.2-stable before
     1997-12-04 and for FreeBSD 2.2.5.

     We urge users of FreeBSD 2.1.* to upgrade to the more stable and
     more powerfull FreeBSD 2.2.5 release.


     Index: identcpu.c
     ===================================================================
     RCS file: /home/cvsup/freebsd/CVS/src/sys/i386/i386/identcpu.c,v
     retrieving revision 1.33
     retrieving revision 1.35
     diff -u -r1.33 -r1.35
     --- identcpu.c	1997/11/07 08:52:27	1.33
     +++ identcpu.c	1997/12/04 14:35:38	1.35
     @@ -107,6 +107,10 @@
      	);
      }
      
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +int has_f00f_bug = 0;
     +#endif
     +
      void
      printcpuinfo(void)
      {
     @@ -136,6 +140,14 @@
      				break;
      			case 0x500:
      				strcat(cpu_model, "Pentium"); /* nb no space */
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +				/*
     +				 * XXX - If/when Intel fixes the bug, this
     +				 * should also check the version of the
     +				 * CPU, not just that it's a Pentium.
     +				 */
     +				has_f00f_bug = 1;
     +#endif
      				break;
      			case 0x600:
      				strcat(cpu_model, "Pentium Pro");
     Index: machdep.c
     ===================================================================
     RCS file: /home/cvsup/freebsd/CVS/src/sys/i386/i386/machdep.c,v
     retrieving revision 1.274
     retrieving revision 1.278
     diff -u -r1.274 -r1.278
     --- machdep.c	1997/11/24 18:35:11	1.274
     +++ machdep.c	1997/12/04 21:21:24	1.278
     @@ -866,6 +867,11 @@
      #endif /* VM86 */
      #endif
      
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +struct gate_descriptor *t_idt;
     +extern int has_f00f_bug;
     +#endif
     +
      static struct i386tss dblfault_tss;
      static char dblfault_stack[PAGE_SIZE];
      
     @@ -1533,6 +1539,40 @@
      	proc0.p_addr->u_pcb.pcb_mpnest = 1;
      	proc0.p_addr->u_pcb.pcb_ext = 0;
      }
     +
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +void f00f_hack(void);
     +SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL);
     +
     +void
     +f00f_hack(void) {
     +	struct region_descriptor r_idt;
     +	unsigned char *tmp;
     +	int i;
     +
     +	if (!has_f00f_bug)
     +		return;
     +
     +	printf("Intel Pentium F00F detected, installing workaround
");
     +
     +	r_idt.rd_limit = sizeof(idt) - 1;
     +
     +	tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2);
     +	if (tmp == 0)
     +		panic("kmem_alloc returned 0");
     +	if (((unsigned int)tmp & (PAGE_SIZE-1)) != 0)
     +		panic("kmem_alloc returned non-page-aligned memory");
     +	/* Put the first seven entries in the lower page */
     +	t_idt = (struct gate_descriptor*)(tmp + PAGE_SIZE - (7*8));
     +	bcopy(idt, t_idt, sizeof(idt));
     +	r_idt.rd_base = (int)t_idt;
     +	lidt(&r_idt);
     +	if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE,
     +			   VM_PROT_READ, FALSE) != KERN_SUCCESS)
     +		panic("vm_map_protect failed");
     +	return;
     +}
     +#endif /* defined(I586_CPU) && !NO_F00F_HACK */
      
      int
      ptrace_set_pc(p, addr)
     Index: trap.c
     ===================================================================
     RCS file: /home/cvsup/freebsd/CVS/src/sys/i386/i386/trap.c,v
     retrieving revision 1.115
     retrieving revision 1.118
     diff -u -r1.115 -r1.118
     --- trap.c	1997/11/24 13:25:37	1.115
     +++ trap.c	1997/12/04 21:21:26	1.118
     @@ -142,6 +143,11 @@
      static void userret __P((struct proc *p, struct trapframe *frame,
      			 u_quad_t oticks));
      
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +extern struct gate_descriptor *t_idt;
     +extern int has_f00f_bug;
     +#endif
     +
      static inline void
      userret(p, frame, oticks)
      	struct proc *p;
     @@ -211,6 +217,9 @@
      	u_long eva;
      #endif
      
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +restart:
     +#endif
      	type = frame.tf_trapno;
      	code = frame.tf_err;
      
     @@ -276,6 +285,10 @@
      			i = trap_pfault(&frame, TRUE);
      			if (i == -1)
      				return;
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +			if (i == -2)
     +				goto restart;
     +#endif
      			if (i == 0)
      				goto out;
      
     @@ -642,7 +655,18 @@
      	if (va >= KERNBASE) {
      		/*
      		 * Don't allow user-mode faults in kernel address space.
     +		 * An exception:  if the faulting address is the invalid
     +		 * instruction entry in the IDT, then the Intel Pentium
     +		 * F00F bug workaround was triggered, and we need to
     +		 * treat it is as an illegal instruction, and not a page
     +		 * fault.
      		 */
     +#if defined(I586_CPU) && !defined(NO_F00F_HACK)
     +		if ((eva == (unsigned int)&t_idt[6]) && has_f00f_bug) {
     +			frame->tf_trapno = T_PRIVINFLT;
     +			return -2;
     +		}
     +#endif
      		if (usermode)
      			goto nogo;
      
     
=============================================================================
FreeBSD, Inc.

Web Site:                       http://www.freebsd.org/
Confidential contacts:          security-officer@freebsd.org
PGP Key:                        ftp://freebsd.org/pub/CERT/public_key.asc
Security notifications:         security-notifications@freebsd.org
Security public discussion:     security@freebsd.org

Notice: Any patches in this document may not apply cleanly due to
        modifications caused by digital signature or mailer software.
        Please reference the URL listed at the top of this document
        for original copies of all patches if necessary.
=============================================================================

- -----BEGIN PGP SIGNATURE-----
Version: 2.6.2

iQCVAwUBNI2g9VUuHi5z0oilAQGFnAP/R4bArrM7+NZKbrJEK+9UpNYBPhsakAF6
4/U1wJJdbBJPl5j4udZki8ZUEPJvM2mSnrs9UevQMYGSoirl92h/0SEgVgjIfhcJ
tcyY97Js6biHAZzib4i/TKoN47wBNjgRLF6SfafuIxfVQYk6RMFB5EUdYBdseVz/
5RgYqQz4m/k=
=xvTs
- -----END PGP SIGNATURE-----


- --------------------------END INCLUDED TEXT--------------------

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3i
Charset: noconv
Comment: ftp://ftp.auscert.org.au/pub/auscert/AUSCERT_PGP.key

iQCVAwUBNI6+nSh9+71yA2DNAQEbCgP+ImkYZFcz6LB+pplEhD7iKxcfLiuqlfZz
YueTON6HlY6ROBOivm4JxEHGAuR5cJbr1Kc3ORMLns14KTfZYsog3xfJXXpH5qXM
ONQoFRyTtodNRwn72dyHZVknYJ6g/LVuyC5C9/um982aN3EtGUgcoUK7DIgLxpol
sa1TP3h1Tlw=
=ZkEr
-----END PGP SIGNATURE-----