Skip to content
Snippets Groups Projects
Commit ea235ec6 authored by Jason A. Donenfeld's avatar Jason A. Donenfeld Committed by Yongqiang Liu
Browse files

fs: check FMODE_LSEEK to control internal pipe splicing

stable inclusion
from stable-v4.19.256
commit ab37175dd3593b9098f2242e370a7b1af4c35368
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5Q0SQ


CVE: NA

--------------------------------

[ Upstream commit 97ef77c52b789ec1411d360ed99dca1efe4b2c81 ]

The original direct splicing mechanism from Jens required the input to
be a regular file because it was avoiding the special socket case. It
also recognized blkdevs as being close enough to a regular file. But it
forgot about chardevs, which behave the same way and work fine here.

This is an okayish heuristic, but it doesn't totally work. For example,
a few chardevs should be spliceable here. And a few regular files
shouldn't. This patch fixes this by instead checking whether FMODE_LSEEK
is set, which represents decently enough what we need rewinding for when
splicing to internal pipes.

Fixes: b92ce558 ("[PATCH] splice: add direct fd <-> fd splicing support")
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent 9750a13a
No related branches found
No related tags found
No related merge requests found
......@@ -899,17 +899,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
{
struct pipe_inode_info *pipe;
long ret, bytes;
umode_t i_mode;
size_t len;
int i, flags, more;
/*
* We require the input being a regular file, as we don't want to
* randomly drop data for eg socket -> socket splicing. Use the
* piped splicing for that!
* We require the input to be seekable, as we don't want to randomly
* drop data for eg socket -> socket splicing. Use the piped splicing
* for that!
*/
i_mode = file_inode(in)->i_mode;
if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
if (unlikely(!(in->f_mode & FMODE_LSEEK)))
return -EINVAL;
/*
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment