Meltdown Och Spectre, förklarade

Även om jag idag är mest känd för nätverk på applikationsnivå och distribuerade system, tillbringade jag den första delen av min karriär på operativsystem och hypervisorer. Jag upprätthåller en djup fascination med de låga detaljerna om hur moderna processorer och systemprogramvara fungerar. När den senaste tidens härdsmälta och Spectre sårbarheter tillkännagavs, jag grävde i den tillgängliga informationen och var angelägna om att lära sig mer.

sårbarheterna är häpnadsväckande; Jag skulle hävda att de är en av de viktigaste upptäckterna inom datavetenskap under de senaste 10-20 åren. Begränsningarna är också svåra att förstå och korrekt information om dem är svår att hitta. Detta är inte förvånande med tanke på deras kritiska natur. Att mildra sårbarheterna har krävt månader av hemligt arbete av alla de stora CPU -, operativsystems-och molnleverantörerna. Det faktum att frågorna hölls under wraps för 6 månader när bokstavligen hundratals människor sannolikt arbetar på dem är fantastiskt.

Även om mycket har skrivits om Meltdown Och Spectre sedan deras tillkännagivande, har jag inte sett en bra mid-level introduktion till sårbarheter och mildringar. I det här inlägget kommer jag att försöka korrigera det genom att ge en mild introduktion till hårdvaru-och mjukvarubakgrunden som krävs för att förstå sårbarheterna, en diskussion om sårbarheterna själva, samt en diskussion om de nuvarande begränsningarna.

viktig anmärkning: eftersom jag inte har arbetat direkt med begränsningarna och inte fungerar på Intel, Microsoft, Google, Amazon, Red Hat, etc. några av de detaljer som jag kommer att ge kanske inte är helt korrekta. Jag har sammanställt det här inlägget baserat på min kunskap om hur dessa system fungerar, offentligt tillgänglig dokumentation och patchar/diskussioner som skickas till LKML och xen-devel. Jag skulle gärna bli korrigerad om något av det här inlägget är felaktigt, men jag tvivlar på att det kommer att hända när som helst snart med tanke på hur mycket av detta ämne fortfarande omfattas av NDA.

i det här avsnittet kommer jag att ge lite bakgrund som krävs för att förstå sårbarheterna. Avsnittet glansar över en stor mängd detaljer och riktar sig till läsare med begränsad förståelse för datormaskinvara och systemprogramvara.

virtuellt minne

virtuellt minne är en teknik som används av alla operativsystem sedan 1970-talet. det ger ett lager av abstraktion mellan minnesadresslayouten som de flesta program ser och de fysiska enheterna som stöder det minnet (RAM, diskar etc.). På en hög nivå tillåter det applikationer att utnyttja mer minne än vad maskinen faktiskt har; detta ger en kraftfull abstraktion som gör många programmeringsuppgifter enklare.

Figur 1: virtuellt minne

figur 1 visar en förenklad dator med 400 byte minne som anges i ”sidor” på 100 byte (riktiga datorer använder två krafter, vanligtvis 4096). Datorn har två processer, var och en med 200 byte minne över 2 sidor vardera. Processerna kan köra samma kod med fasta adresser i 0-199 byte-intervallet, men de stöds av diskret fysiskt minne så att de inte påverkar varandra. Även om moderna operativsystem och datorer använder virtuellt minne på ett väsentligt mer komplicerat sätt än vad som presenteras i detta exempel, gäller den grundläggande förutsättningen som presenteras ovan i alla fall. Operativsystem abstraherar adresserna som applikationen ser från de fysiska resurserna som stöder dem.

att översätta virtuella till fysiska adresser är en så vanlig operation i moderna datorer att om operativsystemet måste vara involverat i alla fall skulle datorn vara otroligt långsam. Modern CPU-hårdvara tillhandahåller en enhet som kallas en Translation Lookaside Buffer (TLB) som cachar nyligen använda mappningar. Detta gör det möjligt för processorer att utföra adressöversättning direkt i hårdvara större delen av tiden.

Figur 2: Virtuellt minne översättning

