From patchwork Thu May 16 13:59:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 10946679 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CEA501515 for ; Thu, 16 May 2019 14:00:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BFE8228BFB for ; Thu, 16 May 2019 14:00:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BD97A28B77; Thu, 16 May 2019 14:00:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BF8CE28BFB for ; Thu, 16 May 2019 14:00:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727679AbfEPOAV (ORCPT ); Thu, 16 May 2019 10:00:21 -0400 Received: from mail-ed1-f66.google.com ([209.85.208.66]:44204 "EHLO mail-ed1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727574AbfEPOAV (ORCPT ); Thu, 16 May 2019 10:00:21 -0400 Received: by mail-ed1-f66.google.com with SMTP id b8so5381262edm.11 for ; Thu, 16 May 2019 07:00:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brauner.io; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=rdh1LHywkV2wJSJtwTdvTYm1jPecNAhthVSzWzS8x28=; b=EfH+kmAUPYIdi8i/ZLz20DN6VfddPwKIm3dOIsBvKjGp8+W3IVOVFCAyF9CZwJ7FGu JdaJzyjLq9y5QgSU/ju1uz/X1/LtrpPOPnntcJCBY0OYfIGuUgdQg0Vi+xqyKb/PdM/+ a+T366Z3pa1iMVFlJDKD4CKvzNn+L6ClSzOJSLu89C4k2UmhfsuqufaanjNx0ajIpeI2 idCeGjvnfgorO7tvg2yAl7Rvqo+lBO9Du3ETT99moeRztpkhh/8x7MhN02EkQwgnPU4h JuD3AcqSnkGl9eliZBLPnSQ00nDlMTmMKW7zXW04kg7OjT6kraFritUXTjITi9F6MT6P o69g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=rdh1LHywkV2wJSJtwTdvTYm1jPecNAhthVSzWzS8x28=; b=Fu6roJRYqcDMjJ3q25MNRrusGfar5yGlKroFOxRA19yX+EzOncW3F05RLb/P9Ytyes 92gP6gvXXH4soJl+L4B0diHMqGcK+NnDRSxFZgtAFzitD0qDAoZB8g5ntXg7875/uMqk zFYBYS/SXJWyGB1E+0nZU5ZU3Fc/p0ps7LMQ/DjoAjI/GEXU2CoNVrj8X1EqE5M1lBrG /YCDObLHfycrUz0FZS81G9bzkJwxboOVPTyGq8KJU4WaN0fqHt26/xP5ghzusZJzyHwl MneMKdqdcdyIx0AKOCYdhIbp6QwoRjaznktCKvuj/nLwYyNNVnLCTJE+86wHn6yndotc MdpQ== X-Gm-Message-State: APjAAAUMJ8Jw09HIAHX6nAnzd5aMOvofsd1K7wDQbAYDhPjM28bMlEQG FohdfjIJvj1KW8FfZtYxuSLQ/w== X-Google-Smtp-Source: APXvYqwuOTQfi39bbLw0or9wCLE252NbPANqnRP1ECxNn0OftR1CtJ17zgJSULTBTb8tkyCdghu/TQ== X-Received: by 2002:a50:89b0:: with SMTP id g45mr51448451edg.200.1558015218674; Thu, 16 May 2019 07:00:18 -0700 (PDT) Received: from localhost.localdomain ([193.96.224.243]) by smtp.gmail.com with ESMTPSA id y20sm1093563ejb.40.2019.05.16.07.00.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 May 2019 07:00:17 -0700 (PDT) From: Christian Brauner To: jannh@google.com, oleg@redhat.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, linux-kernel@vger.kernel.org, arnd@arndb.de Cc: akpm@linux-foundation.org, cyphar@cyphar.com, dhowells@redhat.com, ebiederm@xmission.com, elena.reshetova@intel.com, keescook@chromium.org, luto@amacapital.net, luto@kernel.org, tglx@linutronix.de, linux-alpha@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-ia64@vger.kernel.org, linux-m68k@lists.linux-m68k.org, linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, sparclinux@vger.kernel.org, linux-xtensa@linux-xtensa.org, linux-api@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, joel@joelfernandes.org, dancol@google.com, serge@hallyn.com, Christian Brauner , Geert Uytterhoeven Subject: [PATCH v1 1/2] pid: add pidfd_open() Date: Thu, 16 May 2019 15:59:42 +0200 Message-Id: <20190516135944.7205-1-christian@brauner.io> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds the pidfd_open() syscall. It allows a caller to retrieve pollable pidfds for a process which did not get created via CLONE_PIDFD, i.e. for a process that is created via traditional fork()/clone() calls that is only referenced by a PID: int pidfd = pidfd_open(1234, 0); ret = pidfd_send_signal(pidfd, SIGSTOP, NULL, 0); With the introduction of pidfds through CLONE_PIDFD it is possible to created pidfds at process creation time. However, a lot of processes get created with traditional PID-based calls such as fork() or clone() (without CLONE_PIDFD). For these processes a caller can currently not create a pollable pidfd. This is a huge problem for Android's low memory killer (LMK) and service managers such as systemd. Both are examples of tools that want to make use of pidfds to get reliable notification of process exit for non-parents (pidfd polling) and race-free signal sending (pidfd_send_signal()). They intend to switch to this API for process supervision/management as soon as possible. Having no way to get pollable pidfds from PID-only processes is one of the biggest blockers for them in adopting this api. With pidfd_open() making it possible to retrieve pidfd for PID-based processes we enable them to adopt this api. In line with Arnd's recent changes to consolidate syscall numbers across architectures, I have added the pidfd_open() syscall to all architectures at the same time. Signed-off-by: Christian Brauner Acked-by: Geert Uytterhoeven Cc: Arnd Bergmann Cc: "Eric W. Biederman" Cc: Kees Cook Cc: Thomas Gleixner Cc: Jann Horn Cc: David Howells Cc: Andy Lutomirsky Cc: Andrew Morton Cc: Oleg Nesterov Cc: Aleksa Sarai Cc: Linus Torvalds Cc: Al Viro Cc: linux-api@vger.kernel.org --- v1: - kbuild test robot : - add missing entry for pidfd_open to arch/arm/tools/syscall.tbl - Oleg Nesterov : - use simpler thread-group leader check --- arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/arm64/include/asm/unistd32.h | 2 + arch/ia64/kernel/syscalls/syscall.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/linux/pid.h | 1 + include/linux/syscalls.h | 1 + include/uapi/asm-generic/unistd.h | 4 +- kernel/fork.c | 2 +- kernel/pid.c | 50 +++++++++++++++++++++ 20 files changed, 72 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 165f268beafc..ddc3c93ad7a7 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -467,3 +467,4 @@ 535 common io_uring_setup sys_io_uring_setup 536 common io_uring_enter sys_io_uring_enter 537 common io_uring_register sys_io_uring_register +538 common pidfd_open sys_pidfd_open diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 0393917eaa57..fc41fb34a636 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -441,3 +441,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 23f1a44acada..350e2049b4a9 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -874,6 +874,8 @@ __SYSCALL(__NR_io_uring_setup, sys_io_uring_setup) __SYSCALL(__NR_io_uring_enter, sys_io_uring_enter) #define __NR_io_uring_register 427 __SYSCALL(__NR_io_uring_register, sys_io_uring_register) +#define __NR_pidfd_open 428 +__SYSCALL(__NR_pidfd_open, sys_pidfd_open) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index 56e3d0b685e1..7115f6dd347a 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -348,3 +348,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index df4ec3ec71d1..44bf12b16ffe 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -427,3 +427,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index 4964947732af..0d32e5152dc0 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -433,3 +433,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 9392dfe33f97..726e107b3c9f 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -366,3 +366,4 @@ 425 n32 io_uring_setup sys_io_uring_setup 426 n32 io_uring_enter sys_io_uring_enter 427 n32 io_uring_register sys_io_uring_register +428 n32 pidfd_open sys_pidfd_open diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index fe8ca623add8..83b46b568d51 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -424,3 +424,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 00f5a63c8d9a..5294d04d7fa5 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -509,3 +509,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 061418f787c3..dcdb838adf49 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -430,3 +430,4 @@ 425 common io_uring_setup sys_io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open sys_pidfd_open diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index 480b057556ee..8e66edfbc521 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -430,3 +430,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index a1dd24307b00..d6f3bc686939 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -473,3 +473,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 4cd5f982b1e5..1af6b469160a 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -438,3 +438,4 @@ 425 i386 io_uring_setup sys_io_uring_setup __ia32_sys_io_uring_setup 426 i386 io_uring_enter sys_io_uring_enter __ia32_sys_io_uring_enter 427 i386 io_uring_register sys_io_uring_register __ia32_sys_io_uring_register +428 i386 pidfd_open sys_pidfd_open __ia32_sys_pidfd_open diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 64ca0d06259a..c18e6ebe3387 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -355,6 +355,7 @@ 425 common io_uring_setup __x64_sys_io_uring_setup 426 common io_uring_enter __x64_sys_io_uring_enter 427 common io_uring_register __x64_sys_io_uring_register +428 common pidfd_open __x64_sys_pidfd_open # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 30084eaf8422..21ee795f3003 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -398,3 +398,4 @@ 425 common io_uring_setup sys_io_uring_setup 426 common io_uring_enter sys_io_uring_enter 427 common io_uring_register sys_io_uring_register +428 common pidfd_open sys_pidfd_open diff --git a/include/linux/pid.h b/include/linux/pid.h index 3c8ef5a199ca..c938a92eab99 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -67,6 +67,7 @@ struct pid extern struct pid init_struct_pid; extern const struct file_operations pidfd_fops; +extern int pidfd_create(struct pid *pid); static inline struct pid *get_pid(struct pid *pid) { diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index e2870fe1be5b..989055e0b501 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -929,6 +929,7 @@ asmlinkage long sys_clock_adjtime32(clockid_t which_clock, struct old_timex32 __user *tx); asmlinkage long sys_syncfs(int fd); asmlinkage long sys_setns(int fd, int nstype); +asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags); asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, unsigned int vlen, unsigned flags); asmlinkage long sys_process_vm_readv(pid_t pid, diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index dee7292e1df6..94a257a93d20 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -832,9 +832,11 @@ __SYSCALL(__NR_io_uring_setup, sys_io_uring_setup) __SYSCALL(__NR_io_uring_enter, sys_io_uring_enter) #define __NR_io_uring_register 427 __SYSCALL(__NR_io_uring_register, sys_io_uring_register) +#define __NR_pidfd_open 428 +__SYSCALL(__NR_pidfd_open, sys_pidfd_open) #undef __NR_syscalls -#define __NR_syscalls 428 +#define __NR_syscalls 429 /* * 32 bit systems traditionally used different diff --git a/kernel/fork.c b/kernel/fork.c index 737db1828437..980cc1d2b8d4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1714,7 +1714,7 @@ const struct file_operations pidfd_fops = { * Return: On success, a cloexec pidfd is returned. * On error, a negative errno number will be returned. */ -static int pidfd_create(struct pid *pid) +int pidfd_create(struct pid *pid) { int fd; diff --git a/kernel/pid.c b/kernel/pid.c index 20881598bdfa..4afca3d6dcb8 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -451,6 +452,55 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) return idr_get_next(&ns->idr, &nr); } +/** + * pidfd_open() - Open new pid file descriptor. + * + * @pid: pid for which to retrieve a pidfd + * @flags: flags to pass + * + * This creates a new pid file descriptor with the O_CLOEXEC flag set for + * the process identified by @pid. Currently, the process identified by + * @pid must be a thread-group leader. This restriction currently exists + * for all aspects of pidfds including pidfd creation (CLONE_PIDFD cannot + * be used with CLONE_THREAD) and pidfd polling (only supports thread group + * leaders). + * + * Return: On success, a cloexec pidfd is returned. + * On error, a negative errno number will be returned. + */ +SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags) +{ + int fd, ret; + struct pid *p; + struct task_struct *tsk; + + if (flags) + return -EINVAL; + + if (pid <= 0) + return -EINVAL; + + p = find_get_pid(pid); + if (!p) + return -ESRCH; + + ret = 0; + rcu_read_lock(); + /* + * If this returns non-NULL the pid was used as a thread-group + * leader. Note, we race with exec here: If it changes the + * thread-group leader we might return the old leader. + */ + tsk = pid_task(p, PIDTYPE_TGID); + if (!tsk) + ret = -ESRCH; + rcu_read_unlock(); + + fd = ret ?: pidfd_create(p); + put_pid(p); + return fd; +} + void __init pid_idr_init(void) { /* Verify no one has done anything silly: */ From patchwork Thu May 16 13:59:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 10946677 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9481814DB for ; Thu, 16 May 2019 14:00:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 84AED28A35 for ; Thu, 16 May 2019 14:00:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8238B28BF1; Thu, 16 May 2019 14:00:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8E9C828A35 for ; Thu, 16 May 2019 14:00:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727765AbfEPOA3 (ORCPT ); Thu, 16 May 2019 10:00:29 -0400 Received: from mail-ed1-f66.google.com ([209.85.208.66]:41216 "EHLO mail-ed1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727773AbfEPOAX (ORCPT ); Thu, 16 May 2019 10:00:23 -0400 Received: by mail-ed1-f66.google.com with SMTP id m4so5413192edd.8 for ; Thu, 16 May 2019 07:00:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brauner.io; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rBkcy062NYYGXGh6TqicbzBWp7bPNVyN1NSgT1R4iSI=; b=SBA2Nz1vN94S1Ju76/cX3Iq2qNIMZWAqOz9NnQT+n2LMUVlrugi1VxMZtjUVjgcK9k due+GLQjcSxDqrflXBVQFei6HiKpDh7kApiPOrw6kmLMbbPktWHhXiOlumkx7NNcU1pA LDeIIhNfxe2C7tReM/gFpa3dfnLMFAPSO4pBByzIGvcpnd4z6hw8WNUNGVx+Udna4a1I vrAFHOvpdjC0+iCd4SPLgs7ROXDnIxLKx2xOa8zGLomxBC8L5tFYYd0k3jn/gD9zgeYE s1MFUtubfGy+X2H1NMfyabuSW+Ivg+MJT8zM9avfQbS+Qq1WiqQuhEumwvFTKsRnGoVk CFzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rBkcy062NYYGXGh6TqicbzBWp7bPNVyN1NSgT1R4iSI=; b=iOjTdRQC43+wokGu9lcnUBl5Bh4V9lQk8/KNRw4tzeYeI+lo4mkf6itcWgbuPtp1ab ADC+AruvMtf/lCtnulzbygXwrKaIUpE7l6EgOs2Z8U6SOpc0Ax7kfa/ki57o+WaU+d54 Ia33HVRlBgO4wK1ADhDgV/NZATeUYy5+V2QElMn38DNkARy7qto/aReYsfPneolt9MZQ 3CQXXhUFL8r6Qa8NnhJ4SuRNuc/aRSDo7IH8HkbZmRFVa9xmnKH5NBY0i9qzd8tnR6FK GGfpDuRcTrHxCQZc7nvGautjzEbNWfZmxIgyn9Cug+cZtrLXI5d6wXN75kvhUW+hj/1U MmaA== X-Gm-Message-State: APjAAAWn2dcCKjuf/j1D36QRmmh55RR+1EjZWBemO4SWzQQzQ4h+Cgns m+8Wv5npzQtPSSJ4IP9oIWyfWw== X-Google-Smtp-Source: APXvYqwK1uR02XhXcAPkNqh781MathY3wyFgpsh57U9z72OWZ2kjVfoYK27rsXdKaNrGO6FWKr6ZKQ== X-Received: by 2002:a50:b662:: with SMTP id c31mr51477064ede.252.1558015221861; Thu, 16 May 2019 07:00:21 -0700 (PDT) Received: from localhost.localdomain ([193.96.224.243]) by smtp.gmail.com with ESMTPSA id y20sm1093563ejb.40.2019.05.16.07.00.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 May 2019 07:00:21 -0700 (PDT) From: Christian Brauner To: jannh@google.com, oleg@redhat.com, viro@zeniv.linux.org.uk, torvalds@linux-foundation.org, linux-kernel@vger.kernel.org, arnd@arndb.de Cc: akpm@linux-foundation.org, cyphar@cyphar.com, dhowells@redhat.com, ebiederm@xmission.com, elena.reshetova@intel.com, keescook@chromium.org, luto@amacapital.net, luto@kernel.org, tglx@linutronix.de, linux-alpha@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-ia64@vger.kernel.org, linux-m68k@lists.linux-m68k.org, linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, sparclinux@vger.kernel.org, linux-xtensa@linux-xtensa.org, linux-api@vger.kernel.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, joel@joelfernandes.org, dancol@google.com, serge@hallyn.com, Christian Brauner , "Michael Kerrisk (man-pages)" Subject: [PATCH v1 2/2] tests: add pidfd_open() tests Date: Thu, 16 May 2019 15:59:43 +0200 Message-Id: <20190516135944.7205-2-christian@brauner.io> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190516135944.7205-1-christian@brauner.io> References: <20190516135944.7205-1-christian@brauner.io> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds testing for the new pidfd_open() syscalls. Specifically, we test: - that no invalid flags can be passed to pidfd_open() - that no invalid pid can be passed to pidfd_open() - that a pidfd can be retrieved with pidfd_open() - that the retrieved pidfd references the correct pid Signed-off-by: Christian Brauner Cc: Arnd Bergmann Cc: "Eric W. Biederman" Cc: Kees Cook Cc: Thomas Gleixner Cc: Jann Horn Cc: David Howells Cc: "Michael Kerrisk (man-pages)" Cc: Andy Lutomirsky Cc: Andrew Morton Cc: Oleg Nesterov Cc: Aleksa Sarai Cc: Linus Torvalds Cc: Al Viro Cc: linux-api@vger.kernel.org --- v1: unchanged --- tools/testing/selftests/pidfd/Makefile | 2 +- tools/testing/selftests/pidfd/pidfd.h | 57 ++++++ .../testing/selftests/pidfd/pidfd_open_test.c | 170 ++++++++++++++++++ tools/testing/selftests/pidfd/pidfd_test.c | 41 +---- 4 files changed, 229 insertions(+), 41 deletions(-) create mode 100644 tools/testing/selftests/pidfd/pidfd.h create mode 100644 tools/testing/selftests/pidfd/pidfd_open_test.c diff --git a/tools/testing/selftests/pidfd/Makefile b/tools/testing/selftests/pidfd/Makefile index deaf8073bc06..b36c0be70848 100644 --- a/tools/testing/selftests/pidfd/Makefile +++ b/tools/testing/selftests/pidfd/Makefile @@ -1,6 +1,6 @@ CFLAGS += -g -I../../../../usr/include/ -TEST_GEN_PROGS := pidfd_test +TEST_GEN_PROGS := pidfd_test pidfd_open_test include ../lib.mk diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h new file mode 100644 index 000000000000..8452e910463f --- /dev/null +++ b/tools/testing/selftests/pidfd/pidfd.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __PIDFD_H +#define __PIDFD_H + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kselftest.h" + +/* + * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c + * That means, when it wraps around any pid < 300 will be skipped. + * So we need to use a pid > 300 in order to test recycling. + */ +#define PID_RECYCLE 1000 + +/* + * Define a few custom error codes for the child process to clearly indicate + * what is happening. This way we can tell the difference between a system + * error, a test error, etc. + */ +#define PIDFD_PASS 0 +#define PIDFD_FAIL 1 +#define PIDFD_ERROR 2 +#define PIDFD_SKIP 3 +#define PIDFD_XFAIL 4 + +int wait_for_pid(pid_t pid) +{ + int status, ret; + +again: + ret = waitpid(pid, &status, 0); + if (ret == -1) { + if (errno == EINTR) + goto again; + + return -1; + } + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + + +#endif /* __PIDFD_H */ diff --git a/tools/testing/selftests/pidfd/pidfd_open_test.c b/tools/testing/selftests/pidfd/pidfd_open_test.c new file mode 100644 index 000000000000..9b073c1ac618 --- /dev/null +++ b/tools/testing/selftests/pidfd/pidfd_open_test.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pidfd.h" +#include "../kselftest.h" + +static inline int sys_pidfd_open(pid_t pid, unsigned int flags) +{ + return syscall(__NR_pidfd_open, pid, flags); +} + +static int safe_int(const char *numstr, int *converted) +{ + char *err = NULL; + long sli; + + errno = 0; + sli = strtol(numstr, &err, 0); + if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN)) + return -ERANGE; + + if (errno != 0 && sli == 0) + return -EINVAL; + + if (err == numstr || *err != '\0') + return -EINVAL; + + if (sli > INT_MAX || sli < INT_MIN) + return -ERANGE; + + *converted = (int)sli; + return 0; +} + +static int char_left_gc(const char *buffer, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (buffer[i] == ' ' || + buffer[i] == '\t') + continue; + + return i; + } + + return 0; +} + +static int char_right_gc(const char *buffer, size_t len) +{ + int i; + + for (i = len - 1; i >= 0; i--) { + if (buffer[i] == ' ' || + buffer[i] == '\t' || + buffer[i] == '\n' || + buffer[i] == '\0') + continue; + + return i + 1; + } + + return 0; +} + +static char *trim_whitespace_in_place(char *buffer) +{ + buffer += char_left_gc(buffer, strlen(buffer)); + buffer[char_right_gc(buffer, strlen(buffer))] = '\0'; + return buffer; +} + +static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen) +{ + int ret; + char path[512]; + FILE *f; + size_t n = 0; + pid_t result = -1; + char *line = NULL; + + snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd); + + f = fopen(path, "re"); + if (!f) + return -1; + + while (getline(&line, &n, f) != -1) { + char *numstr; + + if (strncmp(line, key, keylen)) + continue; + + numstr = trim_whitespace_in_place(line + 4); + ret = safe_int(numstr, &result); + if (ret < 0) + goto out; + + break; + } + +out: + free(line); + fclose(f); + return result; +} + +int main(int argc, char **argv) +{ + int pidfd = -1, ret = 1; + pid_t pid; + + pidfd = sys_pidfd_open(-1, 0); + if (pidfd >= 0) { + ksft_print_msg( + "%s - succeeded to open pidfd for invalid pid -1\n", + strerror(errno)); + goto on_error; + } + ksft_test_result_pass("do not allow invalid pid test: passed\n"); + ksft_inc_pass_cnt(); + + pidfd = sys_pidfd_open(getpid(), 1); + if (pidfd >= 0) { + ksft_print_msg( + "%s - succeeded to open pidfd with invalid flag value specified\n", + strerror(errno)); + goto on_error; + } + ksft_test_result_pass("do not allow invalid flag test: passed\n"); + ksft_inc_pass_cnt(); + + pidfd = sys_pidfd_open(getpid(), 0); + if (pidfd < 0) { + ksft_print_msg("%s - failed to open pidfd\n", strerror(errno)); + goto on_error; + } + ksft_test_result_pass("open a new pidfd test: passed\n"); + ksft_inc_pass_cnt(); + + pid = get_pid_from_fdinfo_file(pidfd, "Pid:", sizeof("Pid:") - 1); + ksft_print_msg("pidfd %d refers to process with pid %d\n", pidfd, pid); + + ret = 0; + +on_error: + if (pidfd >= 0) + close(pidfd); + + return !ret ? ksft_exit_pass() : ksft_exit_fail(); +} diff --git a/tools/testing/selftests/pidfd/pidfd_test.c b/tools/testing/selftests/pidfd/pidfd_test.c index d59378a93782..f01de87249c9 100644 --- a/tools/testing/selftests/pidfd/pidfd_test.c +++ b/tools/testing/selftests/pidfd/pidfd_test.c @@ -14,6 +14,7 @@ #include #include +#include "pidfd.h" #include "../kselftest.h" static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, @@ -62,28 +63,6 @@ static int test_pidfd_send_signal_simple_success(void) return 0; } -static int wait_for_pid(pid_t pid) -{ - int status, ret; - -again: - ret = waitpid(pid, &status, 0); - if (ret == -1) { - if (errno == EINTR) - goto again; - - return -1; - } - - if (ret != pid) - goto again; - - if (!WIFEXITED(status)) - return -1; - - return WEXITSTATUS(status); -} - static int test_pidfd_send_signal_exited_fail(void) { int pidfd, ret, saved_errno; @@ -128,13 +107,6 @@ static int test_pidfd_send_signal_exited_fail(void) return 0; } -/* - * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c - * That means, when it wraps around any pid < 300 will be skipped. - * So we need to use a pid > 300 in order to test recycling. - */ -#define PID_RECYCLE 1000 - /* * Maximum number of cycles we allow. This is equivalent to PID_MAX_DEFAULT. * If users set a higher limit or we have cycled PIDFD_MAX_DEFAULT number of @@ -143,17 +115,6 @@ static int test_pidfd_send_signal_exited_fail(void) */ #define PIDFD_MAX_DEFAULT 0x8000 -/* - * Define a few custom error codes for the child process to clearly indicate - * what is happening. This way we can tell the difference between a system - * error, a test error, etc. - */ -#define PIDFD_PASS 0 -#define PIDFD_FAIL 1 -#define PIDFD_ERROR 2 -#define PIDFD_SKIP 3 -#define PIDFD_XFAIL 4 - static int test_pidfd_send_signal_recycled_pid_fail(void) { int i, ret;