From patchwork Thu Mar 30 15:22:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Djalal Harouni X-Patchwork-Id: 9654459 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1EE4C602BD for ; Thu, 30 Mar 2017 15:24:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 113E92852B for ; Thu, 30 Mar 2017 15:24:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 059BB28555; Thu, 30 Mar 2017 15:24:09 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID 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 8B4C12852B for ; Thu, 30 Mar 2017 15:24:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933524AbdC3PXm (ORCPT ); Thu, 30 Mar 2017 11:23:42 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:34123 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934248AbdC3PXc (ORCPT ); Thu, 30 Mar 2017 11:23:32 -0400 Received: by mail-wr0-f193.google.com with SMTP id w43so13080531wrb.1; Thu, 30 Mar 2017 08:23:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MgklDVuPm80batJp6xMyo/vamVZgunVEHpY1F9YGRKY=; b=J3KS+syBnukuo0Ccq7muspbQmnTcIBH8nqikEuoBfBoKuSS5ujuYCQDum5tQTH2gsP f30MQI3qhWnzC2ya82OslI+SGnrX2Sdn34Nz4EdysiYsHma+GlLj//AmkHb0W0dRuu5E PIsdTkVtj+8dRgb/RuRIKmPFqoth7KevLCnhZHCbN6vXEtySXpiXiYzSwUkFlTIKU718 rLA5GvfEfD7S3uW+qM5DHVuwCJ5IyAwJR26EVhBbd7abSxHFKqJnJq0bsQJ2TlmEtF+4 PiTQxVDmn7WSFxotBiHyRtJlF2qRPLfzR2NdToDDCY4ZdEuiV6VDYui5otSD/fdmNY5Y tUIg== 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; bh=MgklDVuPm80batJp6xMyo/vamVZgunVEHpY1F9YGRKY=; b=F0ulPYjaDcIehPMdcBfh56EMyKEQw18KivGQZan8wEXcejDxIctrmdQqRN59PVxLlH lO2ueItawmsspMneXBaDL8AIa4WfossIGpBI5YCge3UVgonAIixxSOrh84rQRwWck175 3aUGew4dXvaHMQ5gUQgxNbPpBybFQUjrVJhmgFbK5scgeq7ooV/f6+bQ7boBrtWZFQXs ZUrUQg2JPtc42r7XuA0BPgpvqF4oU4f5ug0gpxrWtqWQWwTTKD2eBh1qnD5S0arK9+EK cLRKf0NDBDCLcztu5/MGidHipUYNDRzgA5HvyBuopOfnqKfVi85reXxqruMwceamVR9c 6UnQ== X-Gm-Message-State: AFeK/H13IWxRFlDzrmbRYtkK9QzFXcdVIVqbcJVcGyWKIN/jxEt9+MvXt51GBB+0tll6Dw== X-Received: by 10.223.165.66 with SMTP id j2mr248295wrb.157.1490887409841; Thu, 30 Mar 2017 08:23:29 -0700 (PDT) Received: from dztty2.localdomain (ip5b41f4e7.dynamic.kabel-deutschland.de. [91.65.244.231]) by smtp.gmail.com with ESMTPSA id u15sm3188896wrc.10.2017.03.30.08.23.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 30 Mar 2017 08:23:29 -0700 (PDT) From: Djalal Harouni To: Linux Kernel Mailing List , Andy Lutomirski , Alexey Gladkov , Al Viro , , Andrew Morton Cc: Linux API , , Oleg Nesterov , Pavel Emelyanov , James Bottomley , Kees Cook , Dongsu Park , Ingo Molnar , Michal Hocko , Alexey Dobriyan , kernel-hardening@lists.openwall.com, linux-security-module@vger.kernel.org, Djalal Harouni Subject: [PATCH RFC 3/4] proc: support mounting new procfs instances inside same pid namespace Date: Thu, 30 Mar 2017 17:22:58 +0200 Message-Id: <1490887379-25880-4-git-send-email-tixxdz@gmail.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1490887379-25880-1-git-send-email-tixxdz@gmail.com> References: <1490887379-25880-1-git-send-email-tixxdz@gmail.com> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP This patch adds support for 'unshare' mount option to have multiple separated procfs inside the same pid namespace. This allows to solve lot of problem for containers and their specific use cases. Signed-off-by: Djalal Harouni --- fs/proc/generic.c | 10 +++++++++ fs/proc/inode.c | 3 +++ fs/proc/root.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/proc_fs.h | 12 ++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 7e5e419..7ae5377 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -52,6 +52,11 @@ void proc_fs_set_pid_gid(struct proc_fs_info *fs_info, kgid_t gid) fs_info->pid_gid = gid; } +void proc_fs_set_unshare(struct proc_fs_info *fs_info, int version) +{ + fs_info->version = version; +} + int proc_fs_get_hide_pid(struct proc_fs_info *fs_info) { /* For backward compatibility */ @@ -70,6 +75,11 @@ kgid_t proc_fs_get_pid_gid(struct proc_fs_info *fs_info) return fs_info->pid_gid; } +int proc_fs_get_unshare(struct proc_fs_info *fs_info) +{ + return fs_info->version; +} + static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) { if (len < de->namelen) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index ca47a0a..5f7557d 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -111,6 +111,9 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root) if (pid->hide_pid != HIDEPID_OFF) seq_printf(seq, ",hidepid=%u", pid->hide_pid); + if (proc_fs_get_unshare(fs_info) == PROC_FS_V2) + seq_printf(seq, ",unshare"); + return 0; } diff --git a/fs/proc/root.c b/fs/proc/root.c index 6a96c02..7a8f425 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -27,15 +27,52 @@ #include "internal.h" enum { - Opt_gid, Opt_hidepid, Opt_err, + Opt_gid, Opt_hidepid, Opt_unshare, Opt_err, }; static const match_table_t tokens = { {Opt_hidepid, "hidepid=%u"}, {Opt_gid, "gid=%u"}, + {Opt_unshare, "unshare"}, {Opt_err, NULL}, }; +/* We only parse 'unshare' option here */ +int proc_parse_early_options(char *options, struct proc_fs_info *fs_info) +{ + char *p, *opts, *orig; + substring_t args[MAX_OPT_ARGS]; + + if (!options) + return 0; + + opts = kstrdup(options, GFP_KERNEL); + if (!opts) + return -ENOMEM; + + orig = opts; + + while ((p = strsep(&opts, ",")) != NULL) { + int token; + + if (!*p) + continue; + + token = match_token(p, tokens, args); + switch (token) { + case Opt_unshare: + pr_info("proc: mounting a new procfs instance "); + proc_fs_set_unshare(fs_info, PROC_FS_V2); + break; + default: + break; + } + } + + kfree(orig); + return 0; +} + int proc_parse_options(char *options, struct proc_fs_info *fs_info) { char *p; @@ -70,6 +107,8 @@ int proc_parse_options(char *options, struct proc_fs_info *fs_info) } proc_fs_set_hide_pid(fs_info, option); break; + case Opt_unshare: + break; default: pr_err("proc: unrecognized mount option \"%s\" " "or missing value\n", p); @@ -82,9 +121,19 @@ int proc_parse_options(char *options, struct proc_fs_info *fs_info) int proc_remount(struct super_block *sb, int *flags, char *data) { + int error, version; struct proc_fs_info *fs_info = proc_sb(sb); + version = proc_fs_get_unshare(fs_info); + sync_filesystem(sb); + + if (version == PROC_FS_V2) { + error = proc_parse_early_options(data, fs_info); + if (error < 0) + return error; + } + return !proc_parse_options(data, fs_info); } @@ -122,15 +171,21 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, if (!fs_info) return ERR_PTR(-ENOMEM); + /* Set it as early as possible */ + proc_fs_set_unshare(fs_info, PROC_FS_V1); + if (flags & MS_KERNMOUNT) { ns = data; data = NULL; } else { + error = proc_parse_early_options(data, fs_info); + if (error < 0) + goto error_fs_info; + ns = task_active_pid_ns(current); } fs_info->pid_ns = ns; - fs_info->version = PROC_FS_V1; fs_info->hide_pid = HIDEPID_OFF; fs_info->pid_gid = GLOBAL_ROOT_GID; refcount_set(&fs_info->users, 1); diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index c23299d..e3a78a5 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -31,8 +31,11 @@ extern void proc_fs_set_hide_pid(struct proc_fs_info *fs_info, int hide_pid); extern void proc_fs_set_pid_gid(struct proc_fs_info *fs_info, kgid_t gid); +extern void proc_fs_set_unshare(struct proc_fs_info *fs_info, int version); + extern int proc_fs_get_hide_pid(struct proc_fs_info *fs_info); extern kgid_t proc_fs_get_pid_gid(struct proc_fs_info *fs_info); +extern int proc_fs_get_unshare(struct proc_fs_info *fs_info); extern void proc_root_init(void); extern void proc_flush_task(struct task_struct *); @@ -84,6 +87,10 @@ static inline void proc_fs_set_hide_pid(struct proc_fs_info *fs_info, int hide_p { } +static inline void proc_fs_set_unshare(struct proc_fs_info *fs_info, int version) +{ +} + static inline void proc_fs_set_pid_gid(struct proc_info_fs *fs_info, kgid_t gid) { } @@ -98,6 +105,11 @@ extern kgid_t proc_fs_get_pid_gid(struct proc_fs_info *fs_info) return GLOBAL_ROOT_GID; } +static inline int proc_fs_get_unshare(struct proc_fs_info *fs_info) +{ + return PROC_FS_V1; +} + extern inline struct proc_fs_info *proc_sb(struct super_block *sb) { return NULL;} static inline struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent,const char *dest) { return NULL;}