Figur 2 visar adressöversättningsflödet:

  1. ett program hämtar en virtuell adress.
  2. CPU: n försöker översätta den med TLB. Om adressen hittas används översättningen.
  3. Om adressen inte hittas konsulterar CPU en uppsättning ”sidtabeller” för att bestämma kartläggningen. Sidtabeller är en uppsättning fysiska minnessidor som tillhandahålls av operativsystemet på en plats som hårdvaran kan hitta dem (till exempel CR3-registret på x86-hårdvara). Sidtabeller kartlägger virtuella adresser till fysiska adresser och innehåller även metadata som behörigheter.
  4. Om sidtabellen innehåller en mappning returneras den, cachas i TLB och används för sökning. Om sidtabellen inte innehåller en mappning höjs ett” sidfel ” till operativsystemet. Ett sidfel är en speciell typ av avbrott som gör att operativsystemet kan ta kontroll och bestämma vad man ska göra när det saknas eller ogiltig mappning. Till exempel kan operativsystemet avsluta programmet. Det kan också tilldela lite fysiskt minne och kartlägga det i processen. Om en sidfelhanterare fortsätter exekveringen kommer den nya mappningen att användas av TLB.
Figur 3: User / kernel virtual memory mappings

figur 3 visar en något mer realistisk bild av hur virtuellt minne ser ut i en modern dator (Pre-Meltdown — mer om detta nedan). I den här inställningen har vi följande funktioner:

  • kärnminne visas i rött. Den finns i fysiskt adressintervall 0-99. Kärnminne är speciellt minne som endast operativsystemet ska kunna komma åt. Användarprogram ska inte kunna komma åt det.
  • användarminnet visas i grått.
  • odelat fysiskt minne visas i blått.

i det här exemplet börjar vi se några av de användbara funktionerna i virtuellt minne. Primärt:

  • användarminne i varje process ligger i det virtuella intervallet 0-99, men stöds av olika fysiska minne.
  • kärnminne i varje process ligger i det virtuella intervallet 100-199, men stöds av samma fysiska minne.

som jag kort nämnde i föregående avsnitt har varje sida associerade behörighetsbitar. Även om kärnminnet mappas in i varje användarprocess, när processen körs i användarläge kan den inte komma åt kärnminnet. Om en process försöker göra det kommer det att utlösa ett sidfel vid vilken tidpunkt operativsystemet kommer att avsluta det. Men när processen körs i kärnläge (till exempel under ett systemanrop) tillåter processorn åtkomst.

Vid denna tidpunkt kommer jag att notera att denna typ av dubbelmappning (varje process som har kärnan mappad in i den direkt) har varit standardpraxis i operativsystemdesign i över trettio år av prestandaskäl (systemanrop är mycket vanliga och det skulle ta lång tid att omforma kärnan eller användarutrymmet vid varje övergång).

CPU-cache topologi

figur 4: CPU-tråd, kärna, paket och cache-topologi.

nästa bit av bakgrundsinformation som krävs för att förstå sårbarheterna är CPU och cache topologi av moderna processorer. Figur 4 visar en generisk topologi som är gemensam för de flesta moderna processorer. Den består av följande komponenter:

  • den grundläggande exekveringsenheten är ”CPU-tråden” eller ”hårdvarutråden” eller ”hyper-tråden.”Varje CPU-tråd innehåller en uppsättning register och möjligheten att utföra en ström av maskinkod, ungefär som en programtråd.
  • CPU-trådar Finns i en ” CPU-kärna.”De flesta moderna processorer innehåller två trådar per kärna.
  • moderna processorer innehåller i allmänhet flera nivåer av cacheminne. Cache-nivåerna närmare CPU-tråden är mindre, snabbare och dyrare. Ju längre bort från CPU och närmare huvudminnet cachen är desto större, långsammare och billigare är det.
  • typisk modern CPU-design använder en L1 / L2-cache per kärna. Detta innebär att varje CPU-tråd på kärnan använder samma cachar.
  • flera CPU-kärnor finns i ett ” CPU-paket.”Moderna processorer kan innehålla uppemot 30 kärnor (60 trådar) eller mer per förpackning.
  • alla CPU-kärnor i paketet delar vanligtvis en L3-cache.
  • CPU-paket passar in i ” uttag.”De flesta konsumentdatorer är enda uttag medan många datacenterservrar har flera uttag.

spekulativt utförande

figur 5: modern CPU-exekveringsmotor (källa: Google images)

den sista delen av bakgrundsinformation som krävs för att förstå sårbarheterna är en modern CPU-teknik som kallas ” spekulativ exekvering.”Figur 5 visar ett generiskt diagram över exekveringsmotorn i en modern CPU.

