commit:     84702fafb1c2c0a1eaf741847959d41c105b7940
Author:     Arisu Tachibana <alicef <AT> gentoo <DOT> org>
AuthorDate: Thu Aug 28 13:53:40 2025 +0000
Commit:     Arisu Tachibana <alicef <AT> gentoo <DOT> org>
CommitDate: Thu Aug 28 13:53:40 2025 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=84702faf

Add proc: fix missing pde_set_flags() for net proc files

Signed-off-by: Arisu Tachibana <alicef <AT> gentoo.org>

 0000_README                                        |   4 +
 ..._missing_pde_set_flags_for_net_proc_files.patch | 164 +++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/0000_README b/0000_README
index bef879a3..860bf8f3 100644
--- a/0000_README
+++ b/0000_README
@@ -235,6 +235,10 @@ Patch:  1730_parisc-Disable-prctl.patch
 From:   https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
 Desc:   prctl: Temporarily disable prctl(PR_SET_MDWE) on parisc
 
+Patch:  1800_proc_fix_missing_pde_set_flags_for_net_proc_files.patch
+From:   
https://lore.kernel.org/all/[email protected]/
+Desc:   proc: fix missing pde_set_flags() for net proc files
+
 Patch:  2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
 From:   
https://lore.kernel.org/linux-bluetooth/[email protected]/raw
 Desc:   Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. 
See bug #686758

