Interaction between fork and user memory displayed in the kernel

Consider a Linux driver that uses (or ) to map pages from a calling process. Then the physical address of the pages is transmitted to the hardware device. Both the process and the device can read and write to pages until the parties decide to stop communicating. In particular, the link may continue to use pages after the system call that invokes . A system call actually creates a shared memory zone between the process and the hardware device . get_user_pagesget_pageget_user_pages

I'm worried about what happens if the process calls (it can be from another thread and can happen either when the syscall call is made, which calls ) or later), In particular, if the parent writes to the shared memory after the fork What do I know about the base physical address (presumably changed due to copy to write)? I want to understand: forkget_user_pages

  • what the kernel should do to protect against a potentially erroneous process (I do not want to create a security hole !);
  • what restrictions must the process fulfill in order for the functionality of our driver to work correctly (i.e. physical memory remains mapped to the same address in the parent process).

    • Ideally, I would like the usual case when the child process does not use our driver at all (maybe it calls almost immediately exec).
    • Ideally, the parent process should not take any special measures when allocating memory, since we have existing code that passes the buffer allocated by the stack to the driver.
    • I know madvisewith MADV_DONTFORK, and it would be normal if the memory disappeared from the child space of the process, but it is not applicable to the buffer allocated on the stack.
    • "Do not use the plug until you have a connection with our driver" will be annoying, but acceptable as a last resort if point 1 is satisfied.

. Linux, . RTFS, , .

, (, ≥2.6.26). Arm (, - ), .

+3
2

A fork() get_user_pages(): get_user_pages() struct page.

kmap() , , .

EDIT: get_user_pages() , ( , ) -EFAULT, .

fork(), , . ( // , kmap(), ), . - kmap() ( ), , .

1) , , exec(), .

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 vma fork, ,

+4

- madvise(addr, len, MADV_DONTFORK) , . , , CoW.

, , , , , . .

: , , .

DONTFORK, , , ( ), . ( , DONTFORK, , fork).

CoW , .

, CoW, . "" , CoW, , , .

, , on-stack, , forking, .. on-stack . , , , , , - .

, , , . . mmap , , mmap, madvise(DONTFORK) , , mlock(), .

+3

Source: https://habr.com/ru/post/1771988/


All Articles