den primära takeawayen är att moderna processorer är oerhört komplicerade och inte bara utför maskininstruktioner i ordning. Varje CPU-tråd har en komplicerad rörledningsmotor som kan utföra instruktioner i ordning. Anledningen till detta har att göra med caching. Som jag diskuterade i föregående avsnitt använder varje CPU flera nivåer av caching. Varje cache-miss lägger till en betydande mängd fördröjningstid för programkörning. För att mildra detta kan processorer utföra framåt och i ordning medan de väntar på minnesbelastningar. Detta kallas spekulativt utförande. Följande kodavsnitt visar detta.

if (x < array1_size) {
y = array2 * 256];
}

i föregående utdrag, föreställ dig att array1_size inte är tillgängligt i cache, men adressen till array1 är. CPU: n kan gissa (spekulera) att x är mindre än array1_size och fortsätt och utför beräkningarna i if-uttalandet. När array1_size läses från minnet kan CPU avgöra om den gissade korrekt. Om det gjorde det kan det fortsätta att ha sparat en massa tid. Om det inte gjorde det kan det kasta bort spekulativa beräkningar och börja om. Detta är inte värre än om det hade väntat i första hand.

en annan typ av spekulativ exekvering kallas indirekt gren förutsägelse. Detta är extremt vanligt i moderna program på grund av virtuell sändning.

class Base {
public:
virtual void Foo() = 0;
};class Derived : public Base {
public:
void Foo() override { … }
};Base* obj = new Derived;
obj->Foo();

(källan till föregående utdrag är det här inlägget)

det sätt som föregående utdrag implementeras i maskinkod är att ladda ”v-table” eller”virtual dispatch table”från minnesplatsen som obj pekar på och sedan kallar det. Eftersom denna operation är så vanlig har moderna processorer olika interna cachar och kommer ofta att gissa (spekulera) där den indirekta grenen kommer att gå och fortsätta exekveringen vid den tiden. Återigen, om CPU gissar korrekt, kan det fortsätta att ha sparat en massa tid. Om det inte gjorde det kan det kasta bort spekulativa beräkningar och börja om.

Meltdown sårbarhet

Efter att ha täckt all bakgrundsinformation kan vi dyka in i sårbarheterna.

Rogue data cache load

den första sårbarheten, känd som Meltdown, är förvånansvärt enkel att förklara och nästan trivial att utnyttja. Exploateringskoden ser ungefär ut som följande:

1. uint8_t* probe_array = new uint8_t;
2. // ... Make sure probe_array is not cached
3. uint8_t kernel_memory = *(uint8_t*)(kernel_address);
4. uint64_t final_kernel_memory = kernel_memory * 4096;
5. uint8_t dummy = probe_array;
6. // ... catch page fault
7. // ... determine which of 256 slots in probe_array is cached

Låt oss ta varje steg ovan, beskriva vad det gör och hur det leder till att kunna läsa minnet på hela datorn från ett användarprogram.

  1. i den första raden tilldelas en ”sondmatris”. Detta är minne i vår process som används som en sidokanal för att hämta data från kärnan. Hur detta görs kommer snart att bli uppenbart.
  2. efter allokeringen ser angriparen till att inget av minnet i sondmatrisen är cachelagrat. Det finns olika sätt att uppnå detta, varav det enklaste inkluderar CPU-specifika instruktioner för att rensa en minnesplats från cache.
  3. angriparen fortsätter sedan att läsa en byte från kärnans adressutrymme. Kom ihåg från vår tidigare diskussion om virtuellt minne och sidtabeller att alla moderna kärnor vanligtvis kartlägger hela kärnans virtuella adressutrymme i användarprocessen. Operativsystem är beroende av det faktum att varje sidtabellpost har behörighetsinställningar och att användarlägesprogram inte får komma åt kärnminnet. All sådan åtkomst kommer att resultera i ett sidfel. Det är verkligen vad som så småningom kommer att hända i steg 3.
  4. men moderna processorer utför också spekulativ körning och kommer att utföra före felinstruktionen. Således kan steg 3-5 utföras i CPU: s rörledning innan felet uppstår. I detta steg multipliceras byte av kärnminne (som sträcker sig från 0-255) med systemets sidstorlek, vilket vanligtvis är 4096.
  5. i detta steg används den multiplicerade byten av kärnminnet för att läsa från sondmatrisen till ett dummyvärde. Multiplikationen av byte med 4096 är att undvika en CPU-funktion som kallas ”prefetcher” från att läsa mer data än vi vill ha i cachen.
  6. genom detta steg har CPU: n insett sitt misstag och rullat tillbaka till steg 3. Resultaten av de spekulerade instruktionerna är dock fortfarande synliga i cache. Angriparen använder operativsystemfunktionalitet för att fånga felinstruktionen och fortsätta exekveringen (t.ex. hantering av SIGFAULT).
  7. i steg 7 itererar angriparen igenom och ser hur lång tid det tar att läsa var och en av de 256 möjliga byte i sondmatrisen som kunde ha indexerats av kärnminnet. CPU: n har laddat en av platserna i cache och den här platsen laddas väsentligt snabbare än alla andra platser (som måste läsas från huvudminnet). Denna plats är värdet på byte i kärnminnet.

