# 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下手但我還沒研究這麼多)