Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7995bd28 authored by Al Viro's avatar Al Viro
Browse files

splice: don't pass the address of ->f_pos to methods



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c9036e9f
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -131,6 +131,12 @@ extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
 */
 */
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);


/*
 * splice.c
 */
extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
		loff_t *opos, size_t len, unsigned int flags);

/*
/*
 * pipe.c
 * pipe.c
 */
 */
+16 −8
Original line number Original line Diff line number Diff line
@@ -1064,6 +1064,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
	struct fd in, out;
	struct fd in, out;
	struct inode *in_inode, *out_inode;
	struct inode *in_inode, *out_inode;
	loff_t pos;
	loff_t pos;
	loff_t out_pos;
	ssize_t retval;
	ssize_t retval;
	int fl;
	int fl;


@@ -1077,12 +1078,14 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
	if (!(in.file->f_mode & FMODE_READ))
	if (!(in.file->f_mode & FMODE_READ))
		goto fput_in;
		goto fput_in;
	retval = -ESPIPE;
	retval = -ESPIPE;
	if (!ppos)
	if (!ppos) {
		ppos = &in.file->f_pos;
		pos = in.file->f_pos;
	else
	} else {
		pos = *ppos;
		if (!(in.file->f_mode & FMODE_PREAD))
		if (!(in.file->f_mode & FMODE_PREAD))
			goto fput_in;
			goto fput_in;
	retval = rw_verify_area(READ, in.file, ppos, count);
	}
	retval = rw_verify_area(READ, in.file, &pos, count);
	if (retval < 0)
	if (retval < 0)
		goto fput_in;
		goto fput_in;
	count = retval;
	count = retval;
@@ -1099,7 +1102,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
	retval = -EINVAL;
	retval = -EINVAL;
	in_inode = file_inode(in.file);
	in_inode = file_inode(in.file);
	out_inode = file_inode(out.file);
	out_inode = file_inode(out.file);
	retval = rw_verify_area(WRITE, out.file, &out.file->f_pos, count);
	out_pos = out.file->f_pos;
	retval = rw_verify_area(WRITE, out.file, &out_pos, count);
	if (retval < 0)
	if (retval < 0)
		goto fput_out;
		goto fput_out;
	count = retval;
	count = retval;
@@ -1107,7 +1111,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
	if (!max)
	if (!max)
		max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
		max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);


	pos = *ppos;
	if (unlikely(pos + count > max)) {
	if (unlikely(pos + count > max)) {
		retval = -EOVERFLOW;
		retval = -EOVERFLOW;
		if (pos >= max)
		if (pos >= max)
@@ -1126,18 +1129,23 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
	if (in.file->f_flags & O_NONBLOCK)
	if (in.file->f_flags & O_NONBLOCK)
		fl = SPLICE_F_NONBLOCK;
		fl = SPLICE_F_NONBLOCK;
#endif
#endif
	retval = do_splice_direct(in.file, ppos, out.file, count, fl);
	retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl);


	if (retval > 0) {
	if (retval > 0) {
		add_rchar(current, retval);
		add_rchar(current, retval);
		add_wchar(current, retval);
		add_wchar(current, retval);
		fsnotify_access(in.file);
		fsnotify_access(in.file);
		fsnotify_modify(out.file);
		fsnotify_modify(out.file);
		out.file->f_pos = out_pos;
		if (ppos)
			*ppos = pos;
		else
			in.file->f_pos = pos;
	}
	}


	inc_syscr(current);
	inc_syscr(current);
	inc_syscw(current);
	inc_syscw(current);
	if (*ppos > max)
	if (pos > max)
		retval = -EOVERFLOW;
		retval = -EOVERFLOW;


fput_out:
fput_out:
+18 −13
Original line number Original line Diff line number Diff line
@@ -1274,7 +1274,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
{
{
	struct file *file = sd->u.file;
	struct file *file = sd->u.file;


	return do_splice_from(pipe, file, &file->f_pos, sd->total_len,
	return do_splice_from(pipe, file, sd->opos, sd->total_len,
			      sd->flags);
			      sd->flags);
}
}


@@ -1294,7 +1294,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
 *
 *
 */
 */
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
		      size_t len, unsigned int flags)
		      loff_t *opos, size_t len, unsigned int flags)
{
{
	struct splice_desc sd = {
	struct splice_desc sd = {
		.len		= len,
		.len		= len,
@@ -1302,6 +1302,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
		.flags		= flags,
		.flags		= flags,
		.pos		= *ppos,
		.pos		= *ppos,
		.u.file		= out,
		.u.file		= out,
		.opos		= opos,
	};
	};
	long ret;
	long ret;


@@ -1325,7 +1326,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
{
{
	struct pipe_inode_info *ipipe;
	struct pipe_inode_info *ipipe;
	struct pipe_inode_info *opipe;
	struct pipe_inode_info *opipe;
	loff_t offset, *off;
	loff_t offset;
	long ret;
	long ret;


	ipipe = get_pipe_info(in);
	ipipe = get_pipe_info(in);
@@ -1356,13 +1357,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
				return -EINVAL;
				return -EINVAL;
			if (copy_from_user(&offset, off_out, sizeof(loff_t)))
			if (copy_from_user(&offset, off_out, sizeof(loff_t)))
				return -EFAULT;
				return -EFAULT;
			off = &offset;
		} else {
		} else
			offset = out->f_pos;
			off = &out->f_pos;
		}


		ret = do_splice_from(ipipe, out, off, len, flags);
		ret = do_splice_from(ipipe, out, &offset, len, flags);


		if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
		if (!off_out)
			out->f_pos = offset;
		else if (copy_to_user(off_out, &offset, sizeof(loff_t)))
			ret = -EFAULT;
			ret = -EFAULT;


		return ret;
		return ret;
@@ -1376,13 +1379,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
				return -EINVAL;
				return -EINVAL;
			if (copy_from_user(&offset, off_in, sizeof(loff_t)))
			if (copy_from_user(&offset, off_in, sizeof(loff_t)))
				return -EFAULT;
				return -EFAULT;
			off = &offset;
		} else {
		} else
			offset = in->f_pos;
			off = &in->f_pos;
		}


		ret = do_splice_to(in, off, opipe, len, flags);
		ret = do_splice_to(in, &offset, opipe, len, flags);


		if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
		if (!off_in)
			in->f_pos = offset;
		else if (copy_to_user(off_in, &offset, sizeof(loff_t)))
			ret = -EFAULT;
			ret = -EFAULT;


		return ret;
		return ret;
+0 −2
Original line number Original line Diff line number Diff line
@@ -2414,8 +2414,6 @@ extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
		struct file *, loff_t *, size_t, unsigned int);
		struct file *, loff_t *, size_t, unsigned int);
extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
		struct file *out, loff_t *, size_t len, unsigned int flags);
		struct file *out, loff_t *, size_t len, unsigned int flags);
extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
		size_t len, unsigned int flags);


extern void
extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
+1 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ struct splice_desc {
		void *data;		/* cookie */
		void *data;		/* cookie */
	} u;
	} u;
	loff_t pos;			/* file position */
	loff_t pos;			/* file position */
	loff_t *opos;			/* sendfile: output position */
	size_t num_spliced;		/* number of bytes already spliced */
	size_t num_spliced;		/* number of bytes already spliced */
	bool need_wakeup;		/* need to wake up writer */
	bool need_wakeup;		/* need to wake up writer */
};
};