med hjälp av ovanstående teknik och det faktum att det är standardpraxis för moderna operativsystem att kartlägga allt fysiskt minne i kärnans virtuella adressutrymme kan en angripare läsa datorns hela fysiska minne.

Nu kanske du undrar: ”du sa att sidtabeller har behörighetsbitar. Hur kan det vara så att användarlägeskoden kunde spekulativt komma åt kärnminnet?”Anledningen är att detta är en bugg i Intel-processorer. Enligt min mening finns det ingen god anledning, prestanda eller på annat sätt, för att detta ska vara möjligt. Kom ihåg att all virtuell minnesåtkomst måste ske via TLB. Det är lätt möjligt under spekulativ körning att kontrollera att en cachad mappning har behörigheter som är kompatibla med den aktuella körprivilegienivån. Intel-hårdvara gör det helt enkelt inte. Andra processorleverantörer utför en behörighetskontroll och blockerar spekulativ körning. Så vitt vi vet är Meltdown en Intel-enda sårbarhet.

redigera: det verkar som om minst en ARM-processor också är mottaglig för smältning som anges här och här.

Meltdown mitigations

Meltdown är lätt att förstå, trivial att utnyttja, och lyckligtvis har också en relativt enkel begränsning (åtminstone konceptuellt — kärnutvecklare kanske inte håller med om att det är enkelt att implementera).

Kernel page table isolation (KPTI)

minns att i avsnittet om virtuellt minne beskrev jag att alla moderna operativsystem använder en teknik där kärnminnet mappas in i varje användarläge process virtuellt minne adressutrymme. Detta är av både prestanda och enkelhetsskäl. Det betyder att när ETT program gör ett systemanrop är kärnan redo att användas utan ytterligare arbete. Fixen för Meltdown är att inte längre utföra denna dubbla kartläggning.

Figur 6: kernel page Table isolation

figur 6 visar en teknik som kallas kernel page table isolation (kpti). Detta handlar i grunden om att inte kartlägga kärnminne i ett program när det körs i användarutrymme. Om det inte finns någon kartläggning närvarande är spekulativ utförande inte längre möjligt och kommer omedelbart fel.

förutom att göra operativsystemets virtuella minneshanterare (VMM) mer komplicerad, utan hårdvaruassistans kommer denna teknik också att avsevärt sakta ner arbetsbelastningar som gör ett stort antal Användarläge till kärnlägesövergångar, på grund av att sidtabellerna måste ändras vid varje övergång och TLB måste spolas (med tanke på att TLB kan hålla fast vid inaktuella mappningar).

nyare x86-processorer har en funktion som kallas ASID (address space ID) eller PCID (process context ID) som kan användas för att göra denna uppgift väsentligt billigare (ARM och andra mikroarkitekturer har haft den här funktionen i flera år). PCID tillåter att ett ID associeras med en TLB-post och sedan bara spola TLB-poster med det ID. Användningen av PCID gör KPTI billigare, men fortfarande inte gratis.

Sammanfattningsvis är Meltdown en extremt allvarlig och lätt att utnyttja sårbarhet. Lyckligtvis har det en relativt enkel begränsning som redan har distribuerats av alla större OS-leverantörer, varningen är att vissa arbetsbelastningar kommer att gå långsammare tills framtida hårdvara uttryckligen är utformad för den beskrivna adressutrymmesseparationen.

Spectre sårbarhet

