【问题标题】:How linux kernel knows the address passed as argument in syscall is invalid?linux内核如何知道在系统调用中作为参数传递的地址无效?
【发布时间】:2018-10-23 09:39:40
【问题描述】:

目前我正在阅读了解 linux 内核系统调用一章,我无法理解 linux 内核如何知道通过 syscall() 传递的地址参数是无效的这一事实。

Book 提到地址检查会延迟到它被使用,当 linux 使用这个地址时它会产生页面错误。 它进一步提到在内核模式下可能会在三种情况下发生故障

• 内核尝试寻址属于该进程的页面 地址空间,但要么对应的页框不存在,要么 或者内核正在尝试写入只读页面。

• 某些内核函数包含一个编程错误,该错误会导致 执行该程序时引发的异常;或者, 该异常可能是由暂时性硬件错误引起的。

• 系统调用服务例程尝试读取或写入 地址已作为系统调用参数传递的内存区域, 但该地址不属于进程地址空间。

这些情况必须通过缺页处理程序来区分,因为要采取的操作完全不同。缺页处理程序可以通过确定错误的线性地址是否包含在所拥有的内存区域中来轻松识别第一种情况过程。

但是内核如何区分剩余的两种情况。虽然在教科书中有解释,但对我来说似乎很陌生。请帮忙解释一下。

【问题讨论】:

  • 您的问题有问题。当内核模式下可能发生页面错误时,您的三种情况似乎都没有解决。

标签: linux linux-kernel operating-system system-calls


【解决方案1】:

页面错误处理程序__do_page_fault 包含这段代码:

if (!(error_code & X86_PF_USER) &&
            !search_exception_tables(regs->ip)) {
            bad_area_nosemaphore(regs, error_code, address, NULL);
            return;
        }

当系统调用源自内核模式而不是用户模式时,此条件!(error_code & X86_PF_USER) 为真。当执行使用传递给系统调用的线性的指令之一没有发生页面错误时,此条件!search_exception_tables(regs->ip) 为真。请注意,regs->ip 包含导致页面错误的指令的指令指针。当这两个条件都为真时,这意味着要么是某个内核函数中存在错误,要么是存在某些硬件错误(第二种情况)。

regs 包含页面错误时所有架构寄存器的快照。在 x86 上,这包括 CS 段寄存器。该寄存器中的 RPL 可用于确定系统调用是源自用户模式还是内核模式。

search_exception_tables 在编译内核时在编译时构建的指令地址的排序数组上执行二进制搜索。这些基本上是访问传递给系统调用的地址的指令。

对于您列出的其他两种情况,条件!(error_code & X86_PF_USER) 将为假。

【讨论】:

    猜你喜欢
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多