5.系統呼叫如何安全地獲取引數
直接傳遞給kernel資料的地址(指標)?,
- 核心和使用者的頁表不同,不能直接訪問使用者地址
- 可能會傳遞核心記憶體地址,直接訪問就是安全漏洞
因此核心不能使用普通指令從使用者提供的地址載入或儲存。 核心實現了一些函式,可以安全地在使用者提供的地址之間傳輸資料。
fetchstr
是一個例子(kernel/syscall.c:25)
。檔案系統呼叫,如exec
,就使用fetchstr
從使用者空間檢索字串檔名引數。
方法就是利用使用者頁表對地址進行訪問,將資料複製到一個臨時建立的陣列中使用,這樣如果地址不合法,使用者頁表是無法解析的
5.1 fetchstr()
int fetchstr(uint64 addr, char *buf, int max)
{
struct proc *p = myproc();
//將user pagetable傳遞過去
if(copyinstr(p->pagetable, buf, addr, max) < 0)
return -1;
return strlen(buf);
}
5.2 copyinstr()
int copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
{
uint64 n, va0, pa0;
int got_null = 0;
while(got_null == 0 && max > 0){
va0 = PGROUNDDOWN(srcva);
pa0 = walkaddr(pagetable, va0);
if(pa0 == 0)
return -1;
n = PGSIZE - (srcva - va0);
if(n > max)
n = max;
char *p = (char *) (pa0 + (srcva - va0));
while(n > 0){
if(*p == '\0'){
*dst = '\0';
got_null = 1;
break;
} else {
*dst = *p;
}
--n;
--max;
p++;
dst++;
}
srcva = va0 + PGSIZE;
}
if(got_null){
return 0;
} else {
return -1;
}
}