82 lines
2.8 KiB
Diff
82 lines
2.8 KiB
Diff
From 1e0bf201a90df1058f012f12adcc454d4d7c9a69 Mon Sep 17 00:00:00 2001
|
|
From: Christian Brauner <brauner@kernel.org>
|
|
Date: Wed, 2 Jul 2025 11:23:55 +0200
|
|
Subject: anon_inode: rework assertions
|
|
|
|
Making anonymous inodes regular files comes with a lot of risk and
|
|
regression potential as evidenced by a recent hickup in io_uring. We're
|
|
better of continuing to not have them be regular files. Since we have
|
|
S_ANON_INODE we can port all of our assertions easily.
|
|
|
|
Link: https://lore.kernel.org/20250702-work-fixes-v1-1-ff76ea589e33@kernel.org
|
|
Fixes: cfd86ef7e8e7 ("anon_inode: use a proper mode internally")
|
|
Acked-by: Jens Axboe <axboe@kernel.dk>
|
|
Cc: stable@kernel.org
|
|
Reported-by: Jens Axboe <axboe@kernel.dk>
|
|
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
|
---
|
|
fs/exec.c | 9 +++++++--
|
|
fs/libfs.c | 8 +++-----
|
|
fs/namei.c | 2 +-
|
|
3 files changed, 11 insertions(+), 8 deletions(-)
|
|
|
|
--- a/fs/exec.c
|
|
+++ b/fs/exec.c
|
|
@@ -111,6 +111,9 @@ static inline void put_binfmt(struct lin
|
|
|
|
bool path_noexec(const struct path *path)
|
|
{
|
|
+ /* If it's an anonymous inode make sure that we catch any shenanigans. */
|
|
+ VFS_WARN_ON_ONCE(IS_ANON_FILE(d_inode(path->dentry)) &&
|
|
+ !(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC));
|
|
return (path->mnt->mnt_flags & MNT_NOEXEC) ||
|
|
(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
|
|
}
|
|
@@ -894,13 +897,15 @@ static struct file *do_open_execat(int f
|
|
if (IS_ERR(file))
|
|
return file;
|
|
|
|
+ if (path_noexec(&file->f_path))
|
|
+ return ERR_PTR(-EACCES);
|
|
+
|
|
/*
|
|
* In the past the regular type check was here. It moved to may_open() in
|
|
* 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is
|
|
* an invariant that all non-regular files error out before we get here.
|
|
*/
|
|
- if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
|
|
- path_noexec(&file->f_path))
|
|
+ if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)))
|
|
return ERR_PTR(-EACCES);
|
|
|
|
err = exe_file_deny_write_access(file);
|
|
--- a/fs/libfs.c
|
|
+++ b/fs/libfs.c
|
|
@@ -1648,12 +1648,10 @@ struct inode *alloc_anon_inode(struct su
|
|
*/
|
|
inode->i_state = I_DIRTY;
|
|
/*
|
|
- * 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.
|
|
+ * Historically anonymous inodes don't have a type at all and
|
|
+ * userspace has come to rely on this.
|
|
*/
|
|
- inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
|
|
+ inode->i_mode = S_IRUSR | S_IWUSR;
|
|
inode->i_uid = current_fsuid();
|
|
inode->i_gid = current_fsgid();
|
|
inode->i_flags |= S_PRIVATE | S_ANON_INODE;
|
|
--- a/fs/namei.c
|
|
+++ b/fs/namei.c
|
|
@@ -3464,7 +3464,7 @@ static int may_open(struct mnt_idmap *id
|
|
return -EACCES;
|
|
break;
|
|
default:
|
|
- VFS_BUG_ON_INODE(1, inode);
|
|
+ VFS_BUG_ON_INODE(!IS_ANON_FILE(inode), inode);
|
|
}
|
|
|
|
error = inode_permission(idmap, inode, MAY_OPEN | acc_mode);
|