diff --git a/1800_proc_fix_missing_pde_set_flags_for_net_proc_files.patch 
b/1800_proc_fix_missing_pde_set_flags_for_net_proc_files.patch
new file mode 100644
index 00000000..d42d9d07
--- /dev/null
+++ b/1800_proc_fix_missing_pde_set_flags_for_net_proc_files.patch
@@ -0,0 +1,164 @@
+From mboxrd@z Thu Jan  1 00:00:00 1970
+Received: from mta21.hihonor.com (mta21.honor.com [81.70.160.142])
+       (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
+       (No client certificate requested)
+       by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D18E308F18
+       for <[email protected]>; Thu, 21 Aug 2025 10:58:11 +0000 (UTC)
+Authentication-Results: smtp.subspace.kernel.org; arc=none 
smtp.client-ip=81.70.160.142
+ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
+       t=1755773896; cv=none; 
b=uf0SHAKs+B4CVnXckwKblCkTaQzofZ/iIeFqe1l9Igj3XxpGpi8FFZKzT1q5rOZYOSOY9gOoTGx+Z8Zy+I08SQQzgoJxttAoeEklbFCCKFPTRLRQthyO+J1EEf6vI2T1GLJZUhHTthgDrKCTPFbrIf2oGmPkSrJHH+STidm3krA=
+ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org;
+       s=arc-20240116; t=1755773896; c=relaxed/simple;
+       bh=l3jMKIk6lYIIzI4SccsDJUmeup9tuX38D/XM4qedxQU=;
+       h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; 
b=k9YALQ1oS/qWu7MXOxgISf6DxjFqOtw8eXno5JFk+wgaTBuvUyqz5D0hD+ir4kHDBBIz6MHiHUQixuW774vBGzujNekFLweIbzdfYn7osOYNvr8bD80Qam+1D1B5DM0OtVAEBNN8YmkB0RY49sa91xx9G3U5fqJoKOHT+28M+/0=
+ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none 
dis=none) header.from=honor.com; spf=pass smtp.mailfrom=honor.com; arc=none 
smtp.client-ip=81.70.160.142
+Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) 
header.from=honor.com
+Authentication-Results: smtp.subspace.kernel.org; spf=pass 
smtp.mailfrom=honor.com
+Received: from w011.hihonor.com (unknown [10.68.20.122])
+       by mta21.hihonor.com (SkyGuard) with ESMTPS id 4c70fC2v03zYl7h7;
+       Thu, 21 Aug 2025 18:57:55 +0800 (CST)
+Received: from a011.hihonor.com (10.68.31.243) by w011.hihonor.com
+ (10.68.20.122) with Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 21 Aug
+ 2025 18:58:08 +0800
+Received: from localhost.localdomain (10.144.23.14) by a011.hihonor.com
+ (10.68.31.243) with Microsoft SMTP Server (version=TLS1_2,
+ cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 21 Aug
+ 2025 18:58:07 +0800
+From: wangzijie <[email protected]>
+To: <[email protected]>, <[email protected]>,
+       <[email protected]>, <[email protected]>,
+       <[email protected]>, <[email protected]>, <[email protected]>,
+       <[email protected]>, <[email protected]>
+CC: <[email protected]>, <[email protected]>,
+       <[email protected]>, <[email protected]>, wangzijie
+       <[email protected]>
+Subject: [PATCH v3] proc: fix missing pde_set_flags() for net proc files
+Date: Thu, 21 Aug 2025 18:58:06 +0800
+Message-ID: <[email protected]>
+X-Mailer: git-send-email 2.25.1
+Precedence: bulk
+X-Mailing-List: [email protected]
+List-Id: <regressions.lists.linux.dev>
+List-Subscribe: <mailto:[email protected]>
+List-Unsubscribe: <mailto:[email protected]>
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain
+X-ClientProxiedBy: w002.hihonor.com (10.68.28.120) To a011.hihonor.com
+ (10.68.31.243)
+
+To avoid potential UAF issues during module removal races, we use 
pde_set_flags()
+to save proc_ops flags in PDE itself before proc_register(), and then use
+pde_has_proc_*() helpers instead of directly dereferencing pde->proc_ops->*.
+
+However, the pde_set_flags() call was missing when creating net related proc 
files.
+This omission caused incorrect behavior which FMODE_LSEEK was being cleared
+inappropriately in proc_reg_open() for net proc files. Lars reported it in 
this link[1].
+
+Fix this by ensuring pde_set_flags() is called when register proc entry, and 
add
+NULL check for proc_ops in pde_set_flags().
+
+[1]: https://lore.kernel.org/all/[email protected]/
+
+Fixes: ff7ec8dc1b64 ("proc: use the same treatment to check proc_lseek as ones 
for proc_read_iter et.al")
+Cc: [email protected]
+Reported-by: Lars Wendler <[email protected]>
+Signed-off-by: wangzijie <[email protected]>
+---
+v3:
+- followed by Christian's suggestion to stash pde->proc_ops in a local const 
variable
+v2:
+- followed by Jiri's suggestion to refractor code and reformat commit message
+---
+ fs/proc/generic.c | 38 +++++++++++++++++++++-----------------
+ 1 file changed, 21 insertions(+), 17 deletions(-)
+
+diff --git a/fs/proc/generic.c b/fs/proc/generic.c
+index 76e800e38..bd0c099cf 100644
+--- a/fs/proc/generic.c
++++ b/fs/proc/generic.c
+@@ -367,6 +367,25 @@ static const struct inode_operations 
proc_dir_inode_operations = {
+       .setattr        = proc_notify_change,
+ };
+ 
++static void pde_set_flags(struct proc_dir_entry *pde)
++{
++      const struct proc_ops *proc_ops = pde->proc_ops;
++
++      if (!proc_ops)
++              return;
++
++      if (proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
++              pde->flags |= PROC_ENTRY_PERMANENT;
++      if (proc_ops->proc_read_iter)
++              pde->flags |= PROC_ENTRY_proc_read_iter;
++#ifdef CONFIG_COMPAT
++      if (proc_ops->proc_compat_ioctl)
++              pde->flags |= PROC_ENTRY_proc_compat_ioctl;
++#endif
++      if (proc_ops->proc_lseek)
++              pde->flags |= PROC_ENTRY_proc_lseek;
++}
++
+ /* returns the registered entry, or frees dp and returns NULL on failure */
+ struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
+               struct proc_dir_entry *dp)
+@@ -374,6 +393,8 @@ struct proc_dir_entry *proc_register(struct proc_dir_entry 
*dir,
+       if (proc_alloc_inum(&dp->low_ino))
+               goto out_free_entry;
+ 
++      pde_set_flags(dp);
++
+       write_lock(&proc_subdir_lock);
+       dp->parent = dir;
+       if (pde_subdir_insert(dir, dp) == false) {
+@@ -561,20 +582,6 @@ struct proc_dir_entry *proc_create_reg(const char *name, 
umode_t mode,
+       return p;
+ }
+ 
+-static void pde_set_flags(struct proc_dir_entry *pde)
+-{
+-      if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
+-              pde->flags |= PROC_ENTRY_PERMANENT;
+-      if (pde->proc_ops->proc_read_iter)
+-              pde->flags |= PROC_ENTRY_proc_read_iter;
+-#ifdef CONFIG_COMPAT
+-      if (pde->proc_ops->proc_compat_ioctl)
+-              pde->flags |= PROC_ENTRY_proc_compat_ioctl;
+-#endif
+-      if (pde->proc_ops->proc_lseek)
+-              pde->flags |= PROC_ENTRY_proc_lseek;
+-}
+-
+ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
+               struct proc_dir_entry *parent,
+               const struct proc_ops *proc_ops, void *data)
+@@ -585,7 +592,6 @@ struct proc_dir_entry *proc_create_data(const char *name, 
umode_t mode,
+       if (!p)
+               return NULL;
+       p->proc_ops = proc_ops;
+-      pde_set_flags(p);
+       return proc_register(parent, p);
+ }
+ EXPORT_SYMBOL(proc_create_data);
+@@ -636,7 +642,6 @@ struct proc_dir_entry *proc_create_seq_private(const char 
*name, umode_t mode,
+       p->proc_ops = &proc_seq_ops;
+       p->seq_ops = ops;
+       p->state_size = state_size;
+-      pde_set_flags(p);
+       return proc_register(parent, p);
+ }
+ EXPORT_SYMBOL(proc_create_seq_private);
+@@ -667,7 +672,6 @@ struct proc_dir_entry *proc_create_single_data(const char 
*name, umode_t mode,
+               return NULL;
+       p->proc_ops = &proc_single_ops;
+       p->single_show = show;
+-      pde_set_flags(p);
+       return proc_register(parent, p);
+ }
+ EXPORT_SYMBOL(proc_create_single_data);
+-- 
+2.25.1
+
+

Reply via email to