Spectre delar vissa egenskaper hos Meltdown och består av två varianter. Till skillnad från Meltdown är Spectre väsentligt svårare att utnyttja, men påverkar nästan alla moderna processorer som producerats under de senaste tjugo åren. I huvudsak är Spectre en attack mot modern CPU-och operativsystemdesign jämfört med en specifik säkerhetsproblem.

Bounds check bypass (Spectre variant 1)

den första Spectre-varianten kallas ”bounds check bypass.”Detta visas i följande kodavsnitt (vilket är samma kodavsnitt som jag använde för att införa spekulativ körning ovan).

if (x < array1_size) {
y = array2 * 256];
}

i föregående exempel antar du följande händelsesekvens:

  1. angriparen kontrollerar x.
  2. array1_size är inte cachelagrat.
  3. array1 är cachad.
  4. CPU gissar att x är mindre än array1_size. (Processorer använder olika proprietära algoritmer och heuristik för att avgöra om de ska spekulera, varför attackdetaljer för Spectre varierar mellan processorleverantörer och modeller.)
  5. CPU exekverar kroppen av IF-uttalandet medan den väntar på array1_size för att ladda, vilket påverkar cachen på ett liknande sätt som Meltdown.
  6. angriparen kan sedan bestämma det faktiska värdet för array1 via en av olika metoder. (Se forskningsdokumentet för mer information om cache-inferensattacker.)

Spectre är betydligt svårare att utnyttja än Meltdown eftersom denna sårbarhet inte beror på utökning av privilegier. Angriparen måste övertyga kärnan att köra kod och spekulera felaktigt. Vanligtvis måste angriparen förgifta spekulationsmotorn och lura den att gissa felaktigt. Som sagt, forskare har visat flera proof-of-concept exploits.

Jag vill upprepa vad ett verkligt otroligt att hitta detta utnyttjande är. Jag anser inte personligen att detta är en CPU-designfel som Meltdown i sig. Jag anser att detta är en grundläggande uppenbarelse om hur modern hårdvara och mjukvara fungerar tillsammans. Det faktum att CPU-cachar kan användas indirekt för att lära sig om åtkomstmönster har varit känt under en tid. Det faktum att CPU-cachar kan användas som en sidokanal för att dumpa datorminne är häpnadsväckande, både konceptuellt och i dess konsekvenser.

Branch target injection (Spectre variant 2)

Kom ihåg att indirekt förgrening är mycket vanligt i moderna program. Variant 2 Av Spectre använder indirekt grenförutsägelse för att förgifta CPU: n till spekulativt utförande i en minnesplats som den aldrig annars skulle ha utfört. Om exekvering av dessa instruktioner kan lämna tillstånd bakom i cachen som kan detekteras med hjälp av cache-inferensattacker, kan angriparen sedan dumpa allt kärnminne. Liksom Spectre variant 1, Spectre variant 2 är mycket svårare att utnyttja än härdsmälta, men forskare har visat arbetar proof-of-concept utnyttjar variant 2.

Spectre mitigations

Spectre mitigations är väsentligt mer intressanta än Meltdown mitigation. Faktum är att academic Spectre paper skriver att det för närvarande inte finns några kända mildringar. Det verkar som om bakom kulisserna och parallellt med det akademiska arbetet har Intel (och förmodligen andra CPU-leverantörer) och de stora OS-och molnleverantörerna arbetat rasande i månader för att utveckla mildringar. I det här avsnittet kommer jag att täcka de olika begränsningarna som har utvecklats och implementerats. Detta är det avsnitt Jag är mest disig på eftersom det är oerhört svårt att få korrekt information så jag pussla ihop saker från olika källor.

statisk analys och fäktning (variant 1 mitigation)

den enda kända variant 1 (bounds check bypass) mitigation är statisk analys av kod för att bestämma kodsekvenser som kan angripas för att störa spekulation. Sårbara kodsekvenser kan ha en serialiseringsinstruktion som lfence infogad som stoppar spekulativ körning tills alla instruktioner upp till staketet har utförts. Försiktighet måste vidtas när du sätter in staketinstruktioner eftersom för många kan ha allvarliga prestandaeffekter.

Retpoline (variant 2 mitigation)

den första Spectre variant 2 (branch target injection) mitigation utvecklades av Google och är känd som ”retpoline.”Det är oklart för mig om det utvecklades isolerat av Google eller av Google i samarbete med Intel. Jag skulle spekulera i att det experimentellt utvecklades av Google och sedan verifierades av Intel-hårdvaruingenjörer, men jag är inte säker. Detaljer om” retpoline ” – metoden finns i Googles papper om ämnet. Jag kommer att sammanfatta dem här (jag glansar över några detaljer inklusive underflöde som omfattas av papperet).

