From patchwork Tue Apr 18 21:35:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 55699 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 37758385703C for ; Tue, 18 Apr 2023 21:35:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 37758385703C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1681853735; bh=RzGsb+HctMlsTPaJwf01kxq+bFoJ9N+Vx5bHafuRew4=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=B+0V1xnF1z1iRUMBFuFDvakv7pHY7ApQpjoLej8pGQdi9Ce2RsEUDy5hsvqCUMQoZ /tNMpZUyPZOOFbFt4uSU9kY1KgU14oVTsF9Fxqj1xEwErtNEphmBJGDFxyfsjqIUHZ 4DYsJXMCWDe43//WrHEOUDJfx/gTmFE2HaHVuyNw= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-oo1-xc2c.google.com (mail-oo1-xc2c.google.com [IPv6:2607:f8b0:4864:20::c2c]) by sourceware.org (Postfix) with ESMTPS id A37153858D1E for ; Tue, 18 Apr 2023 21:35:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A37153858D1E Received: by mail-oo1-xc2c.google.com with SMTP id 006d021491bc7-545783a5950so650202eaf.2 for ; Tue, 18 Apr 2023 14:35:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681853709; x=1684445709; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=RzGsb+HctMlsTPaJwf01kxq+bFoJ9N+Vx5bHafuRew4=; b=l5eTQSw6uMp95496cXvE/syhFWrnXpn5vgEU5aW5FEglUOfY4vl98mB0VxuLO3UVB8 qyO1aA2cNv6bhGMEFhGBqfNKq/vxTDO7kTIrThyZuFdFbn720Dk0C7rrcR9a1v6L1hhS YrSQWtYoFcShQsw2SN9W+iWWk6RfiFoB89aKAM6no+CjhOrhfngCwMsBOY+QormkSiOj SNaM3wX2hvxG3fj0LkHBu46DJfvrhT9NOyK/r6MbiYn3i2jWJMocFnMUPYtDeFZ4kaKp 2LH9Xed3bEhHtdm6ly8LIo+0bUbZEXCSIS2cggkwY+YCv/eY+BrDBNPz4lf3OO1eNR1/ OEVw== X-Gm-Message-State: AAQBX9cCdw/W1QK2oXf0WtnfEB8vsj2+oa9q5Xf6ViyZPbzi/sgbjSEA Q1D7XNBuJMfA6yb03hq6kGKlK3IQahxwWwzDKusNAQ== X-Google-Smtp-Source: AKy350bMUXkrBofWy5HBC4loSRiJoIjSBHLKKpbkfohDz4OJt6x20+RT3PCR/jlLotfG3PLzOnfJ1A== X-Received: by 2002:a05:6870:b50a:b0:187:fa5e:f209 with SMTP id v10-20020a056870b50a00b00187fa5ef209mr2448722oap.5.1681853709298; Tue, 18 Apr 2023 14:35:09 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c3:333:3aff:2c50:5de7:ce94]) by smtp.gmail.com with ESMTPSA id e26-20020a05683013da00b006a6080ba7desm167581otq.58.2023.04.18.14.35.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Apr 2023 14:35:08 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 0/4] Add pidfd_spawn, pidfd_spawnp, pidfd_fork, and pidfd_getpid Date: Tue, 18 Apr 2023 18:35:01 -0300 Message-Id: <20230418213505.3834934-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Spam-Status: No, score=-5.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The glibc 2.36 added wrappers for Linux syscall pidfd_open, pidfd_getfd, and pidfd_send_signal, and exported the P_PIDFD to use with waitid. However, although the pidfd is a race free interface, the pidfd_open is subject to TOCTOU if the file descriptor is not obtained directly from the clone or clone3 syscall (there is still a small window between the clone return and the pidfd_getfd where the process can be reaped and the process ID reused). A fully race free interface with posix_spawn interface is being discussed by GNOME [1] [2], and Qt already uses on its QtProcess implementation [3]. The Qt code has some pitfalls by not using a libc provided symbol: - It calls clone through the syscall symbol, which does not run the pthread_atfork handlers even though it really intends to use the clone semantic for fork (by only using CLONE_PIDFD | SIGCHLD). - It also does not reset any internal state, such as internal IO, malloc, loader, etc. locks. - It does not set the TCB tid field nor the robust list, used by pthread code. - It does not optimize process creation by using CLONE_VM and CLONE_VFORK. The pidfd_spawn and pidfd_spawnp handles all these cases by using the same internal implementation used by posix_spawn: int pidfd_spawn (int *restrict pidfd, const char *restrict file, const posix_spawn_file_actions_t *restrict facts, const posix_spawnattr_t *restrict attrp, char *const argv[restrict], char *const envp[restrict]) int pidfd_spawnp (int *restrict pidfd, const char *restrict path, const posix_spawn_file_actions_t *restrict facts, const posix_spawnattr_t *restrict attrp, char *const argv[restrict_arr], char *const envp[restrict_arr]); The implementation makes sure that kernel must support the complete pidfd interface, meaning that waitid (P_PIDFD) should be supported. It ensure that non racy workaround is required (such as reading procfs fdinfo pid to use along with old wait interfaces). If kernel does not have the required support the interface returns ENOSYS. A new symbol is used instead of a posix_spawn extension to avoid possible issue with language bindings that might track the argument lifetime. Although for Linux pid_t and int are interchangeable, POSIX only state that pid_t should be a signed interger. Both symbols reuse the posix_spawn posix_spawn_file_actions_t and posix_spawnattr_t, to either avoid rehash posix_spawn API or add a new one. It also mean that both interfaces support the same attribute and file actions, and a new flag or file actions on posix_spawn is also added automatically for pidfd_spawn. Along with the spawn interface, a fork like one is also provided: int pidfd_fork (unsigned int flags) The kernel already sets O_CLOEXEC as default and it follow fork/_Fork convention on returning a positive or negative value to the parent (with negative indicating an error) and zero to the child. Different than fork, pidfd_fork does not run the pthread_atfork handlers (similar to _Fork). It can be change by using PIDFD_FORK_RUNATFORK with flags. To have a way to interop between process IDs and process file descriptors, the pidfd_getpid is also provided. It just read the procps fdinfo entry from the file descriptor to get the process ID. [1] https://gitlab.gnome.org/GNOME/glib/-/issues/1866 [2] https://sourceware.org/bugzilla/show_bug.cgi?id=30349 [3] https://codebrowser.dev/qt6/qtbase/src/3rdparty/forkfd/forkfd_linux.c.html Adhemerval Zanella (4): posix: Re-flow and sort multiline definitions posix: Add pidfd_spawn and pidfd_spawnp (BZ# 30349) posix: Add pidfd_fork linux: Add pidfd_getpid NEWS | 16 + bits/spawn_ext.h | 21 + include/clone_internal.h | 4 + manual/process.texi | 22 +- posix/Makefile | 556 ++++++++++++++---- posix/fork-internal.c | 125 ++++ posix/fork-internal.h | 29 + posix/fork.c | 98 +-- posix/spawn.h | 2 + posix/spawn_int.h | 3 +- posix/tst-posix_spawn-setsid.c | 168 ++++-- posix/tst-spawn-chdir.c | 15 +- posix/tst-spawn.c | 24 +- posix/tst-spawn.h | 36 ++ posix/tst-spawn2.c | 17 +- posix/tst-spawn3.c | 100 ++-- posix/tst-spawn4.c | 7 +- posix/tst-spawn5.c | 14 +- posix/tst-spawn6.c | 15 +- posix/tst-spawn7.c | 13 +- sysdeps/nptl/_Fork.c | 2 +- sysdeps/unix/sysv/linux/Makefile | 35 +- sysdeps/unix/sysv/linux/Versions | 6 + sysdeps/unix/sysv/linux/aarch64/libc.abilist | 4 + sysdeps/unix/sysv/linux/alpha/libc.abilist | 4 + sysdeps/unix/sysv/linux/arc/libc.abilist | 4 + sysdeps/unix/sysv/linux/arch-fork.h | 16 +- sysdeps/unix/sysv/linux/arm/be/libc.abilist | 4 + sysdeps/unix/sysv/linux/arm/le/libc.abilist | 4 + sysdeps/unix/sysv/linux/bits/spawn_ext.h | 45 ++ sysdeps/unix/sysv/linux/clone-pidfd-support.c | 58 ++ sysdeps/unix/sysv/linux/csky/libc.abilist | 4 + sysdeps/unix/sysv/linux/hppa/libc.abilist | 4 + sysdeps/unix/sysv/linux/i386/libc.abilist | 4 + sysdeps/unix/sysv/linux/ia64/libc.abilist | 4 + .../sysv/linux/loongarch/lp64/libc.abilist | 4 + .../sysv/linux/m68k/coldfire/libc.abilist | 4 + .../unix/sysv/linux/m68k/m680x0/libc.abilist | 4 + .../sysv/linux/microblaze/be/libc.abilist | 4 + .../sysv/linux/microblaze/le/libc.abilist | 4 + .../sysv/linux/mips/mips32/fpu/libc.abilist | 4 + .../sysv/linux/mips/mips32/nofpu/libc.abilist | 4 + .../sysv/linux/mips/mips64/n32/libc.abilist | 4 + .../sysv/linux/mips/mips64/n64/libc.abilist | 4 + sysdeps/unix/sysv/linux/nios2/libc.abilist | 4 + sysdeps/unix/sysv/linux/or1k/libc.abilist | 4 + sysdeps/unix/sysv/linux/pidfd_fork.c | 76 +++ sysdeps/unix/sysv/linux/pidfd_getpid.c | 70 +++ sysdeps/unix/sysv/linux/pidfd_spawn.c | 30 + sysdeps/unix/sysv/linux/pidfd_spawnp.c | 30 + .../linux/powerpc/powerpc32/fpu/libc.abilist | 4 + .../powerpc/powerpc32/nofpu/libc.abilist | 4 + .../linux/powerpc/powerpc64/be/libc.abilist | 4 + .../linux/powerpc/powerpc64/le/libc.abilist | 4 + sysdeps/unix/sysv/linux/procutils.c | 99 ++++ sysdeps/unix/sysv/linux/procutils.h | 37 ++ .../unix/sysv/linux/riscv/rv32/libc.abilist | 4 + .../unix/sysv/linux/riscv/rv64/libc.abilist | 4 + .../unix/sysv/linux/s390/s390-32/libc.abilist | 4 + .../unix/sysv/linux/s390/s390-64/libc.abilist | 4 + sysdeps/unix/sysv/linux/sh/be/libc.abilist | 4 + sysdeps/unix/sysv/linux/sh/le/libc.abilist | 4 + .../sysv/linux/sparc/sparc32/libc.abilist | 4 + .../sysv/linux/sparc/sparc64/libc.abilist | 4 + sysdeps/unix/sysv/linux/spawni.c | 20 +- sysdeps/unix/sysv/linux/sys/pidfd.h | 17 + sysdeps/unix/sysv/linux/tst-pidfd.c | 7 + sysdeps/unix/sysv/linux/tst-pidfd_fork.c | 150 +++++ .../sysv/linux/tst-posix_spawn-setsid-pidfd.c | 20 + .../unix/sysv/linux/tst-spawn-chdir-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn-pidfd.h | 63 ++ sysdeps/unix/sysv/linux/tst-spawn2-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn3-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn4-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn5-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn6-pidfd.c | 20 + sysdeps/unix/sysv/linux/tst-spawn7-pidfd.c | 20 + .../unix/sysv/linux/x86_64/64/libc.abilist | 4 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 4 + 80 files changed, 1975 insertions(+), 387 deletions(-) create mode 100644 bits/spawn_ext.h create mode 100644 posix/fork-internal.c create mode 100644 posix/fork-internal.h create mode 100644 posix/tst-spawn.h create mode 100644 sysdeps/unix/sysv/linux/bits/spawn_ext.h create mode 100644 sysdeps/unix/sysv/linux/clone-pidfd-support.c create mode 100644 sysdeps/unix/sysv/linux/pidfd_fork.c create mode 100644 sysdeps/unix/sysv/linux/pidfd_getpid.c create mode 100644 sysdeps/unix/sysv/linux/pidfd_spawn.c create mode 100644 sysdeps/unix/sysv/linux/pidfd_spawnp.c create mode 100644 sysdeps/unix/sysv/linux/procutils.c create mode 100644 sysdeps/unix/sysv/linux/procutils.h create mode 100644 sysdeps/unix/sysv/linux/tst-pidfd_fork.c create mode 100644 sysdeps/unix/sysv/linux/tst-posix_spawn-setsid-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn-chdir-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn-pidfd.h create mode 100644 sysdeps/unix/sysv/linux/tst-spawn2-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn3-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn4-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn5-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn6-pidfd.c create mode 100644 sysdeps/unix/sysv/linux/tst-spawn7-pidfd.c