[PATCH openEuler-1.0-LTS 2/2] ovl: check access to copy_file_range source with src mounter creds
mainline inclusion from mainline-v7.2-rc5 commit a1e0eb8f55cfe09bb31a202a388babc411292656 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17160 CVE: CVE-2026-68448 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- Commit 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") allowed filesystems that implement the copy_file_range() f_op to decide if they want to access cross-sb copy from/to the same fs type. The same commit added checks to verify same sb copy for filesystems that implement ->copy_file_range() and do not support cross-sb copy at the time, namely, to ceph, fuse and nfs. The two remaining fs which implement ->copy_file_range(), cifs and overlayfs started to support cross-sb copy from this time. While overlayfs does support cross-sb copy when the two underlying files are on the same base fs, the copy operation on the two real files from two different overalyfs filesystems is performed with the mounter creds of the destination overlayfs and the read permission access hook for the source file was called with the wrong creds. This could cause either deny of access to copy which would otherwise be allowed (e.g. with splice) or allow read access to file which would otherwise be denied. Fix the latter case by explicitly verifying read access to source file with the source overlayfs mounter creds. The former case remains a quirk of cross-sb overlayfs copy, but userspace could fall back to regular copy so no harm done. Fixes: 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://patch.msgid.link/20260712122421.203113-1-amir73il@gmail.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org> Conflicts: fs/overlayfs/file.c [6f5c84162a30 ("ovl: add override_creds cleanup guard extension for overlayfs") not merged.] Signed-off-by: Ran Hongyun <ranhongyun1@huawei.com> --- fs/overlayfs/file.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 63b7b2600d81..4d9b73cc31ad 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -583,6 +583,7 @@ static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, u64 len, unsigned int flags, enum ovl_copyop op) { + struct inode *inode_in = file_inode(file_in); struct inode *inode_out = file_inode(file_out); struct fd real_in, real_out; const struct cred *old_cred; @@ -598,6 +599,22 @@ static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, return ret; } + /* + * For cross-sb copy, vfs_copy_file_range() will verify read access with + * the mounter creds of the dest fs mounter, so we need to explicitly + * verify read access with the source mounter creds. + */ + if (unlikely(inode_in->i_sb != inode_out->i_sb)) { + old_cred = ovl_override_creds(inode_in->i_sb); + ret = rw_verify_area(READ, real_in.file, &pos_in, len); + revert_creds(old_cred); + if (unlikely(ret)) { + fdput(real_in); + fdput(real_out); + goto out_unlock; + } + } + old_cred = ovl_override_creds(file_inode(file_out)->i_sb); switch (op) { case OVL_COPY: -- 2.52.0
participants (1)
-
Ran Hongyun