![我找到了进行系统调用的内核代码。但我想这是不允许的?](https://linux22.com/image/149896/%E6%88%91%E6%89%BE%E5%88%B0%E4%BA%86%E8%BF%9B%E8%A1%8C%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E7%9A%84%E5%86%85%E6%A0%B8%E4%BB%A3%E7%A0%81%E3%80%82%E4%BD%86%E6%88%91%E6%83%B3%E8%BF%99%E6%98%AF%E4%B8%8D%E5%85%81%E8%AE%B8%E7%9A%84%EF%BC%9F.png)
语境:linux-5.0/Documentation/process/adding-syscalls.rst#do-not-call-system-calls-in-the-kernel
首先,内核代码不能再调用像“sys_xyzzy()”这样的函数,因为它们有错误的调用约定。
但其次,“内核数据和用户数据之间的数据访问方式可能有所不同。”
现在有一些函数可以直接替换旧的“sys_xyzzy()”调用。例如:ksys_mount()。
ksys_mount() 获取指向__user
内存的指针,就像调用 sys_mount() 所做的那样。因此,如果您向它传递一个指向内核内存的指针,它应该会失败。具体来说,当调用copy_from_user()时会失败,除非你用set_fs()玩游戏。
那么...为什么我们要在内核中的不同位置多次调用 ksys_mount() 呢?这些怎么可能起作用?它们不包含对 set_fs() 的调用。
https://elixir.bootlin.com/linux/v5.0/ident/ksys_mount
- 驱动程序/base/devtmpfs.c
- 初始化/do_mounts.c
- ...
答案1
devtmpfs
当前在内核线程中运行。在内核线程中,addr_limit
被有效禁用。至少对于 x86 来说是这样的——它是特定于体系结构的代码。
init/do_mounts.c
很相似。内核 init 进程必须像内核线程一样启动,并addr_limit
有效禁用。随后,它调用do_execve()
开始执行用户空间init程序。内核确保调用“set_fs(USER_DS)”,在执行用户空间程序之前。