linux 分叉不安全吗

Is linux fork insecure

我正在读这个article

它说叉子创建了自己的副本 fork man 也这么说

. The entire virtual address space of the parent is replicated in the child

这是否意味着子进程可以读取我所有的进程内存状态?

子进程是否可以转储整个父内存状态,并且可以对其进行分析以提取父变量及其值。 ?

但是文章也说两个进程不能互相准备数据。 所以我很困惑?

是的,child 进程可以读取所有 parent 进程状态的 原始副本 (但是在写入时,只有它自己的地址 space 受到影响) 就在 fork(2). However, most of the time, the child would eventually use execve(2) to start a new program, and that would "clear" and replace the copy of the original parent's address space (by a fresh address space). Notice that execve and mmap(2) (see also shared memory in shm_overview(7)...) are the common ways to change the address space in virtual memory of some process (and how the kernel handles page faults).

之后

内核使用(并设置 MMU for) lazy copy on write 机制使 child 的地址 space 成为 parent 的副本,所以 fork 在实践中非常有效。

另请阅读 proc(5),然后键入以下命令:

cat /proc/self/maps
cat /proc/$$/maps
sudo cat /proc/1/maps

并了解正在发生的事情

另请阅读 fork, and the Advanced Linux Programming 书中的维基页面。

没有不安全因素,因为如果 child 正在更改某些数据(例如变量、堆或堆栈位置...),它不会影响 parent 进程。

如果执行 fork 的程序在某个虚拟内存位置保存一些密码,child 进程只要执行相同的程序就能够读取该位置。一旦 child 成功执行了 execve(这是常见的情况,任何 shell 正在做的事情)之前的地址 space 就会消失并被新地址取代,在该 exec-ed 程序的 ELF 可执行文件中进行了描述。

那个 Unix 模型中没有 "lie" 或 "insecurity"。但与其他几个操作系统相反,Unix & POSIX 有两个独立的 system calls for creating a new process (fork) and executing a new program (execve). Other systems might have some single spawn operation mixing the two abilities. posix_spawn is often implemented by a mixture of fork & execve (and so are system(3) & popen(3), also using waitpid(2) & /bin/sh.....).

Unix 方法的优点(将 forkexecve 分开)是在 fork 之后和 child 中的 execve 之前你可以做很多有用的事情(例如关闭无用的文件描述符,......)。不分离这两个功能的操作系统可能需要有一个相当复杂的生成原语。

很少有 fork 而不是 后跟一些 execve。一些MPI implementations might do that, and you might also do that. But then you know that you are able to read all the parent's address space thru your own copy - so what you felt was an insecurity is becoming a useful feature. In the old days you had the obsolete vfork which blocked the parents. There is not need to use it today; actually, fork is often implemented thru clone(2) which you should not use directly in practice (see futex(7)...) but only thru POSIX pthreads。但将 fork 视为过程的神奇克隆器可能会有所帮助。

编码时(即使在 C 中)不要忘记测试 forkexecve 的失败。参见 perror(3)

PS。 fork 系统调用与 multiverse 的想法一样难以理解。都是"forking"的时候!

当您调用 fork() 时,新进程将访问 父进程内存的副本(即变量、文件描述符等)。

这与线程形成对比,其中所有线程共享相同的内存space,即在一个线程中修改的变量将在所有其他线程中获得新值。

所以如果,分叉后,父进程修改内存,子进程将看不到该更改 - 因为内存已被复制,子进程的内存将不会得到改变了。