# Reading [The Linux Kernel Module Programming Guide](https://sysprog21.github.io/lkmpg/) (6) ## System Call 前面提到user program要用system call才能操作kernel space的資料,舉凡各種檔案操作,讀取kernel資訊像是時間或版本號等等。在舊的版本是用system call table維護syscall的function pointer,當呼叫syscall時才從這table取出對應的function pointer執行,這種方式又被稱作indirect call。 針對indirect call,硬體設計有類似if/else的branch predictor,叫做 Branch Target Buffer (BTB),用來預測要跳轉執行的位置,使cpu pipeline減少不必要的等待。 ## 為何要改成switch case的形式來跳到要執行的function? ### [Spectre Attacks](https://spectreattack.com/spectre.pdf) 先從這篇最後提供的範例了解x86架構下的Spectre attacks如何洩漏secret data ### 基礎概念 假設想要偷的資料secret位置是已知的,透過違法存取`array1[x]` 可以找到,例子中的x是array1 address 和secret address的距離,但是即便知道個位置,也只能使用branch predictor暫時的違法存取,在branch predictor校正回歸後還是拿不到secret address的值。所以這邊hacker很天才的利用cache不會被還原的機制找到一個漏洞,先建立一塊可以合法存取的buffer,一開始如果這塊buffer還沒load進cache裡面,程式去讀取它的時候會比較耗時。利用branch predictor錯誤時違法讀到的值來access這塊可以合法讀取的buffer,像是`array2[array1[x] * 512];`,如此一來,之後程式讀取`array2[array1[x] * 512]`的速度就會比讀取其他位置更快,利用時間差可以知道違法讀到的值`array1[x]`是什麼。 以下介紹範例程式的邏輯: 這邊secret是hacker想要讀取的位置,這邊看到victim_function是有boundary check,保證不會違法存取的狀況,array1其實不是很重要,它只要在branch predictor錯誤時可以短暫的access到secret data,將array2對應address放進cache,這邊的victim_function又被稱作gadget。 ```clike=14 unsigned int array1_size = 16; uint8_t unused1[64]; uint8_t array1[160] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; uint8_t unused2[64]; uint8_t array2[256 * 512]; char *secret = "The Magic Words are Squeamish Ossifrage."; uint8_t temp = 0; /* To not optimize out victim_function() */ void victim_function(size_t x) { if (x < array1_size) { temp &= array2[array1[x] * 512]; } } ``` `readMemoryByte`是主要的攻擊程式,主要的步驟如下 1. 將array2移出cache 2. 訓練branch predictor 3. 違法存取(使vitim_function短暫的讀到secret) 4. 找出array2裡面符合cache存取時間限制的位置 5. 該位置的值為secret的值 ## Spectre Attacks VARIANT 2 前面提到BTB可以減少pipeline的空指令,但是BTB mispredict發生時,就會先執行錯誤的function address再由cpu rollback執行結果,和前面同樣的是,cache沒有被rollback。假如已知kernel space gadget的address,可以在user program中訓練BTB指向kernel space gadget的對應位置,接下來呼叫syscall就會讓cpu短暫執行kernel space gadget,使的部分結果留在cache裡面,透過一些手段洩漏出來。 ## 使用swich case好處 使用switch case會讓branch predict失敗時跳轉的位置是固定在syscalls裡面,也就是說attacker不能自己決定要執行的gadget,最多只能從syscalls中挑一個,嚴重的限制attacker的行為。 ## 沒跑範例code的原因 我的環境是比較新版的linux,架構是RISC-V,要改寫S-mode read only memory是要M-mode的權限(Physical Memory Protection),我沒有找到必較簡單達成的方式因此放棄。(可能要從SBI下手但我還沒研究這麼多)