-----BEGIN PGP SIGNED MESSAGE----- =============================================================================== Security Advisory CERT-NL =============================================================================== Author/Source : Rene Ritzen Index : S-97-88 Distribution : World Page : 1 Classification: External Version: 1 Subject : FreeBSD Inc. vendor initiated bulletin Date : 12-Dec-97 =============================================================================== By courtesy of FreeBSD Inc. CERT-NL received information on Pentium processors having a flaw which allow unpriviledged crashes. CERT-NL recommends to implement the solution outlined in section V of this document. ============================================================================= 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-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. ============================================================================= CERT-NL is the Computer Emergency Response Team for SURFnet customers. SURFnet is the Dutch network for educational, research and related institutes. CERT-NL is a member of the Forum of Incident Response and Security Teams (FIRST). All CERT-NL material is available under: http://www.surfnet.nl/surfnet/security/cert-nl.html ftp://ftp.surfnet.nl/surfnet/net-security In case of computer or network security problems please contact your local CERT/security-team or CERT-NL (if your institute is NOT a SURFnet customer please address the appropriate (local) CERT/security-team). CERT-NL is one/two hour(s) ahead of UTC (GMT) in winter/summer, i.e. UTC+0100 in winter and UTC+0200 in summer (DST). Email: cert-nl@surfnet.nl ATTENDED REGULARLY ALL DAYS Phone: +31 302 305 305 BUSINESS HOURS ONLY Fax: +31 302 305 329 BUSINESS HOURS ONLY Snailmail: The NetherlandsTRECHT NOODGEVALLEN: 06 52 87 92 82 ALTIJD BEREIKBAAR EMERGENCIES : +31 6 52 87 92 82 ATTENDED AT ALL TIMES CERT-NL'S EMERGENCY PHONENUMBER IS ONLY TO BE USED IN CASE OF EMERGENCIES: THE SURFNET HELPDESK OPERATING THE EMERGENCY NUMBER HAS A *FIXED* PROCEDURE FOR DEALING WITH YOUR ALERT AND WILL IN REGULAR CASES RELAY IT TO CERT-NL IN AN APPROPRIATE MANNER. CERT-NL WILL THEN CONTACT YOU. ============================================================================== -----BEGIN PGP SIGNATURE----- Version: 2.6.2i iQCVAwUBNJEdoUU5nQkWIq1FAQEM6QP/RcGEnulf0cSrn+Y5wsy5eTZJKlclWUkg QqcnY6bF5ypI8RKrJuVAfLdGJCWDmb27YuLnH6GJkHDHUsANpOEbHRVT0gdAmwSP 7t7M8oXxiXDJePFGBVNOq/7bY06Tio3i4NZMUEVU2zlCI3I0eBzegH7B0yNR+EHp 3AVbqD+oOgw= =ZYHK -----END PGP SIGNATURE-----