From patchwork Mon Nov 19 10:32:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 10688439 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 2BD0813B5 for ; Mon, 19 Nov 2018 10:33:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1B609287F8 for ; Mon, 19 Nov 2018 10:33:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0F32829310; Mon, 19 Nov 2018 10:33:42 +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=ham 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 8349C287F8 for ; Mon, 19 Nov 2018 10:33:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727951AbeKSU4w (ORCPT ); Mon, 19 Nov 2018 15:56:52 -0500 Received: from mail-pg1-f193.google.com ([209.85.215.193]:37508 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727943AbeKSU4w (ORCPT ); Mon, 19 Nov 2018 15:56:52 -0500 Received: by mail-pg1-f193.google.com with SMTP id 80so13659326pge.4 for ; Mon, 19 Nov 2018 02:33:40 -0800 (PST) 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=Pfk17pduLrrmmy1RCURdhpMiDwOWVPCBsvdRFX8G//Y=; b=BBwNgxcS+t4Ebk4vrZvTFSNs9/zXdIwZlcPQhEpiz45Wc4gH408AAAxSOHtCliu4xH SXAF2XL0zGSwoyrnyXuQ7QYugfPVeegiZzGw46Az5kSeVVFHgIhy8JDEWYCyEjXrBb0N VKsXtzt9w3e1KjAeF3Q5Ztlc27KJ2PGxQLG49xV4ksZiU96hQzaf9unC3scauJShPhdp NITbxwTpqa624dT7LpI10mH8/TtxKKYDFwBk0uzCbMKxAHSt0UxPLlxrtSYo9BC+d+gd RqcEuFfG0cF7dGGKFhBZHiYA1qqQWlHhHnVRxGLTUXtveEa1rJdhE2tuNBO7V6LNVOHb 0sFg== 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=Pfk17pduLrrmmy1RCURdhpMiDwOWVPCBsvdRFX8G//Y=; b=EoyRDdVAWuGaZ0s2fnnFA95M+AZ6GTzA3w8XdPWP/D5vFdmkdDptPEtU5yJ3BJ8b42 inpj8vvvl41rUhNisujYNmZx0X+Vj/5zsjjMqCFzLAhNqtFicUckxSZ8o+dEOBYyUtBr nN8ytZbKiKmOi8O2oGYS6/iRvNWh+ASeZLTl1il4oxyKp81Pg7iU2IXRQTHPUaNOOHQ6 c8RVH1b95e3rxG1ALcMesfdVqmVUkfJYBxUHP0lZfbpFiG+jnAmPPrAFQVM5bPoIKT1T 7L+LYr38Qxib+TQHV9+Y/Yspi2YaZmIweUikzbFr3TOB83TQlkBzUgvqd2NFE+DHGNm4 lOeg== X-Gm-Message-State: AGRZ1gLbUJWT79pE3OIKhi5S9KeB86UE5gpRNg7yYuqVij+Wa8kdlkKq SFSirPg1X9pLPWnKCvQHfQyaMQ== X-Google-Smtp-Source: AJdET5fineJx07A2aAOW+uwCqOS5ZORJf1bz2v1J9oGk4GcmIQOQgWMpKYd5GdMEyabhHmXHZ8VUoA== X-Received: by 2002:a62:ed09:: with SMTP id u9-v6mr21926577pfh.188.1542623620044; Mon, 19 Nov 2018 02:33:40 -0800 (PST) Received: from localhost.localdomain ([2404:4404:133a:4500:9d11:de0b:446c:8485]) by smtp.gmail.com with ESMTPSA id d21sm32958139pgv.37.2018.11.19.02.33.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Nov 2018 02:33:39 -0800 (PST) From: Christian Brauner To: ebiederm@xmission.com, linux-kernel@vger.kernel.org Cc: serge@hallyn.com, jannh@google.com, luto@kernel.org, akpm@linux-foundation.org, oleg@redhat.com, cyphar@cyphar.com, viro@zeniv.linux.org.uk, linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, dancol@google.com, timmurray@google.com, linux-man@vger.kernel.org, Christian Brauner , Kees Cook Subject: [PATCH v1 1/2] proc: get process file descriptor from /proc/ Date: Mon, 19 Nov 2018 11:32:38 +0100 Message-Id: <20181119103241.5229-2-christian@brauner.io> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181119103241.5229-1-christian@brauner.io> References: <20181119103241.5229-1-christian@brauner.io> MIME-Version: 1.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP With this patch an open() call on /proc/ will give userspace a handle to struct pid of the process associated with /proc/. This allows to maintain a stable handle on a process. I have been discussing various approaches extensively during technical conferences this year culminating in a long argument with Eric at Linux Plumbers. The general consensus was that having a handle on a process should be something that is very simple and easy to maintain with the option of being extensible via a more advanced api if the need arises. I believe that this patch is the most simple, dumb, and therefore maintainable solution. [1]: https://lkml.org/lkml/2018/10/30/118 Cc: "Eric W. Biederman" Cc: Serge Hallyn Cc: Jann Horn Cc: Kees Cook Cc: Andy Lutomirsky Cc: Andrew Morton Cc: Oleg Nesterov Cc: Aleksa Sarai Cc: Al Viro Signed-off-by: Christian Brauner --- Changelog: v1: - remove ioctl() to signal processes and replace with a dedicated syscall in the next patch --- fs/proc/base.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index ce3465479447..6365a4fea314 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3032,10 +3032,27 @@ static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); } +static int proc_tgid_open(struct inode *inode, struct file *file) +{ + /* grab reference to struct pid and stash the pointer away */ + file->private_data = get_pid(proc_pid(inode)); + return 0; +} + +static int proc_tgid_release(struct inode *inode, struct file *file) +{ + struct pid *pid = file->private_data; + /* drop reference to struct pid */ + put_pid(pid); + return 0; +} + static const struct file_operations proc_tgid_base_operations = { + .open = proc_tgid_open, .read = generic_read_dir, .iterate_shared = proc_tgid_base_readdir, .llseek = generic_file_llseek, + .release = proc_tgid_release, }; static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) From patchwork Mon Nov 19 10:32:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 10688443 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 23FFD13B5 for ; Mon, 19 Nov 2018 10:34:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 13F8D294C4 for ; Mon, 19 Nov 2018 10:34:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 05FE9292B7; Mon, 19 Nov 2018 10:34:06 +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=ham 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 3C2E529708 for ; Mon, 19 Nov 2018 10:34:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728002AbeKSU5A (ORCPT ); Mon, 19 Nov 2018 15:57:00 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:34042 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727983AbeKSU47 (ORCPT ); Mon, 19 Nov 2018 15:56:59 -0500 Received: by mail-pl1-f195.google.com with SMTP id f12-v6so14409785plo.1 for ; Mon, 19 Nov 2018 02:33:47 -0800 (PST) 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=ypnAEQr2pPVfgeHXxl0uTmHsonpkGSyBmX5Kki2tpqc=; b=UY3Ewh34E3OMltOE3MRGyT5QajgQH62bFtxuhu2MdcaUwDEiO3C0TIrgHysgVPq92N cPB5DinoHv41e/1F5xpY6OWsuWs1S3FgWq8oCo1tjRb3EVg4RXa0fXx11GlI9PtoNp+4 K2sLt5ROD/09XsP5Q/r0lHO7TwM55DEKlfl4/k6wRiF9Iv9xURr52gTWqtNEqSZyENAC q0RtV9OfW3C61JzetSanBhhRxRf5MlKvZq1dSrTd4kyLAdFdlnOLKjgkF+lViv+HgLkW idiO85lSPyiTESD8UDsZKFgQ/9eeIUnq5YFed9OviEh2aGhc8HrnwAlaEjkoYXesQ5p7 HQ8w== 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=ypnAEQr2pPVfgeHXxl0uTmHsonpkGSyBmX5Kki2tpqc=; b=tih44WUiyi7jmC/PYv7U7yRkxspFcD19ZdjXvZL/dMP9jGd05IqMKVFIR0md55/jBZ uOBZk5IcuakBcZEsxroDe2TH3ZGRZmzT8SpG3JV/Og9TT2kL6zrBw7PO9ByReoYpXkOp R7o056sLJ7AXx499SKmgWy0jOiaRgWOgVhjR6OggZqdCnnr3yR9ySLyBpo5WQWTE+x/m lNXwPiQwyYnXrC9pSqPT5r3mWx5rQwvSr3TaJcPmEdekgvN9KqfMi6BipRw+PpP8wxXM Y+36gkXGdcPf/DnXoej65DecTlz/ljCih1nprzJrELr8lbLwznWzfvm2DClVu0fqiWtq SwvA== X-Gm-Message-State: AGRZ1gKDxnt/WD9OtQlvwJLm+jy/mievk9i13lo8BrmKZnEduG34T4Ex jY/Zp5WkuEHxXn+lQkz2k/Vf6g== X-Google-Smtp-Source: AJdET5eJSWKr/cCjRL01SE5ntIY8owEi5HuCqcUYm4hrXeOj0yjX8vRS1adQL8OCs5JxC2CyqHktnw== X-Received: by 2002:a17:902:b03:: with SMTP id 3-v6mr21986283plq.233.1542623627048; Mon, 19 Nov 2018 02:33:47 -0800 (PST) Received: from localhost.localdomain ([2404:4404:133a:4500:9d11:de0b:446c:8485]) by smtp.gmail.com with ESMTPSA id d21sm32958139pgv.37.2018.11.19.02.33.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Nov 2018 02:33:46 -0800 (PST) From: Christian Brauner To: ebiederm@xmission.com, linux-kernel@vger.kernel.org Cc: serge@hallyn.com, jannh@google.com, luto@kernel.org, akpm@linux-foundation.org, oleg@redhat.com, cyphar@cyphar.com, viro@zeniv.linux.org.uk, linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, dancol@google.com, timmurray@google.com, linux-man@vger.kernel.org, Christian Brauner , Kees Cook Subject: [PATCH v1 2/2] signal: add procfd_signal() syscall Date: Mon, 19 Nov 2018 11:32:39 +0100 Message-Id: <20181119103241.5229-3-christian@brauner.io> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181119103241.5229-1-christian@brauner.io> References: <20181119103241.5229-1-christian@brauner.io> MIME-Version: 1.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The kill() syscall operates on process identifiers. After a process has exited its pid can be reused by another process. If a caller sends a signal to a reused pid it will end up signaling the wrong process. This issue has often surfaced and there has been a push [1] to address this problem. A prior patch has introduced the ability to get a file descriptor referencing struct pid by opening /proc/. This guarantees a stable handle on a process which can be used to send signals to the referenced process. Discussion has shown that a dedicated syscall is preferable over ioctl()s. Thus, the new syscall procfd_signal() is introduced to solve this problem. It operates on a process file descriptor. The syscall takes an additional siginfo_t and flags argument. If siginfo_t is NULL then procfd_signal() behaves like kill() if it is not NULL it behaves like rt_sigqueueinfo. The flags argument is added to allow for future extensions of this syscall. It currently needs to be passed as 0. With this patch a process can be killed via: #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int ret; char buf[1000]; if (argc < 2) exit(EXIT_FAILURE); ret = snprintf(buf, sizeof(buf), "/proc/%s", argv[1]); if (ret < 0) exit(EXIT_FAILURE); int fd = open(buf, O_DIRECTORY | O_CLOEXEC); if (fd < 0) { printf("%s - Failed to open \"%s\"\n", strerror(errno), buf); exit(EXIT_FAILURE); } ret = syscall(__NR_procfd_signal, fd, SIGKILL, NULL, 0); if (ret < 0) { printf("Failed to send SIGKILL \"%s\"\n", strerror(errno)); close(fd); exit(EXIT_FAILURE); } close(fd); exit(EXIT_SUCCESS); } [1]: https://lkml.org/lkml/2018/11/18/130 Cc: "Eric W. Biederman" Cc: Serge Hallyn Cc: Jann Horn Cc: Kees Cook Cc: Andy Lutomirsky Cc: Andrew Morton Cc: Oleg Nesterov Cc: Aleksa Sarai Cc: Al Viro Signed-off-by: Christian Brauner --- Changelog: v1: - patch introduced --- arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + fs/proc/base.c | 6 ++ include/linux/proc_fs.h | 1 + include/linux/syscalls.h | 2 + kernel/signal.c | 76 ++++++++++++++++++++++++-- 6 files changed, 81 insertions(+), 6 deletions(-) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 3cf7b533b3d1..e637eab883e9 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -398,3 +398,4 @@ 384 i386 arch_prctl sys_arch_prctl __ia32_compat_sys_arch_prctl 385 i386 io_pgetevents sys_io_pgetevents __ia32_compat_sys_io_pgetevents 386 i386 rseq sys_rseq __ia32_sys_rseq +387 i386 procfd_signal sys_procfd_signal __ia32_sys_procfd_signal diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index f0b1709a5ffb..e95f6741ab42 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -343,6 +343,7 @@ 332 common statx __x64_sys_statx 333 common io_pgetevents __x64_sys_io_pgetevents 334 common rseq __x64_sys_rseq +335 common procfd_signal __x64_sys_procfd_signal # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/fs/proc/base.c b/fs/proc/base.c index 6365a4fea314..a12c9de92bd0 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3055,6 +3055,12 @@ static const struct file_operations proc_tgid_base_operations = { .release = proc_tgid_release, }; +bool proc_is_procfd(const struct file *file) +{ + return d_is_dir(file->f_path.dentry) && + (file->f_op == &proc_tgid_base_operations); +} + static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { return proc_pident_lookup(dir, dentry, diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index d0e1f1522a78..2d53a47fba34 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -73,6 +73,7 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo int (*show)(struct seq_file *, void *), proc_write_t write, void *data); +extern bool proc_is_procfd(const struct file *file); #else /* CONFIG_PROC_FS */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 2ac3d13a915b..a5ca8cb84566 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -907,6 +907,8 @@ asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, unsigned mask, struct statx __user *buffer); asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, int flags, uint32_t sig); +asmlinkage long sys_procfd_signal(int fd, int sig, siginfo_t __user *info, + int flags); /* * Architecture-specific system calls diff --git a/kernel/signal.c b/kernel/signal.c index 9a32bc2088c9..e8a8929de710 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -3286,6 +3288,16 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, } #endif +static inline void prepare_kill_siginfo(int sig, struct kernel_siginfo *info) +{ + clear_siginfo(info); + info->si_signo = sig; + info->si_errno = 0; + info->si_code = SI_USER; + info->si_pid = task_tgid_vnr(current); + info->si_uid = from_kuid_munged(current_user_ns(), current_uid()); +} + /** * sys_kill - send a signal to a process * @pid: the PID of the process @@ -3295,16 +3307,68 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) { struct kernel_siginfo info; - clear_siginfo(&info); - info.si_signo = sig; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = task_tgid_vnr(current); - info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); + prepare_kill_siginfo(sig, &info); return kill_something_info(sig, &info, pid); } +/** + * sys_procfd_signal - send a signal to a process through a process file + * descriptor + * @fd: the file descriptor of the process + * @sig: signal to be sent + * @info: the signal info + * @flags: future flags to be passed + */ +SYSCALL_DEFINE4(procfd_signal, int, fd, int, sig, siginfo_t __user *, info, + int, flags) +{ + int ret; + struct pid *pid; + kernel_siginfo_t kinfo; + struct fd f; + + /* Enforce flags be set to 0 until we add an extension. */ + if (flags) + return -EINVAL; + + f = fdget_raw(fd); + if (!f.file) + return -EBADF; + + ret = -EINVAL; + /* Is this a process file descriptor? */ + if (!proc_is_procfd(f.file)) + goto err; + + pid = f.file->private_data; + if (!pid) + goto err; + + if (info) { + ret = __copy_siginfo_from_user(sig, &kinfo, info); + if (unlikely(ret)) + goto err; + /* + * Not even root can pretend to send signals from the kernel. + * Nor can they impersonate a kill()/tgkill(), which adds + * source info. + */ + ret = -EPERM; + if ((kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL) && + (task_pid(current) != pid)) + goto err; + } else { + prepare_kill_siginfo(sig, &kinfo); + } + + ret = kill_pid_info(sig, &kinfo, pid); + +err: + fdput(f); + return ret; +} + static int do_send_specific(pid_t tgid, pid_t pid, int sig, struct kernel_siginfo *info) {