Retpoline förlitar sig på det faktum att Anropet och återkomsten från funktioner och tillhörande stackmanipulationer är så vanliga i datorprogram att CPU: er är kraftigt optimerade för att utföra dem. (Om du inte är bekant med hur stacken fungerar i förhållande till att ringa och återvända från funktioner här inlägget är en bra primer.) I ett nötskal, när ett ”samtal” utförs, trycks returadressen på stapeln. ”ret” dyker returadressen av och fortsätter utförandet. Spekulativ exekveringshårdvara kommer ihåg den pressade returadressen och fortsätter spekulativt exekveringen vid den tiden.

retpoline-konstruktionen ersätter ett indirekt hopp till minnesplatsen lagrad i registret r11:

jmp *%r11

med:

call set_up_target; (1)
capture_spec: (4)
pause;
jmp capture_spec;
set_up_target:
mov %r11, (%rsp); (2)
ret; (3)

Låt oss se vad den tidigare monteringskoden gör ett steg i taget och hur det mildrar greninjektion.

  1. i detta steg anropar koden en minnesplats som är känd vid kompileringstiden så är en hårdkodad offset och inte indirekt. Detta placerar returadressen för capture_spec på stacken.
  2. returadressen från samtalet skrivs över med det faktiska hoppmålet.
  3. en retur utförs på det verkliga målet.
  4. när CPU spekulativt exekverar kommer den att återgå till en oändlig slinga! Kom ihåg att CPU: n kommer att spekulera framåt tills minnesbelastningen är klar. I det här fallet har spekulationerna manipulerats för att fångas in i en oändlig slinga som inte har några biverkningar som kan observeras för en angripare. När CPU så småningom utför den verkliga avkastningen kommer den att avbryta det spekulativa utförandet som inte hade någon effekt.

enligt min mening är detta en verkligt genial mildring. Kudos till ingenjörerna som utvecklade den. Nackdelen med denna begränsning är att den kräver att all programvara kompileras så att indirekta grenar omvandlas till retpoline-grenar. För molntjänster som Google som äger hela stacken är omkompilering inte en stor sak. För andra kan det vara en mycket stor sak eller omöjlig.

IBRS, STIBP och IBPB (variant 2 mitigation)

det verkar som om samtidigt med retpoline-utvecklingen har Intel (och AMD i viss utsträckning) arbetat rasande på hårdvaruändringar för att mildra greninjektionsattacker. De tre nya hårdvarufunktionerna som skickas som CPU-mikrokoduppdateringar är:

  • indirekt gren begränsad spekulation (IBRS)
  • Single Thread indirekt gren prediktorer (STIBP)
  • indirekt gren prediktor barriär (IBPB)

begränsad information om de nya mikrokod funktioner är tillgängliga från Intel här. Jag har kunnat grovt sammanfoga vad dessa nya funktioner gör genom att läsa ovanstående dokumentation och titta på Linux kernel och Xen hypervisor patchar. Från min analys används varje funktion potentiellt enligt följande:

  • IBRS spolar båda grenförutsägelsecachen mellan behörighetsnivåer (användare till kärna) och inaktiverar grenförutsägelse på syskonens CPU-tråd. Kom ihåg att varje CPU-kärna vanligtvis har två CPU-trådar. Det verkar som om på moderna processorer delas grenprediktionshårdvaran mellan trådarna. Detta innebär att inte bara kan användarläge kod förgifta gren prediktor innan du anger kärnkod, kod som körs på syskon CPU tråden kan också förgifta den. Att aktivera IBRS i kärnläge förhindrar i huvudsak tidigare körning i användarläge och eventuell körning på syskonens CPU-tråd från att påverka grenförutsägelse.
  • STIBP verkar vara en delmängd av IBRS som bara inaktiverar grenförutsägelse på syskonens CPU-tråd. Såvitt jag kan säga är det huvudsakliga användningsfallet för den här funktionen att förhindra att en syskon CPU-tråd förgiftar grenprediktorn när man kör två olika användarlägesprocesser (eller virtuella maskiner) på samma CPU-kärna samtidigt. Det är ärligt talat inte helt klart för mig just nu när STIBP ska användas.
  • IBPB verkar spola grenförutsägelsecachen för kod som körs på samma behörighetsnivå. Detta kan användas när du växlar mellan två användarlägesprogram eller två virtuella maskiner för att säkerställa att den tidigare koden inte stör den kod som ska köras (men utan STIBP tror jag att koden som körs på syskonens CPU-tråd fortfarande kan förgifta grenprediktorn).

