Add the RHEL 211.17.1..211.18.1 backports (1162-1244) from centos-stream-10 and upstream, on top of 211.16.1. Includes the lpfc 14.4.0.x revert batch and the RHEL-only lpfc_nlp_get UAF guard. Bump to 211.18.1.
133 lines
4.6 KiB
Diff
133 lines
4.6 KiB
Diff
From ad4c21b7a2a9f224f45989127541560ccf7cdf53 Mon Sep 17 00:00:00 2001
|
|
From: Rafael Aquini <raquini@redhat.com>
|
|
Date: Mon, 11 May 2026 10:39:34 -0400
|
|
Subject: [PATCH] anon_inode: use a proper mode internally
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-171616
|
|
Conflicts:
|
|
* fs/anon_inodes.c: minor context difference due to RHEL-10 missing unrelated
|
|
commit c1feab95e0b2 ("add a string-to-qstr constructor")
|
|
* fs/internal.h: minor context difference due to RHEL-10 missing unrelated
|
|
commits da06e3c51794 ("fs: don't needlessly acquire f_lock") and
|
|
37c4a9590e1e ("statmount: allow to retrieve idmappings")
|
|
|
|
commit cfd86ef7e8e7b9e015707e46479a6b1de141eed0
|
|
Author: Christian Brauner <brauner@kernel.org>
|
|
Date: Mon Apr 7 11:54:15 2025 +0200
|
|
|
|
anon_inode: use a proper mode internally
|
|
|
|
This allows the VFS to not trip over anonymous inodes and we can add
|
|
asserts based on the mode into the vfs. When we report it to userspace
|
|
we can simply hide the mode to avoid regressions. I've audited all
|
|
direct callers of alloc_anon_inode() and only secretmen overrides i_mode
|
|
and i_op inode operations but it already uses a regular file.
|
|
|
|
Link: https://lore.kernel.org/20250407-work-anon_inode-v1-1-53a44c20d44e@kernel.org
|
|
Fixes: af153bb63a336 ("vfs: catch invalid modes in may_open()")
|
|
Reviewed-by: Jeff Layton <jlayton@kernel.org>
|
|
Cc: stable@vger.kernel.org # all LTS kernels
|
|
Reported-by: syzbot+5d8e79d323a13aa0b248@syzkaller.appspotmail.com
|
|
Closes: https://lore.kernel.org/all/67ed3fb3.050a0220.14623d.0009.GAE@google.com
|
|
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
|
|
|
Signed-off-by: Rafael Aquini <raquini@redhat.com>
|
|
|
|
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
|
|
index 5a070be69922..7c07b22c1d47 100644
|
|
--- a/fs/anon_inodes.c
|
|
+++ b/fs/anon_inodes.c
|
|
@@ -24,9 +24,43 @@
|
|
|
|
#include <linux/uaccess.h>
|
|
|
|
+#include "internal.h"
|
|
+
|
|
static struct vfsmount *anon_inode_mnt __ro_after_init;
|
|
static struct inode *anon_inode_inode __ro_after_init;
|
|
|
|
+/*
|
|
+ * User space expects anonymous inodes to have no file type in st_mode.
|
|
+ *
|
|
+ * In particular, 'lsof' has this legacy logic:
|
|
+ *
|
|
+ * type = s->st_mode & S_IFMT;
|
|
+ * switch (type) {
|
|
+ * ...
|
|
+ * case 0:
|
|
+ * if (!strcmp(p, "anon_inode"))
|
|
+ * Lf->ntype = Ntype = N_ANON_INODE;
|
|
+ *
|
|
+ * to detect our old anon_inode logic.
|
|
+ *
|
|
+ * Rather than mess with our internal sane inode data, just fix it
|
|
+ * up here in getattr() by masking off the format bits.
|
|
+ */
|
|
+int anon_inode_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|
+ struct kstat *stat, u32 request_mask,
|
|
+ unsigned int query_flags)
|
|
+{
|
|
+ struct inode *inode = d_inode(path->dentry);
|
|
+
|
|
+ generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
|
|
+ stat->mode &= ~S_IFMT;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct inode_operations anon_inode_operations = {
|
|
+ .getattr = anon_inode_getattr,
|
|
+};
|
|
+
|
|
/*
|
|
* anon_inodefs_dname() is called from d_path().
|
|
*/
|
|
@@ -78,6 +112,7 @@ struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *n
|
|
if (IS_ERR(inode))
|
|
return inode;
|
|
inode->i_flags &= ~S_PRIVATE;
|
|
+ inode->i_op = &anon_inode_operations;
|
|
error = security_inode_init_security_anon(inode, &qname, context_inode);
|
|
if (error) {
|
|
iput(inode);
|
|
@@ -326,6 +361,7 @@ static int __init anon_inode_init(void)
|
|
anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
|
|
if (IS_ERR(anon_inode_inode))
|
|
panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));
|
|
+ anon_inode_inode->i_op = &anon_inode_operations;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/fs/internal.h b/fs/internal.h
|
|
index b555366c7974..afa926ccee7e 100644
|
|
--- a/fs/internal.h
|
|
+++ b/fs/internal.h
|
|
@@ -338,3 +338,6 @@ static inline bool path_mounted(const struct path *path)
|
|
return path->mnt->mnt_root == path->dentry;
|
|
}
|
|
void file_f_owner_release(struct file *file);
|
|
+int anon_inode_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|
+ struct kstat *stat, u32 request_mask,
|
|
+ unsigned int query_flags);
|
|
diff --git a/fs/libfs.c b/fs/libfs.c
|
|
index 7fd661bb935f..4e9de5aa4d7f 100644
|
|
--- a/fs/libfs.c
|
|
+++ b/fs/libfs.c
|
|
@@ -1651,7 +1651,13 @@ struct inode *alloc_anon_inode(struct super_block *s)
|
|
* that it already _is_ on the dirty list.
|
|
*/
|
|
inode->i_state = I_DIRTY;
|
|
- inode->i_mode = S_IRUSR | S_IWUSR;
|
|
+ /*
|
|
+ * Historically anonymous inodes didn't have a type at all and
|
|
+ * userspace has come to rely on this. Internally they're just
|
|
+ * regular files but S_IFREG is masked off when reporting
|
|
+ * information to userspace.
|
|
+ */
|
|
+ inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
|
|
inode->i_uid = current_fsuid();
|
|
inode->i_gid = current_fsgid();
|
|
inode->i_flags |= S_PRIVATE;
|
|
--
|
|
2.50.1 (Apple Git-155)
|
|
|