F00F-buggen
Den här artikeln behöver källhänvisningar för att kunna verifieras. (2020-12) Åtgärda genom att lägga till pålitliga källor (gärna som fotnoter). Uppgifter utan källhänvisning kan ifrågasättas och tas bort utan att det behöver diskuteras på diskussionssidan. |
F00F-buggen är en bugg i första generationens Pentiumprocessorer (P5) från Intel, som gör att processorn låser sig och systemet stannar. Benämningen står för den hexadecimala representationen av den maskinkod som utlöser låsningen.
Introduktion
[redigera | redigera wikitext]Den 8 november 1997 postades ett anonymt inlägg på Usenet:
Date: Sat, 8 Nov 1997 07:36:04 +0100 (MET)
From: Anonymous <nobody@REPLAY.COM>
To: best-of-security@cyber.com.au
Subject: BoS: WARNING: Serious Pentium Bug
There is a SERIOUS bug in all pentium CPUs. The following
code will crash any machine running on a pentium CPU, MMX or no
MMX, any speed, regardless of OS (crash as in instant seize, hard
reboot the only cure):
char x [5] = { 0xf0, 0x0f, 0xc7, 0xc8 };
main ()
{
void (*f)() = x;
f();
}
This require no special permissions to run, it works fine with
average-joe-userspace permissions. I have verified this, it works.
Demand a new CPU from Intel.
Implikationerna var enorma. Buggen innebar att vem som helst som hade tillstånd att exekvera kod på ett system med en Intel Pentium processor enkelt kunde låsa hela systemet. För ett nätverk med sådana system kunde det innebära att hela nätverket slutade fungera.
Teori
[redigera | redigera wikitext]När en av Intels mikroprocessorer av typ 80186 och nyare försöker utföra en ogiltig kod kommer ett undantag (kallat #UD) att signaleras. Detta undantag kommer normalt att avsluta det körande programmet.
Den hexadecimala kodningen av instruktionen som givit sitt namn åt buggen, F0 0F C7 C8 (egentligen F0 0F C7 C8 upp till F0 0F C7 CF), motsvarar maskininstruktionen LOCK CMPXCHG8B EAX. CMPXCHG8B jämför innehållet i en 64-bitars minnesadress med innehållet i registren EDX och EAX. En av operanderna måste peka på en minnesadress och den andra operanden är EDX:EAX. Det är möjligt att skapa en instruktionskodning som inte pekar på en minnesadress. Eftersom detta är en ogiltig instruktion kommer denna kod inte att genereras av en kompilator eller assembler. Programmeraren måste istället skapa den för hand.
En sådan kodning borde signalera #UD-undantaget, och instruktionen CMPXCHG8B EAX gör mycket riktigt det. Om den ogiltiga koden inleds med prefixet LOCK kommer emellertid processorn att sluta fungera. LOCK-prefixet är i sig självt ogiltigt tillsammans med CMPXCHG8B och får endast användas vid läs-, ändrings- och skrivoperationer på minne. Eftersom CMPXCHG8B bearbetar register, inte minne, bör alltså ett #UD-undantag signaleras när den används tillsammans med LOCK vilket dock inte görs.
Hur buggen framkallas
[redigera | redigera wikitext]När en instruktionskod mellan F0 0F C7 C8 och F0 0F C7 CF körs, kommer processorn att signalera ett #UD-undantag. Processorn försöker läsa vektoradressen till #UD-undantaget, men eftersom LOCK-prefixet använts i den föregående instruktionen och kräver en läs/ändra/skriv-sekvens kommer bussen att vara låst för de två följande minnesläsningarna (som krävs för att hämta adressen för #UD-undantagets vektoradress). Inga avslutande låsta skrivningar inträffar och processorn låses.