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: 9654451 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 35E6D602BD for ; Thu, 30 Mar 2017 15:23:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2888C2852B for ; Thu, 30 Mar 2017 15:23:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1D39D28555; Thu, 30 Mar 2017 15:23:56 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 03A672852B for ; Thu, 30 Mar 2017 15:23:54 +0000 (UTC) Received: (qmail 17997 invoked by uid 550); 30 Mar 2017 15:23:42 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 17881 invoked from network); 30 Mar 2017 15:23:41 -0000 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=Emf04mxGEnyEoozRx1Q7hzGevYYJAAE5yuFoTfpwi9oH3ld0uBvs9tDRWn0uvF3Gwg klbRd5mtGbeNMjjAYzktgVHuSO5gZrTsnuAR2eosVtObB9V92DV2BCr0YR71IEO2Fp9F PWSyEGmOC/UmE+rtx59E5SsfqYPE238kH4tpr3XOfslX/lVJXZGpKd00/cLxkvP+HJwd lOmTQDlYyMAK+SlxWwnxLo295zzbmvpgrtQ/hrCx4MwBD50sC3BbjrCJpBsDNJmksjMD Gq74/3GCifporsyhOrQFwB5G+6hNf1Gf4hzOmhXb2rQTwBmjDU/OZ/Cm5/dmTXvl3ZpT 3sJQ== X-Gm-Message-State: AFeK/H0lWNiUY/Kg91N0s89RE1MD6IBqO1C3OwgpaDhDxcEIO891nKYdZujdkyr1jca4Fw== X-Received: by 10.223.165.66 with SMTP id j2mr248295wrb.157.1490887409841; 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 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> Subject: [kernel-hardening] [PATCH RFC 3/4] proc: support mounting new procfs instances inside same pid namespace 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;}