190 lines
5.3 KiB
Diff
190 lines
5.3 KiB
Diff
From 5c28f6ec073077ce1239652c7a74555904eb0577 Mon Sep 17 00:00:00 2001
|
|
From: Ondrej Mosnacek <omosnace@redhat.com>
|
|
Date: Wed, 3 Jun 2026 10:51:41 +0200
|
|
Subject: [PATCH] fs: factor out backing_file_splice_{read,write}() helpers
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-179443
|
|
CVE: CVE-2026-46054
|
|
|
|
commit 9b7e9e2f5d5c3d079ec46bc71b114012e362ea6e
|
|
Author: Amir Goldstein <amir73il@gmail.com>
|
|
Date: Fri Oct 13 12:13:12 2023 +0300
|
|
|
|
fs: factor out backing_file_splice_{read,write}() helpers
|
|
|
|
There is not much in those helpers, but it makes sense to have them
|
|
logically next to the backing_file_{read,write}_iter() helpers as they
|
|
may grow more common logic in the future.
|
|
|
|
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
|
|
|
|
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
|
|
|
|
diff --git a/fs/backing-file.c b/fs/backing-file.c
|
|
index 6d915a45e288..5cc411566ce0 100644
|
|
--- a/fs/backing-file.c
|
|
+++ b/fs/backing-file.c
|
|
@@ -10,6 +10,7 @@
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/backing-file.h>
|
|
+#include <linux/splice.h>
|
|
|
|
#include "internal.h"
|
|
|
|
@@ -248,6 +249,56 @@ ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
|
|
}
|
|
EXPORT_SYMBOL_GPL(backing_file_write_iter);
|
|
|
|
+ssize_t backing_file_splice_read(struct file *in, loff_t *ppos,
|
|
+ struct pipe_inode_info *pipe, size_t len,
|
|
+ unsigned int flags,
|
|
+ struct backing_file_ctx *ctx)
|
|
+{
|
|
+ const struct cred *old_cred;
|
|
+ ssize_t ret;
|
|
+
|
|
+ if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING)))
|
|
+ return -EIO;
|
|
+
|
|
+ old_cred = override_creds(ctx->cred);
|
|
+ ret = vfs_splice_read(in, ppos, pipe, len, flags);
|
|
+ revert_creds(old_cred);
|
|
+
|
|
+ if (ctx->accessed)
|
|
+ ctx->accessed(ctx->user_file);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(backing_file_splice_read);
|
|
+
|
|
+ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
|
|
+ struct file *out, loff_t *ppos, size_t len,
|
|
+ unsigned int flags,
|
|
+ struct backing_file_ctx *ctx)
|
|
+{
|
|
+ const struct cred *old_cred;
|
|
+ ssize_t ret;
|
|
+
|
|
+ if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING)))
|
|
+ return -EIO;
|
|
+
|
|
+ ret = file_remove_privs(ctx->user_file);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ old_cred = override_creds(ctx->cred);
|
|
+ file_start_write(out);
|
|
+ ret = iter_file_splice_write(pipe, out, ppos, len, flags);
|
|
+ file_end_write(out);
|
|
+ revert_creds(old_cred);
|
|
+
|
|
+ if (ctx->end_write)
|
|
+ ctx->end_write(ctx->user_file);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(backing_file_splice_write);
|
|
+
|
|
static int __init backing_aio_init(void)
|
|
{
|
|
backing_aio_cachep = kmem_cache_create("backing_aio",
|
|
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
|
|
index 3eee9f45971e..165a92b25c0a 100644
|
|
--- a/fs/overlayfs/file.c
|
|
+++ b/fs/overlayfs/file.c
|
|
@@ -9,7 +9,6 @@
|
|
#include <linux/xattr.h>
|
|
#include <linux/uio.h>
|
|
#include <linux/uaccess.h>
|
|
-#include <linux/splice.h>
|
|
#include <linux/security.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/fs.h>
|
|
@@ -328,20 +327,21 @@ static ssize_t ovl_splice_read(struct file *in, loff_t *ppos,
|
|
struct pipe_inode_info *pipe, size_t len,
|
|
unsigned int flags)
|
|
{
|
|
- const struct cred *old_cred;
|
|
struct fd real;
|
|
ssize_t ret;
|
|
+ struct backing_file_ctx ctx = {
|
|
+ .cred = ovl_creds(file_inode(in)->i_sb),
|
|
+ .user_file = in,
|
|
+ .accessed = ovl_file_accessed,
|
|
+ };
|
|
|
|
ret = ovl_real_fdget(in, &real);
|
|
if (ret)
|
|
return ret;
|
|
|
|
- old_cred = ovl_override_creds(file_inode(in)->i_sb);
|
|
- ret = vfs_splice_read(real.file, ppos, pipe, len, flags);
|
|
- revert_creds(old_cred);
|
|
- ovl_file_accessed(in);
|
|
-
|
|
+ ret = backing_file_splice_read(real.file, ppos, pipe, len, flags, &ctx);
|
|
fdput(real);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -357,30 +357,23 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
|
|
loff_t *ppos, size_t len, unsigned int flags)
|
|
{
|
|
struct fd real;
|
|
- const struct cred *old_cred;
|
|
struct inode *inode = file_inode(out);
|
|
ssize_t ret;
|
|
+ struct backing_file_ctx ctx = {
|
|
+ .cred = ovl_creds(inode->i_sb),
|
|
+ .user_file = out,
|
|
+ .end_write = ovl_file_modified,
|
|
+ };
|
|
|
|
inode_lock(inode);
|
|
/* Update mode */
|
|
ovl_copyattr(inode);
|
|
- ret = file_remove_privs(out);
|
|
- if (ret)
|
|
- goto out_unlock;
|
|
|
|
ret = ovl_real_fdget(out, &real);
|
|
if (ret)
|
|
goto out_unlock;
|
|
|
|
- old_cred = ovl_override_creds(inode->i_sb);
|
|
- file_start_write(real.file);
|
|
-
|
|
- ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
|
|
-
|
|
- file_end_write(real.file);
|
|
- /* Update size */
|
|
- ovl_file_modified(out);
|
|
- revert_creds(old_cred);
|
|
+ ret = backing_file_splice_write(pipe, real.file, ppos, len, flags, &ctx);
|
|
fdput(real);
|
|
|
|
out_unlock:
|
|
diff --git a/include/linux/backing-file.h b/include/linux/backing-file.h
|
|
index 0648d548a418..0546d5b1c9f5 100644
|
|
--- a/include/linux/backing-file.h
|
|
+++ b/include/linux/backing-file.h
|
|
@@ -28,5 +28,13 @@ ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
|
|
ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
|
|
struct kiocb *iocb, int flags,
|
|
struct backing_file_ctx *ctx);
|
|
+ssize_t backing_file_splice_read(struct file *in, loff_t *ppos,
|
|
+ struct pipe_inode_info *pipe, size_t len,
|
|
+ unsigned int flags,
|
|
+ struct backing_file_ctx *ctx);
|
|
+ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
|
|
+ struct file *out, loff_t *ppos, size_t len,
|
|
+ unsigned int flags,
|
|
+ struct backing_file_ctx *ctx);
|
|
|
|
#endif /* _LINUX_BACKING_FILE_H */
|
|
--
|
|
2.50.1 (Apple Git-155)
|
|
|