När detta skrivs verkar de viktigaste begränsningarna som jag ser implementeras för branch target injection vulnerability vara både retpoline och IBRS. Förmodligen är detta det snabbaste sättet att skydda kärnan från användarlägesprogram eller hypervisorn från virtuella maskingäster. I framtiden förväntar jag mig att både STIBP och IBPB ska distribueras beroende på paranoia-nivån för olika användarlägesprogram som stör varandra.

kostnaden för IBRS verkar också variera extremt mycket mellan CPU-arkitekturer med nyare Intel Skylake-processorer som är relativt billiga jämfört med äldre processorer. På Lyft såg vi en cirka 20% avmattning på vissa systemanrop tunga arbetsbelastningar på AWS C4-instanser när begränsningarna rullades ut. Jag skulle spekulera i att Amazon rullade ut IBRS och eventuellt också retpoline, men jag är inte säker. Det verkar som om Google kanske bara har rullat ut retpoline i sitt moln.

med tiden förväntar jag mig att processorer så småningom flyttar till en IBRS ”always on” – modell där hårdvaran bara är standard för att rengöra grenpredictorseparation mellan CPU-trådar och korrekt spolar tillstånd på ändringar av behörighetsnivå. Den enda anledningen till att detta inte skulle göras idag är den uppenbara prestandakostnaden för att eftermontera denna funktionalitet på redan släppta mikroarkitekturer via mikrokoduppdateringar.

slutsats

det är mycket sällsynt att ett forskningsresultat i grunden förändrar hur datorer byggs och körs. Meltdown Och Spectre har gjort just det. Dessa resultat kommer att förändra hårdvaru-och mjukvarudesign väsentligt under de kommande 7-10 åren (nästa CPU-hårdvarucykel), eftersom designers tar hänsyn till den nya verkligheten av möjligheterna till dataläckage via cache-sidokanaler.

under tiden kommer Meltdown-Och Spectre-resultaten och tillhörande mildringar att få betydande konsekvenser för datoranvändare under de kommande åren. På kort sikt kommer begränsningarna att ha en prestandapåverkan som kan vara betydande beroende på arbetsbelastning och specifik hårdvara. Detta kan kräva operativa förändringar för vissa infrastrukturer (till exempel på Lyft flyttar vi aggressivt vissa arbetsbelastningar till AWS C5-instanser på grund av att IBRS verkar springa väsentligt snabbare på Skylake-processorer och den nya Nitro hypervisor levererar avbrott direkt till gäster som använder SR-IOV och APICv, vilket tar bort många virtuella maskinutgångar för Io tunga arbetsbelastningar). Stationära datoranvändare är inte immuna heller, på grund av proof-of-concept webbläsarattacker med JavaScript som OS och webbläsare leverantörer arbetar för att mildra. På grund av sårbarheternas komplexitet är det dessutom nästan säkert att säkerhetsforskare kommer att hitta nya exploater som inte omfattas av de nuvarande begränsningarna som måste patchas.

Även om jag älskar att arbeta på Lyft och känner att det arbete vi gör i MicroService systems infrastructure space är några av de mest effektfulla arbeten som görs i branschen just nu, gör händelser som detta att jag saknar att arbeta med operativsystem och hypervisorer. Jag är extremt avundsjuk på det heroiska arbete som gjordes under de senaste sex månaderna av ett stort antal människor för att undersöka och mildra sårbarheterna. Jag skulle gärna ha varit en del av det!

vidare läsning

  • härdsmälta och Spectre akademiska uppsatser: https://spectreattack.com/
  • Google Project Zero blogginlägg: https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html
  • Intel Spectre hardware mitigations: https://software.intel.com/sites/default/files/managed/c5/63/336996-Speculative-Execution-Side-Channel-Mitigations.pdf
  • retpoline blogginlägg: https://support.google.com/faqs/answer/7625886
  • bra sammanfattning av känd information: https://github.com/marcan/speculation-bugs/blob/master/README.md



Lämna ett svar

Din e-postadress kommer inte publiceras.