Security Linux系统调用&;内核模式
我知道系统调用的存在是为了提供对用户空间中不允许的功能的访问,例如使用Security Linux系统调用&;内核模式,security,system-calls,Security,System Calls,我知道系统调用的存在是为了提供对用户空间中不允许的功能的访问,例如使用read()系统调用访问HDD。我还了解到,这些是由用户模式层以库调用的形式抽象的,例如fread(),以提供跨硬件的兼容性 因此,从应用程序开发人员的角度来看,我们有以下几点: 我的问题是,;是什么阻止我将fread()和read()函数中的所有指令直接内联到程序中?指令是相同的,所以CPU应该以相同的方式工作?我还没有试过,但我认为这不起作用的原因,我失踪。否则,任何应用程序都可能获得任意内核模式操作 TL;DR:什么允许
read()
系统调用访问HDD。我还了解到,这些是由用户模式层以库调用的形式抽象的,例如fread()
,以提供跨硬件的兼容性
因此,从应用程序开发人员的角度来看,我们有以下几点:
我的问题是,;是什么阻止我将fread()
和read()
函数中的所有指令直接内联到程序中?指令是相同的,所以CPU应该以相同的方式工作?我还没有试过,但我认为这不起作用的原因,我失踪。否则,任何应用程序都可能获得任意内核模式操作
TL;DR:什么允许系统调用“进入”应用程序无法复制的内核模式?您可以将它们内联。您可以通过
syscall(2)
直接发出系统调用,但这很快就会变得一团糟。请注意,系统调用开销(在内核检查中,上下文来回切换,…)更不用说系统调用本身所花费的时间了,通过在噪声中内联dissapear使您受益匪浅(如果有任何收益,更多的代码意味着缓存不太有用,性能会受到影响)。相信libc/内核人员已经研究了这个问题,并在背后为您做了内联(在相关的*.h
文件中),如果这真的是一个可测量的收益。系统调用本身不会进入内核。更准确地说,例如,就应用程序而言,您调用的read函数仍然是库调用。read(2)
在内部所做的是根据CPU体系结构和操作系统,使用一些中断或syscall(2)
汇编指令调用实际的系统调用
这是userland代码执行特权代码的唯一方式,但它是一种间接方式。用户区和内核代码在不同的上下文中执行
这意味着您不能将内核源代码添加到您的userland代码中,并期望它除了崩溃之外还能做任何有用的事情。特别是,内核代码可以访问与硬件交互所需的物理内存地址。Userland代码仅限于访问不具有此功能的虚拟内存空间。此外,允许userland代码执行的指令是CPU支持的指令的子集。一些与I/O、中断和虚拟化相关的指令就是禁用代码的示例。它们被称为特权指令,根据CPU体系结构的不同,需要处于较低的环或监控模式 我的意思是内联
read()
的内容,当然这也行不通,否则我可以在我的程序进入环0的任何点停止,然后转移到一些恶意软件。啊,这就是内存映射,很有趣。还有更多内容需要阅读,谢谢。更不用说在用户模式(答案更新)下禁止的特权指令了。嗯,我仍然不清楚切换是如何发生的,以及为什么我不能手动执行“切换指令”:
如果我只是将所有这些都内联在一个外壳代码中,为什么我得不到内核模式执行?切换是通过调用syscall(2)或等效程序来实现的。问题在于开关不是线性的,即开关后执行的指令不是您的指令,而是操作系统为您调用的特定系统调用号注册的指令。您的指令将仅在系统调用返回后执行,然后您将返回非特权模式。这就是为什么在运行现代操作系统时,你无法让你的代码在内核模式下执行,除非你编写并安装内核模块,或者自己编写操作系统……啊,现在越来越清楚了。执行内核模式指令的唯一方法是通过中断描述符表。因此,您必须要么写入IDT,要么写入IDT指向的内存区域。这两个进程永远不会映射为可写的usermode进程。谢谢你们两位。
//library //syscall //k_driver //device_driver
fread() -> read() -> k_read() -> d_read()