81 lines
2.3 KiB
Diff
81 lines
2.3 KiB
Diff
From ea4199112ae6d8da866417f50e035be01488c502 Mon Sep 17 00:00:00 2001
|
|
From: Christian Brauner <brauner@kernel.org>
|
|
Date: Mon, 7 Apr 2025 11:54:17 +0200
|
|
Subject: anon_inode: explicitly block ->setattr()
|
|
|
|
It is currently possible to change the mode and owner of the single
|
|
anonymous inode in the kernel:
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ret, sfd;
|
|
sigset_t mask;
|
|
struct signalfd_siginfo fdsi;
|
|
|
|
sigemptyset(&mask);
|
|
sigaddset(&mask, SIGINT);
|
|
sigaddset(&mask, SIGQUIT);
|
|
|
|
ret = sigprocmask(SIG_BLOCK, &mask, NULL);
|
|
if (ret < 0)
|
|
_exit(1);
|
|
|
|
sfd = signalfd(-1, &mask, 0);
|
|
if (sfd < 0)
|
|
_exit(2);
|
|
|
|
ret = fchown(sfd, 5555, 5555);
|
|
if (ret < 0)
|
|
_exit(3);
|
|
|
|
ret = fchmod(sfd, 0777);
|
|
if (ret < 0)
|
|
_exit(3);
|
|
|
|
_exit(4);
|
|
}
|
|
|
|
This is a bug. It's not really a meaningful one because anonymous inodes
|
|
don't really figure into path lookup and they cannot be reopened via
|
|
/proc/<pid>/fd/<nr> and can't be used for lookup itself. So they can
|
|
only ever serve as direct references.
|
|
|
|
But it is still completely bogus to allow the mode and ownership or any
|
|
of the properties of the anonymous inode to be changed. Block this!
|
|
|
|
Link: https://lore.kernel.org/20250407-work-anon_inode-v1-3-53a44c20d44e@kernel.org
|
|
Reviewed-by: Jeff Layton <jlayton@kernel.org>
|
|
Cc: stable@vger.kernel.org # all LTS kernels
|
|
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
|
---
|
|
fs/anon_inodes.c | 7 +++++++
|
|
fs/internal.h | 2 ++
|
|
2 files changed, 9 insertions(+)
|
|
|
|
--- a/fs/anon_inodes.c
|
|
+++ b/fs/anon_inodes.c
|
|
@@ -57,8 +57,15 @@ int anon_inode_getattr(struct mnt_idmap
|
|
return 0;
|
|
}
|
|
|
|
+int anon_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
|
+ struct iattr *attr)
|
|
+{
|
|
+ return -EOPNOTSUPP;
|
|
+}
|
|
+
|
|
static const struct inode_operations anon_inode_operations = {
|
|
.getattr = anon_inode_getattr,
|
|
+ .setattr = anon_inode_setattr,
|
|
};
|
|
|
|
/*
|
|
--- a/fs/internal.h
|
|
+++ b/fs/internal.h
|
|
@@ -346,3 +346,5 @@ int statmount_mnt_idmap(struct mnt_idmap
|
|
int anon_inode_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|
struct kstat *stat, u32 request_mask,
|
|
unsigned int query_flags);
|
|
+int anon_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
|
+ struct iattr *attr);
|