From nobody Sun Sep 14 09:55:01 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E95CAC54E94 for ; Wed, 25 Jan 2023 15:31:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236097AbjAYPbR (ORCPT ); Wed, 25 Jan 2023 10:31:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53374 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236080AbjAYPbG (ORCPT ); Wed, 25 Jan 2023 10:31:06 -0500 Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [205.139.111.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 904405999A for ; Wed, 25 Jan 2023 07:31:01 -0800 (PST) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-341-08M_FhysPKuYZMQaiPJFQg-1; Wed, 25 Jan 2023 10:29:31 -0500 X-MC-Unique: 08M_FhysPKuYZMQaiPJFQg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 69DC72804832; Wed, 25 Jan 2023 15:29:31 +0000 (UTC) Received: from comp-core-i7-2640m-0182e6.redhat.com (ovpn-208-16.brq.redhat.com [10.40.208.16]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9A4D72026D76; Wed, 25 Jan 2023 15:29:29 +0000 (UTC) From: Alexey Gladkov To: LKML , containers@lists.linux.dev, linux-fsdevel@vger.kernel.org Cc: Alexey Dobriyan , Al Viro , Andrew Morton , Christian Brauner , Val Cowan Subject: [RFC PATCH v1 3/6] proc: Check that subset= option has been set Date: Wed, 25 Jan 2023 16:28:50 +0100 Message-Id: <346dd92ea62d8469416e12ab71b67b775eb2494b.1674660533.git.legion@kernel.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Refactor subset option. Before this option had only one value - pid. Now another meaning has appeared and therefore their combinations are possible. Signed-off-by: Alexey Gladkov --- fs/proc/generic.c | 4 ++-- fs/proc/inode.c | 16 +++++++++++++--- fs/proc/internal.h | 6 ------ fs/proc/proc_allowlist.c | 22 ++++------------------ fs/proc/root.c | 27 +++++++++++++++++++-------- include/linux/proc_fs.h | 15 +++++---------- 6 files changed, 43 insertions(+), 47 deletions(-) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index d4c8589987e7..71a38b275814 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -269,7 +269,7 @@ struct dentry *proc_lookup(struct inode *dir, struct de= ntry *dentry, { struct proc_fs_info *fs_info =3D proc_sb_info(dir->i_sb); =20 - if (fs_info->pidonly =3D=3D PROC_PIDONLY_ON && !proc_has_allowlist(fs_inf= o)) + if ((fs_info->subset & PROC_SUBSET_PIDONLY) && !(fs_info->subset & PROC_S= UBSET_ALLOWLIST)) return ERR_PTR(-ENOENT); =20 return proc_lookup_de(dir, dentry, PDE(dir)); @@ -334,7 +334,7 @@ int proc_readdir(struct file *file, struct dir_context = *ctx) struct inode *inode =3D file_inode(file); struct proc_fs_info *fs_info =3D proc_sb_info(inode->i_sb); =20 - if (fs_info->pidonly =3D=3D PROC_PIDONLY_ON && !proc_has_allowlist(fs_inf= o)) + if ((fs_info->subset & PROC_SUBSET_PIDONLY) && !(fs_info->subset & PROC_S= UBSET_ALLOWLIST)) return 1; =20 return proc_readdir_de(file, ctx, PDE(inode)); diff --git a/fs/proc/inode.c b/fs/proc/inode.c index f495fdb39151..4c486237a16b 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -184,9 +184,19 @@ static int proc_show_options(struct seq_file *seq, str= uct dentry *root) seq_printf(seq, ",gid=3D%u", from_kgid_munged(&init_user_ns, fs_info->pi= d_gid)); if (fs_info->hide_pid !=3D HIDEPID_OFF) seq_printf(seq, ",hidepid=3D%s", hidepid2str(fs_info->hide_pid)); - if (fs_info->pidonly !=3D PROC_PIDONLY_OFF) - seq_printf(seq, ",subset=3Dpid"); - + if (fs_info->subset & PROC_SUBSET_SET) { + bool need_delim =3D false; + seq_printf(seq, ",subset=3D"); + if (fs_info->subset & PROC_SUBSET_PIDONLY) { + seq_printf(seq, "pid"); + need_delim =3D true; + } + if (fs_info->subset & PROC_SUBSET_ALLOWLIST) { + if (need_delim) + seq_printf(seq, "+"); + seq_printf(seq, "allowlist"); + } + } return 0; } =20 diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 999d105f6f96..3e1b1f29b13d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -334,14 +334,8 @@ static inline void pde_force_lookup(struct proc_dir_en= try *pde) * proc_allowlist.c */ #ifdef CONFIG_PROC_ALLOW_LIST -extern bool proc_has_allowlist(struct proc_fs_info *); extern bool proc_pde_access_allowed(struct proc_fs_info *, struct proc_dir= _entry *); #else -static inline bool proc_has_allowlist(struct proc_fs_info *fs_info) -{ - return false; -} - static inline bool proc_pde_access_allowed(struct proc_fs_info *fs_info, s= truct proc_dir_entry *pde) { return true; diff --git a/fs/proc/proc_allowlist.c b/fs/proc/proc_allowlist.c index b38e11b04199..2153acb8e467 100644 --- a/fs/proc/proc_allowlist.c +++ b/fs/proc/proc_allowlist.c @@ -16,38 +16,24 @@ #define FILE_SEQFILE(f) ((struct seq_file *)((f)->private_data)) #define FILE_DATA(f) (FILE_SEQFILE(f)->private) =20 -bool proc_has_allowlist(struct proc_fs_info *fs_info) -{ - bool ret; - unsigned long flags; - - read_lock_irqsave(&fs_info->allowlist_lock, flags); - ret =3D (fs_info->allowlist =3D=3D NULL); - read_unlock_irqrestore(&fs_info->allowlist_lock, flags); - - return ret; -} - bool proc_pde_access_allowed(struct proc_fs_info *fs_info, struct proc_dir= _entry *de) { bool ret =3D false; char *ptr; unsigned long flags; =20 - read_lock_irqsave(&fs_info->allowlist_lock, flags); - - if (!fs_info->allowlist) { - read_unlock_irqrestore(&fs_info->allowlist_lock, flags); - + if (!(fs_info->subset & PROC_SUBSET_ALLOWLIST)) { if (!pde_is_allowlist(de)) ret =3D true; =20 return ret; } =20 + read_lock_irqsave(&fs_info->allowlist_lock, flags); + ptr =3D fs_info->allowlist; =20 - while (*ptr !=3D '\0') { + while (ptr && *ptr !=3D '\0') { struct proc_dir_entry *pde; char *sep, *end; size_t len, pathlen; diff --git a/fs/proc/root.c b/fs/proc/root.c index 1564f5cd118d..6e9b125072e5 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -31,8 +31,7 @@ struct proc_fs_context { unsigned int mask; enum proc_hidepid hidepid; int gid; - enum proc_pidonly pidonly; - enum proc_allowlist allowlist; + unsigned int subset; }; =20 enum proc_param { @@ -91,6 +90,8 @@ static int proc_parse_subset_param(struct fs_context *fc,= char *value) { struct proc_fs_context *ctx =3D fc->fs_private; =20 + ctx->subset |=3D PROC_SUBSET_SET; + while (value) { char *ptr =3D strchr(value, '+'); =20 @@ -99,10 +100,10 @@ static int proc_parse_subset_param(struct fs_context *= fc, char *value) =20 if (*value !=3D '\0') { if (!strcmp(value, "pid")) { - ctx->pidonly =3D PROC_PIDONLY_ON; + ctx->subset |=3D PROC_SUBSET_PIDONLY; } else if (IS_ENABLED(CONFIG_PROC_ALLOW_LIST) && !strcmp(value, "allowlist")) { - ctx->allowlist =3D PROC_ALLOWLIST_ON; + ctx->subset |=3D PROC_SUBSET_ALLOWLIST; } else { return invalf(fc, "proc: unsupported subset option - %s\n", value); } @@ -169,8 +170,8 @@ static void proc_apply_options(struct proc_fs_info *fs_= info, if (ctx->mask & (1 << Opt_hidepid)) fs_info->hide_pid =3D ctx->hidepid; if (ctx->mask & (1 << Opt_subset)) { - fs_info->pidonly =3D ctx->pidonly; - if (ctx->allowlist =3D=3D PROC_ALLOWLIST_ON) { + fs_info->subset =3D ctx->subset; + if (ctx->subset & PROC_SUBSET_ALLOWLIST) { fs_info->allowlist =3D proc_init_allowlist(); } else { fs_info->allowlist =3D NULL; @@ -346,14 +347,21 @@ static int proc_root_getattr(struct user_namespace *m= nt_userns, =20 static struct dentry *proc_root_lookup(struct inode * dir, struct dentry *= dentry, unsigned int flags) { - if (!proc_pid_lookup(dentry, flags)) - return NULL; + struct proc_fs_info *fs_info =3D proc_sb_info(dir->i_sb); + + if (!(fs_info->subset & PROC_SUBSET_SET) || (fs_info->subset & PROC_SUBSE= T_PIDONLY)) { + if (!proc_pid_lookup(dentry, flags)) + return NULL; + } =20 return proc_lookup(dir, dentry, flags); } =20 static int proc_root_readdir(struct file *file, struct dir_context *ctx) { + struct inode *inode =3D file_inode(file); + struct proc_fs_info *fs_info =3D proc_sb_info(inode->i_sb); + if (ctx->pos < FIRST_PROCESS_ENTRY) { int error =3D proc_readdir(file, ctx); if (unlikely(error <=3D 0)) @@ -361,6 +369,9 @@ static int proc_root_readdir(struct file *file, struct = dir_context *ctx) ctx->pos =3D FIRST_PROCESS_ENTRY; } =20 + if ((fs_info->subset & PROC_SUBSET_SET) && !(fs_info->subset & PROC_SUBSE= T_PIDONLY)) + return 1; + return proc_pid_readdir(file, ctx); } =20 diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 9105d75aeb18..08d0d0ae6e42 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -53,15 +53,10 @@ enum proc_hidepid { HIDEPID_NOT_PTRACEABLE =3D 4, /* Limit pids to only ptraceable pids */ }; =20 -/* definitions for proc mount option pidonly */ -enum proc_pidonly { - PROC_PIDONLY_OFF =3D 0, - PROC_PIDONLY_ON =3D 1, -}; - -enum proc_allowlist { - PROC_ALLOWLIST_OFF =3D 0, - PROC_ALLOWLIST_ON =3D 1, +enum proc_subset { + PROC_SUBSET_SET =3D (1 << 0), + PROC_SUBSET_PIDONLY =3D (1 << 1), + PROC_SUBSET_ALLOWLIST =3D (1 << 2), }; =20 struct proc_fs_info { @@ -70,7 +65,7 @@ struct proc_fs_info { struct dentry *proc_thread_self; /* For /proc/thread-self */ kgid_t pid_gid; enum proc_hidepid hide_pid; - enum proc_pidonly pidonly; + unsigned int subset; char *allowlist; rwlock_t allowlist_lock; }; --=20 2.33.6