前文:
五、熔斷(Meltdown)
In this section, present Meltdown, a powerful attack allowing to readarbitrary physical memory from an unprivileged user program, comprised of thebuilding blocks presented in Section 4. First, we discuss the attack setting toemphasize the wide applicability of this attack. Second, we present an attackoverview, showing how Meltdown can be mounted on both Windows and Linux onpersonal computers as well as in the cloud. Finally, we discuss a concreteimplementation of Meltdown allowing to dump kernel memory with up to 503KB/s.
在這一章我們將向您展示meltdown的威力:透過一個普通的使用者程式讀取系統中任意位置的物理記憶體。整個攻擊過程的框架圖已經在第4章描述。首先,我們討論攻擊設定,透過設定我們可以看出meltdown這種攻擊具有非常廣泛的適用性。其次,我們對meltdown攻擊進行概述,並展示了它如何對安裝Windows和Linux的個人計算機上以及雲伺服器展開攻擊。最後,我們討論了一個具體的實現,該Meltdown的實現允許以503kB/s的速度dump核心空間的記憶體。
Attack setting.
In our attack, we consider personal computersand virtual machines in the cloud. In the attack scenario, the attacker hasarbitrary unprivileged code execution on the attacked system, i.e., the attacker can run any code withthe privileges of a normal user. However, the attacker has no physical accessto the machine. Further, we assume that the system is fully protected withstate-of-the-art software-based defenses such as ASLR and KASLR as well as CPUfeatures like SMAP, SMEP, NX, and PXN. Most importantly, we assume a completelybug-free operating system, thus, no software vulnerability exists that can beexploited to gain kernel privileges or leak information. The attacker targets secretuser data, e.g., passwords and private keys, or any other valuable information.
攻擊設定如下:
我們考慮個人計算機和雲伺服器上的虛擬機器兩種應用場景。在攻擊過程中,攻擊者只使用未授權的程式碼來攻擊系統,也就是說攻擊者只能以一個普通使用者的許可權來執行程式碼。另外,攻擊者沒有對機器進行物理訪問。進一步,我們假設我們準備攻擊的系統是已經有了非常好的基於軟體的防禦措施,例如ASLR和KASLR,同時CPU也包含了像SMAP,SMEP,NX,和PXN的功能。最重要的是,我們假設被攻擊系統是一個完全無bug的作業系統,沒有軟體漏洞可以被利用來獲得root許可權或洩露資訊。攻擊者的標的是使用者的秘密資料,例如密碼和私鑰,或任何其他有價值的資訊。
1、概述
Meltdown combines the two building blocks discussed in Section 4. First,an attacker makes the CPU execute a transient instruction sequence which usesan inaccessible secret value stored somewhere in physical memory (cf. Section4.1). The transient instruction sequence acts as the transmitter of a covertchannel (cf. Section 4.2), ultimately leaking the secret value to the attacker.
Meltdown使用了第4章中討論攻擊架構圖。首先,攻擊者讓CPU執行一個瞬態指令序列,該指令序列會操作儲存在物理記憶體中不可訪問的秘密資料(參見第4.1節)。瞬態指令序列充當隱蔽通道的傳送端(參見第4.2節),最終將秘密資料洩漏給攻擊者。
Meltdown consists of 3 steps:
Step 1 The content of anattacker-chosen memory location,which is inaccessible to the attacker, isloaded into a register.
Step 2 Atransient instruction accesses a cache line based on the secret content of theregister.
Step 3 The attacker usesFlush+Reload to determine the accessed cache line and hence the secret storedat the chosen memory location.
By repeating these steps for different memory locations, the attacker candump the kernel memory, including the entire physical memory.
Meltdown攻擊包括3個步驟:
步驟1:攻擊者訪問秘密資料所在的記憶體位置(該記憶體是攻擊者沒有許可權訪問的),並載入到一個暫存器中。
步驟2,瞬態指令基於暫存器中儲存的秘密資料內容訪問cache line。
步驟3:攻擊者使用Flush+Reload來確定在步驟2中訪問的cache line,從而恢覆在步驟1中讀取的秘密資料。
在不同的記憶體地址上不斷重覆上面的步驟,攻擊者可以dump整個核心地址空間的資料,這也就包括了整個物理記憶體。
Listing 2 shows the basic implementation of the transient instructionsequence and the sending part of the covert channel, using x86 assemblyinstructions. Note that this part of the attack could also be implementedentirely in higher level languages like C. In the following, we will discuss eachstep of Meltdown and the corresponding code line in Listing 2.
上面的串列顯示了瞬態指令序列和隱蔽通道傳送部分的基本實現(使用x86彙編指令)。需要註意的是:這部分攻擊的程式碼也可以完全用C這樣的高階語言來實現。在隨後的文章中,我們會討論串列中的每一行程式碼是如何完成meltdown攻擊的。
Step 1: Reading the secret. To load data from the main memory into a register, thedata in the main memory is referenced using a virtual address. In parallel to translatinga virtual address into a physical address, the CPU also checks the permissionbits of the virtual address, i.e., whether this virtual address is user accessible or onlyaccessible by the kernel. As already discussed in Section 2.2, thishardware-based isolation through a permission bit is considered secure andrecommended by the hardware vendors. Hence, modern operating systems always mapthe entire kernel into the virtual address space of every user process.
步驟1:
讀記憶體中的秘密資料。為了將資料從主儲存器載入到暫存器中,我們使用虛擬地址來訪問主存中的資料。在將虛擬地址轉換為物理地址的同時,CPU還會檢查虛擬地址的許可權位:這個虛擬地址可否被使用者態訪問,還是隻能在核心態中訪問。正如在第2.2節中已經討論過的那樣,我們都認為這個基於硬體的地址空間隔離是安全的,並且硬體廠商也推薦使用這種隔離方法。因此,現代作業系統總是將整個核心地址空間對映到每個使用者行程的虛擬地址空間。
As a consequence, all kernel addresses lead to a valid physical addresswhen translating them, and the CPU can access the content of such addresses.The only difference to accessing a user space address is that the CPU raises anexception as the current permission level does not allow to access such an address.Hence, the user space cannot simply read the contents of such an address. However,Meltdown exploits the out-of-order execution of modern CPUs, which stillexecutes instructions in the small time window between the illegal memoryaccess and the raising of the exception.
訪問核心地址空間的時候,只要建立了虛擬地址的對映(即可以透過頁表翻譯出一個有效的物理地址),CPU都可以訪問這些地址的內容。和訪問使用者地址空間唯一不同是會進行許可權檢查,由於當前CPU許可權級別不夠而訪問核心空間地址的時候會觸發異常。因此,使用者空間不能簡單地透過讀取核心地址的內容來獲得秘密資料。然而,亂序執行的特性允許CPU在一個很小的時間視窗內(從執行了非法記憶體訪問的指令到觸發異常),仍然會繼續執行指令。Meltdown就是利用了亂序執行的特性完成了攻擊。
In line 4 of Listing 2, we load the byte value located at the targetkernel address, stored in the RCX register, into the least significantbyte of the RAX register represented by AL. As explained in more detail inSection 2.1, theMOV instruction is fetched by the core,decoded into μOPs, allocated, and sent to thereorder buffer. There, architectural registers (e.g., RAX and RCX in Listing 2) are mapped to underlyingphysical registers enabling out-of-order execution. Trying to utilize thepipeline as much as possible, subsequent instructions (lines 5-7) are already decodedand allocated as μOPs as well. The μOPs are further sent to thereservation station holding the μOPs while they wait to be executed by the correspondingexecution unit. The execution of a μOP can be delayed if execution units are already used totheir corresponding capacity or operand values have not been calculated yet.
在上面程式碼串列中的第4行,我們訪問了位於核心地址空間的memory(地址儲存在RCX暫存器),獲取了一個位元組的資料,儲存在AL暫存器(即RAX暫存器的8個LSB位元)。根據2.1節中的描述,MOV指令由CPU core取指,解碼成μOPS,分配併傳送到重排序緩衝區。在那裡,architecturalregister(軟體可見的暫存器,例如RAX和RCX)會被對映成底層的物理暫存器以便實現亂序執行。為了盡可能地利用流水線,隨後的指令(5-7的程式碼)已經解碼並分配為uOPs。該uOPs會進一步送到保留站(暫存uOPs),在保留站中,uOPs會等待相應的執行單元空閑,如果執行單元準備好,該uOPs會立刻執行,如果執行單元已經達到了容量的上限(例如有3個加法器,那麼可以同時進行3個加法運算,第四個加法uOPs就需要等待了)或uOPs運算元值尚未計算出來,uOPs則被延遲執行。
When the kernel address is loaded in line 4, it is likely that the CPUalready issued the subsequent instructions as part of the out-or-orderexecution, and that their corresponding μOPs wait in the reservation stationfor the content of the kernel address to arrive. As soon as the fetched data isobserved on the common data bus, the μOPs can begin their execution.
當在程式第4行載入核心地址到暫存器的時候,由於亂序執行,很可能CPU已經把後續指令發射出去,並且它們相應的μOPs會在保留站中等待核心地址的內容到來。一旦在公共資料匯流排上觀察到所獲取的核心地址資料,這些μOPs就會立刻開始執行。
When the μOPs finish their execution, theyretire in order, and, thus, their results are committed to the architectural state.During the retirement, any interrupts and exception that occurred during theexecution of the instruction are handled. Thus, if the MOV instruction that loads the kernel address is retired, theexception is registered and the pipeline is flushed to eliminate all results ofsubsequent instructions which were executed out of order. However, there is arace condition between raising this exception and our attack step 2 which wedescribe below.
當μOPs執行完畢後,它們就按順序進行retire(這個術語叫做retire,很難翻譯,這裡就不翻譯了,但是和commit是一個意思),因此,μOPs的結果會被提交並體現在體系結構狀態上。在提交過程中,在執行指令期間發生的任何中斷和異常都會被處理。因此,在提交MOV指令的時候發現該指令操作的是核心地址,這時候會觸發異常。這時候CPU流水線會執行flush操作,由於亂序執行而提前執行的那些指令(Mov指令之後)結果會被清掉。然而,在觸發這個異常和我們執行的攻擊步驟2之間有一個競爭條件(race condition),我們在下麵描述。
As reported by Gruss et al. [9], prefetching kernel addresses sometimessucceeds. We found that prefetching the kernel address can slightly improve theperformance of the attack on some systems.
根據Gruss等人的研究[ 9 ],預取核心地址有時成功。我們發現:預取核心地址可以略微改善某些系統的攻擊效能。
Step 2: Transmitting the secret. The instruction sequence from step 1 which is executedout of order has to be chosen in a way that it becomes a transient instruction sequence.If this transient instruction sequence is executed before the MOV instruction is retired (i.e., raises the exception), and thetransient instruction sequence performed computations based on the secret, itcan be utilized to transmit the secret to the attacker.
步驟2:傳送秘密資料
在步驟1中亂序執行的指令序列能否成為瞬態指令序列是需要條件的。如果的確是瞬態指令序列,那麼它必須要在MOV指令retirement之前被執行(即在觸發異常之前),而且瞬態指令序列會基於秘密資料進行計算,而這個計算的副作用可以用來向攻擊者傳遞秘密資料。
As already discussed, we utilize cache attacks that allow to build fastand low-noise covert channel using the CPU’s cache. Thus, the transientinstruction sequence has to encode the secret into the microarchitectural cachestate, similarly to the toy example in Section 3.
正如之前已經討論過的,我們利用快取攻擊,即利用CPU的高速快取建立快速和低噪聲的隱蔽通道。然後,瞬態指令序列必須要把秘密資料編碼在微架構快取狀態中。這個過程類似於第三節中的那個簡單示例程式。
We allocate a probe array in memory and ensure that no part of this arrayis cached. To transmit the secret, the transient instruction sequence containsan indirect memory access to an address which is calculated based on the secret(inaccessible) value. In line 5 of Listing 2 the secret value from step 1 ismultiplied by the page size, i.e., 4 KB. The multiplication of the secret ensures thataccesses to the array have a large spatial distance to each other. Thisprevents the hardware prefetcher from loading adjacent memory locations intothe cache as well. Here, we read a single byte at once, hence our probe array is256×4096 bytes, assuming 4KB pages.
我們在記憶體中分配一個探測陣列,並確保該陣列的所有記憶體都沒有被cached。為了傳遞秘密資料,瞬態指令序列包含對探測陣列的間接記憶體訪問,具體的訪問地址是基於那個秘密資料的(該秘密資料是使用者態不可訪問的)。具體可以參考上面串列中的第5行程式碼:第1步獲取的秘密資料會乘以頁面大小,即4 KB(程式碼使用了移位操作,是一樣的意思)。這個乘法操作確保了對陣列的訪問具有較大的空間距離。這可以防止硬體prefetcher把相鄰儲存單元的資料載入到快取中。在這示例中,由於一次只讀出一個位元組,所以我們的探測陣列是256×4096位元組(假設頁面大小是4KB)。
Note that in the out-of-order execution we have a noise-bias towardsregister value ‘0’. Wediscuss the reasons for this in Section 5.2. However, for this reason, we introducea retry-logic into the transient instruction sequence. In case we read a ‘0’, we try to read the secret again (step1). In line 7, the multiplied secret is added to the base address of the probearray, forming the target address of the covert channel. This address is readto cache the corresponding cache line. Consequently, our transient instructionsequence affects the cache state based on the secret value that was read instep 1.
註意:在亂序執行中,我們對暫存器值“0”有一個噪聲偏置(noise-bias)。我們在第5.2節討論了具體的原因。正是由於這個原因,我們在瞬態指令序列中引入了重試邏輯。如果我們讀到了“0”值,我們試著重新讀這個秘密資料(第1步)。在程式碼的第7行中,將秘密資料乘以4096並累加到探測陣列的基地址中,從而形成隱蔽通道的標的地址。讀取該標的地址可以將資料載入到對應的cacheline中。因此,瞬態指令序列根據第1步中讀取的秘密資料修改了探測陣列對應的快取狀態。
Since the transient instruction sequence in step 2 races against raisingthe exception, reducing the runtime of step 2 can significantly improve theperformance of the attack. For instance, taking care that the addresstranslation for the probe array is cached in the TLB increases the attackperformance on some systems.
由於步驟2中的瞬態指令序列需要和異常的觸發相競爭,因此減少步驟2的執行時間可以顯著提高攻擊的效能。例如:把探測陣列的地址翻譯預先快取在TLB中。
Step 3: Receiving the secret. In step 3, the attacker recovers the secret value (step1) by leveraging a microarchitectural side-channel attack (i.e., the receiving end of a microarchitecturalcovert channel) that transfers the cache state (step 2) back into anarchitectural state. As discussed in Section 4.2, Meltdown relies onFlush+Reload to transfer the cache state into an architectural state.
步驟3:接收秘密資料。
在步驟3中,攻擊者利用微架構側通道攻擊(即微架構隱蔽通道的接收端)將cache state轉換成了軟體可以感知的體系結構狀態(architectural state),從而恢復了秘密資料。正如第4.2節中所討論的,meltdown依賴於Flush+Reload來將快取狀態轉換為CPU體系結構狀態。
When the transient instruction sequence of step 2 is executed, exactly onecache line of the probe array is cached. The position of the cached cache linewithin the probe array depends only on the secret which is read in step 1.Thus, the attacker iterates over all 256 pages of the probe array and measuresthe access time for every first cache line (i.e., offset) on the page. The number of thepage containing the cached cache line corresponds directly to the secret value.
在步驟2中執行的瞬態指令序列時,整個探測陣列只有一個頁面的cacheline被載入了。具體載入的cacheline的在探測陣列中的位置僅取決於步驟1中讀取的秘密資料。因此,攻擊者遍歷所有探測陣列中的256個頁面,測試每個頁面第一個cacheline的訪問時間,已經預先載入了cacheline的那個page index就直接對應著秘密資料的數值。
Dumping the entire physical memory. By repeating all 3 steps of Meltdown,the attacker can dump the entire memory by iterating over all differentaddresses. However, as the memory access to the kernel address raises an exceptionthat terminates the program, we use one of the methods described in Section 4.1to handle or suppress the exception.
Dump整個物理記憶體:
透過重覆上面的3個步驟,同時修改不同的攻擊地址,攻擊者可以dump所有記憶體。但是,由於對核心地址的記憶體訪問引發了一個終止程式的異常,所以我們使用第4.1節中描述的方法來處理或抑制這個異常。
As all major operating systems also typically map the entire physicalmemory into the kernel address space (cf. Section 2.2) in every user process,Meltdown is not only limited to reading kernel memory but it is capable ofreading the entire physical memory of the target machine.
在目前所有的主流作業系統中,我們通常會把整個物理記憶體對映到核心地址空間(參見第2.2節),而每個使用者行程中又包括核心地址空間部分。因此Meltdown不僅能讀取核心地址空間的記憶體值,而且能夠讀取整個系統的物理記憶體。
2、最佳化和限制(optimizations and limitations)
The case of 0. If the exception is triggered while trying to read from an inaccessiblekernel address, the register where the data should be stored, appears to bezeroed out. This is reasonable because if the exception is unhandled, the userspace application is terminated, and the value from the inaccessible kerneladdress could be observed in the register contents stored in the core dump ofthe crashed process. The direct solution to fix this problem is to zero out thecorresponding registers. If the zeroing out of the register is faster than theexecution of the subsequent instruction (line 5 inListing 2), the attacker may read a false value in the third step. To preventthe transient instruction sequence from continuing with a wrong value, i.e., ‘0’, Meltdown retries reading the address until itencounters a value different from ‘0’(line 6). As the transient instruction sequence terminates after the exception israised, there is no cache access if the secret value is 0. Thus, Meltdownassumes that the secret value is indeed ‘0’if there is no cache hit at all.
讀出數值是0的場景。
根據前面的描述,在instruction commit階段,當檢測到使用者態訪問核心地址的時候,除了觸發異常,CPU還會清除指令的操作結果,也就是說AL暫存器會被清零。如果瞬態指令序列在和異常的競爭中失敗了(暫存器清零早於上面程式串列中第五行程式碼執行),那麼很可能從核心地址讀出的並非其真是值,而是清零後的數值。對暫存器清零也是合理的,因為如果異常沒有被處理,使用者空間的應用程式會終止,該行程的core dump檔案中會保留暫存器的內容,如果不清零,那麼核心空間的資料可以透過core dump檔案洩露出去。清零可以修正這個issue,保證核心空間資料的安全。為了防止瞬態指令序列繼續操作錯誤的“0”值,Meltdown會重讀地址直到讀出非“0”值(第6行程式碼)。
你可能會問:如果秘密資料就是0怎麼辦?其實當異常觸發後,瞬態指令序列終止執行,如果秘密資料確實等於0,則不存在任何cacheline被載入。因此,meltdown在進行探測資料cacheline掃描過程中,如果沒有任何cacheline命中,那麼秘密資料實際上就是“0”。
The loop is terminated by either the read value not being ‘0’ or by the raised exception of theinvalid memory access. Note that this loop does not slow down the attackmeasurably, since, in either case, the processor runs ahead of the illegalmemory access, regardless of whether ahead is a loop or ahead is a linearcontrol flow. In either case, the time until the control flow returned fromexception handling or exception suppression remains the same with and withoutthis loop. Thus, capturing read ‘0’sbeforehand and recovering early from a lost race condition vastly increases thereading speed.
無論是讀出數值非“0”或無效地址訪問觸發了異常,程式碼中的迴圈邏輯都會終止。註意,這個迴圈不會降低攻擊的效能,因為,在上面兩種情況中,CPU會提前允許非法記憶體訪問指令之後的程式碼指令,而CPU並不關心這些指令是一個迴圈控制或是一個線性的控制流。無論哪一種情況,從異常處理函式(或者異常抑制)傳回的時間都是一樣的,和有沒有迴圈控制是無關的。因此,儘早發現讀出值是“0”,也就是說儘早發現自己在和異常的競爭中失敗並恢復,可以大大提高了讀取速度。
Single-bit transmission :
In the attack description in Section 5.1, the attacker transmitted 8 bitsthrough the covert channel at once and performed 28 = 256 Flush+Reload measurements to recover the secret.However, there is a clear trade-off between running more transient instructionsequences and performing more Flush+Reload measurements. The attacker couldtransmit an arbitrary number of bits in a single transmission through thecovert channel, by either reading more bits using a MOV instruction for a larger data value. Furthermore, the attackercould mask bits using additional instructions in the transient instructionsequence. We found the number of additional instructions in the transientinstruction sequence to have a negligible influence on the performance of theattack.
單個bit資料的傳送:
在第5.1節的描述中,攻擊者透過隱蔽通道一次可以傳輸8個bit,接收端執行2^8=256次Flush+Reload命令來恢復秘密資料。不過,我們需要在執行更多的瞬態指令序列和執行更多的Flush+Reload測量之間進行平衡。攻擊者可以透過隱蔽通道在一次傳輸中傳送任意位元的資料,當然這需要使用MOV指令去讀取更多bit的秘密資料。此外,攻擊者可以在瞬態指令序列中增加mask的操作(這樣可以傳送更少的bit,從而減少接收端Flush+Reload的次數)。我們發現在瞬態指令序列中增加的指令數對攻擊的效能影響是微不足道的。
The performance bottleneck in the generic attack description above isindeed, the time spent on Flush+Reload measurements. In fact, with thisimplementation, almost the entire time will be spent on Flush+Reload measurements.By transmitting only a single bit, we can omit all but one Flush+Reloadmeasurement, i.e., the measurement on cache line 1. Ifthe transmitted bit was a ‘1’,then we observe a cache hit on cache line 1. Otherwise, we observe no cache hiton cache line 1.
上面描述的meltdown攻擊中的效能瓶頸主要是在透過Flush+Reload恢復秘密資料上所花費的時間。實際上在本章中的meltdown程式碼實現中,幾乎所有的時間都將花費在Flush+Reload上了。如果只傳送一個bit,那麼除了一次Flush+Reload測量時間,其他的我們都可以忽略。在這種情況下,我們只需要檢測一個cacheline的狀態,如果cache hit,那麼傳輸的bit是“1”,如果cache miss,那麼傳輸的bit是“0”。
Transmitting only a single bit at once also has drawbacks. As describedabove, our side channel has a bias towards a secret value of ‘0’. If we read and transmit multiple bitsat once, the likelihood that all bits are ‘0’may quite small for actual user data. The likelihood that a single bit is ‘0’ is typically close to 50 %. Hence, thenumber of bits read and transmitted at once is a tradeoff between some impliciterror-reduction and the overall transmission rate of the covert channel.
一次只傳輸一個位元也有缺點。如上所述,我們的側通道更偏向於“0”值。如果我們一次讀取多個位元的秘密資料併發送出去,那麼所有bit都是“0”的可能性應該說是相當小。單個bit等於“0”的可能性通常接近50%。因此,一次傳輸的位元數是需要在隱蔽通道的總傳輸速率和減少差錯之間進行平衡。
However, since the error rates are quite small in either case, ourevaluation (cf. Section 6) is based on the single-bit transmission mechanics.
不過,由於兩種情況下的錯誤率都很小,因此我們的評估(參見第6節)是基於單位元傳輸機制的。
Exception Suppression using IntelTSX.
和Intel的TSX相關,暫時沒有興趣瞭解。
Dealing with KASLR.
In 2013, kernel address space layoutrandomization (KASLR) had been introduced to the Linux kernel (starting fromversion 3.14 [4]) allowing to randomize the location of the kernel code at boottime. However, only as recently as May 2017, KASLR had been enabled by defaultin version 4.12 [27]. With KASLR also the direct-physical map is randomizedand, thus, not fixed at a certain address such that the attacker is required toobtain the randomized offset before mounting the Meltdown attack. However, therandomization is limited to 40 bit.
處理KASLR。
2013年,核心地址空間佈局隨機化(KASLR)已被合併到Linux核心中(從3.14版開始[ 4 ]),這個特性允許在開機的時候把核心程式碼載入到一個隨機化地址上去。在最近的(2017年5月)4.12版的核心中,KASLR已經被預設啟用[27 ]。並且直接對映部分的地址也是隨機的,並非固定在某個地址上。因此,在利用meltdown漏洞對核心進行攻擊之前,攻擊者需要需要獲得一個40-bit的隨機偏移值。
Thus, if we assume a setup of the target machine with 8GB of RAM, it issufficient to test the address space for addresses in 8GB steps. This allows tocover the search space of 40 bit with only 128 tests in the worst case. If theattacker can successfully obtain a value from a tested address, the attackercan proceed dumping the entire memory from that location. This allows to mount Meltdownon a system despite being protected by KASLR within seconds.
假設標的機有8GB記憶體,那麼我們其實是可以使用8G的步長來進行地址空間的探測。即便是在最壞的情況下也只有128次就可以確定這個40-bit的隨機偏移值。攻擊者一旦能夠成功地攻擊某個測試地址,那麼他也可以繼續從該位置dump整個記憶體。儘管系統受到KASLR的保護,實際上利用meltdown漏洞,攻擊者也可以在幾秒鐘內完成攻擊。
本文未完待續