FreeBSD Security Advisory: FreeBSD-SA-97:06.f00f

From: Aleph One (aleph1at_private)
Date: Tue Dec 09 1997 - 13:21:49 PST

  • Next message: Security Alert: "Re: HPUX rexecd bug on trusted system"

    -----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\n");
         +
         +  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-officerat_private
    PGP Key:                        ftp://freebsd.org/pub/CERT/public_key.asc
    Security notifications:         security-notificationsat_private
    Security public discussion:     securityat_private
    
    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-----
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:35:09 PDT