我担心如果进程调用fork会发生什么(它可能来自另一个线程,并且可能在调用get_user_pages的系统调用正在进行时或之后发生).特别是,如果父进程在fork之后写入共享内存区域,我对底层物理地址有什么了解(可能是由于写时复制而改变)?我想明白:
>内核需要做些什么才能防止可能行为不端的进程(我不想创建安全漏洞!);
>进程需要遵守什么限制,以便我们的驱动程序的功能正常工作(即物理内存仍然映射到父进程中的同一地址).>理想情况下,我想要一个常见的情况,即子进程根本不使用我们的驱动程序(它可能几乎立即调用exec)来工作.
>理想情况下,父进程在分配内存时不必采取任何特殊步骤,因为我们现有的代码将堆栈分配的缓冲区传递给驱动程序.>我知道MADV_DONTFORK的madvise,并且可以让内存从子进程的空间中消失,但它不适用于堆栈分配的缓冲区.>“当你与我们的驱动程序激活连接时不要使用fork”会很烦人,但如果满足第1点,则可以接受作为最后的手段.我愿意指出文档或源代码.我特别关注Linux Device Drivers,但没有发现这个问题. RTFS应用于内核源代码的相关部分有点压倒性.
内核版本并没有完全修复,但是最新版本(假设≥2.6.26).如果重要的话,我们只针对Arm平台(到目前为止单处理器,但多核只是在拐角处).
fork()不会干扰get_user_pages():get_user_pages()将为您提供结构页面.在能够访问它之前,您需要kmap()它,并且此映射在内核空间中完成,而不是在用户空间中完成.
编辑:get_user_pages()触摸页面表,但你不应该担心这(它只是确保页面在用户空间中映射),并返回-EFAULT,如果它有任何问题这样做.
如果你fork(),直到执行copy-on-write,孩子将能够看到该页面.
一旦完成写入复制(因为子/驱动程序/父级通过用户空间映射写入页面 – 而不是驱动程序具有的内核kmap()),将不再共享该页面.如果您仍然在页面上(在驱动程序代码中)持有kmap(),您将无法知道您是持有父页面还是子页面.1)这不是一个安全漏洞,因为一旦你执行了(),所有这一切都消失了.
2)当你fork()时,你希望两个进程都是相同的(它是一个分叉!!).我认为你的设计应该允许父母和孩子访问驱动程序. Execve()将刷新所有内容.
如何在用户空间中添加一些功能,如:
f = open("/dev/your_thing") mapping = mmap(f, ...)
在设备上调用mmap()时,使用特殊标志安装内存映射:
http://os1a.cs.columbia.edu/lxr/source/include/Linux/mm.h#071你有一些有趣的东西,比如:
#define VM_SHARED 0x00000008 #define VM_LOCKED 0x00002000 #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */
VM_SHARED将禁止写入时复制VM_LOCKED将禁用该页面上的交换VM_DONTCOPY会告诉内核不要在fork上复制vma区域,虽然我不认为这是个好主意
精彩评论