4.系统调用如何安全地获取参数

5.系统调用如何安全地获取参数

直接传递给kernel数据的地址(指针)?,

  1. 内核和用户的页表不同,不能直接访问用户地址
  2. 可能会传递内核内存地址,直接访问就是安全漏洞

因此内核不能使用普通指令从用户提供的地址加载或存储。 内核实现了一些函数,可以安全地在用户提供的地址之间传输数据。

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;
  }
}
posted @ 2024-04-21 00:18  INnoVation-V2  阅读(9)  评论(0编辑  收藏  举报