execveat(2) / fexecve(3) 与 Python 的子进程类似的行为

execveat(2) / fexecve(3) like behavior with Python’s subprocess

如何让 Python 的 subprocess 模块接受一个 fd 而不是路径(== execveat() with AT_EMPTY_PATH)? 示例:

subprocess.Popen (["argv0", "argv1"], shell=False,
                  executable=os.open ("/proc/self/exe",
                                      os.O_RDONLY
                                      | os.O_CLOEXEC))

使用 Python 3.6.5 由于 TypeError 而失败。

目标当然是避免验证之间的 TOCTTOU 二进制文件和对 execve(2).

的调用

我知道 os.execve() 也可以与 fds 一起使用,但我会 不想在此基础上重新实现 subprocess 模块。

CPython 的 _posixsubprocess, the internal implementation of subprocess for POSIX,既不支持 fexecve(3) 也不支持 execveat(2)。如果您可以假设 /proc 已安装,则只需将 /proc/self/fd/N(其中 N 是所需的 fd)指定为可执行文件。这也是 fexecve(3) 回退到旧内核的原因。有关 /proc/self/fd.

的详细信息,请参阅 Linux 联机帮助页 proc(5)

编辑 示例:

def spawn_exefd(args, fd, bufsize=-1, *args, **kwargs):
    return subprocess.Popen(args, bufsize, "/proc/self/fd/%d" % (fd,), *args, **kwargs)

#import fcntl # py2
import os
fd = os.open("/bin/sh", os.O_RDONLY | os.O_CLOEXEC)
#fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.fcntl(fd, fcntl.F_GETFD) | fcntl.FD_CLOEXEC) # py2
spawn_exefd(["sh", "-i"], fd)