All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] fs: make pipe/splice fcntl safe
@ 2015-04-12 17:08 Dmitry Monakhov
  2015-04-12 17:08 ` [PATCH 1/2] pipe: fix race with fcntl Dmitry Monakhov
  2015-04-12 17:08 ` [PATCH 2/2] splice: fix race beween splice_write vs fcntl Dmitry Monakhov
  0 siblings, 2 replies; 5+ messages in thread
From: Dmitry Monakhov @ 2015-04-12 17:08 UTC (permalink / raw)
  To: linux-kernel, viro; +Cc: linux-fsdevel, Dmitry Monakhov

Al Viro already made most vfs/write_iters fcntl safe, but pipe and splice
are still affected. Patchset against vfs.git#for-next f1d36c2d711166aaa84f37
TOC:
0001-pipe-fix-race-with-fcntl
0002-splice-fix-race-beween-splice_write-vs-fcntl

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] pipe: fix race with fcntl
  2015-04-12 17:08 [PATCH 0/2] fs: make pipe/splice fcntl safe Dmitry Monakhov
@ 2015-04-12 17:08 ` Dmitry Monakhov
  2015-04-12 17:34   ` Al Viro
  2015-04-12 17:08 ` [PATCH 2/2] splice: fix race beween splice_write vs fcntl Dmitry Monakhov
  1 sibling, 1 reply; 5+ messages in thread
From: Dmitry Monakhov @ 2015-04-12 17:08 UTC (permalink / raw)
  To: linux-kernel, viro; +Cc: linux-fsdevel, Dmitry Monakhov

Fix other long standing issues caused by fcntl(,F_SETFL,):
- User can disable O_DIRECT for pipe[1] (paketized IO), but can not enable it again.
- Currently we do not set O_APPEND on pipe[1] (IMHO it is wrong, but let it be)
  so it is reasonable to completely prohibit change O_APPEND flag on both
  end's of pipe. Add ->check_flags method in order to diallow O_APPEND toggling.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/fcntl.c |    6 ++++--
 fs/pipe.c  |   16 +++++++++++++---
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/fs/fcntl.c b/fs/fcntl.c
index ee85cd4..0bdc9c7 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -51,9 +51,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
 	       if (arg & O_NDELAY)
 		   arg |= O_NONBLOCK;
 
+	/* allowed only for inodes with ->direct_io method or write pipe */
 	if (arg & O_DIRECT) {
-		if (!filp->f_mapping || !filp->f_mapping->a_ops ||
-			!filp->f_mapping->a_ops->direct_IO)
+		if ((!filp->f_mapping || !filp->f_mapping->a_ops ||
+		     !filp->f_mapping->a_ops->direct_IO) &&
+		    !(get_pipe_info(filp) && (filp->f_flags | O_WRONLY)))
 				return -EINVAL;
 	}
 
diff --git a/fs/pipe.c b/fs/pipe.c
index 8865f79..0c15647 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -329,9 +329,9 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 	return ret;
 }
 
-static inline int is_packetized(struct file *file)
+static inline int is_packetized(struct kiocb *iocb)
 {
-	return (file->f_flags & O_DIRECT) != 0;
+	return (iocb->ki_flags & IOCB_DIRECT) != 0;
 }
 
 static ssize_t
@@ -427,7 +427,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
 			buf->offset = 0;
 			buf->len = copied;
 			buf->flags = 0;
-			if (is_packetized(filp)) {
+			if (is_packetized(iocb)) {
 				buf->ops = &packet_pipe_buf_ops;
 				buf->flags = PIPE_BUF_FLAG_PACKET;
 			}
@@ -943,6 +943,15 @@ err:
 	return ret;
 }
 
+/* XXX: Currently it is not possible distinguish read side from write one */
+static int pipe_check_flags(int flags)
+{
+	if (flags & O_APPEND)
+	    return -EINVAL;
+
+	return 0;
+}
+
 const struct file_operations pipefifo_fops = {
 	.open		= fifo_open,
 	.llseek		= no_llseek,
@@ -952,6 +961,7 @@ const struct file_operations pipefifo_fops = {
 	.unlocked_ioctl	= pipe_ioctl,
 	.release	= pipe_release,
 	.fasync		= pipe_fasync,
+	.check_flags	= pipe_check_flags,
 };
 
 /*
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] splice: fix race beween splice_write vs fcntl
  2015-04-12 17:08 [PATCH 0/2] fs: make pipe/splice fcntl safe Dmitry Monakhov
  2015-04-12 17:08 ` [PATCH 1/2] pipe: fix race with fcntl Dmitry Monakhov
@ 2015-04-12 17:08 ` Dmitry Monakhov
  1 sibling, 0 replies; 5+ messages in thread
From: Dmitry Monakhov @ 2015-04-12 17:08 UTC (permalink / raw)
  To: linux-kernel, viro; +Cc: linux-fsdevel, Dmitry Monakhov

file->f_flags & O_APPEND is checked twice
-> do_splice_direct or do_splice: return EINVAL if O_APPEND enabled
   -> generic_write_checks: seek to end in case of O_APPEND
This is obviously whong and result in unpredictable behaviour if raced with
fcntl. It is reasonable to recheck append flag after kiocb was constructed
(where ->ki_flags is stable), for that reason we should use special
analog of vfs_write_iter() which asserts non-append behaviour.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/splice.c |   23 ++++++++++++++++++++++-
 1 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/fs/splice.c b/fs/splice.c
index 41cbb16..d49615d 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -922,6 +922,27 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 
 	return ret;
 }
+ssize_t splice_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
+{
+	struct kiocb kiocb;
+	ssize_t ret;
+
+	if (!file->f_op->write_iter)
+		return -EINVAL;
+
+	init_sync_kiocb(&kiocb, file);
+	if (kiocb.ki_flags & IOCB_APPEND)
+		return -EINVAL;
+
+	kiocb.ki_pos = *ppos;
+	iter->type |= WRITE;
+	ret = file->f_op->write_iter(&kiocb, iter);
+	BUG_ON(ret == -EIOCBQUEUED);
+	if (ret > 0)
+		*ppos = kiocb.ki_pos;
+	return ret;
+}
+
 
 /**
  * iter_file_splice_write - splice data from a pipe to a file
@@ -1005,7 +1026,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 
 		iov_iter_bvec(&from, ITER_BVEC | WRITE, array, n,
 			      sd.total_len - left);
-		ret = vfs_iter_write(out, &from, &sd.pos);
+		ret = splice_iter_write(out, &from, &sd.pos);
 		if (ret <= 0)
 			break;
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] pipe: fix race with fcntl
  2015-04-12 17:08 ` [PATCH 1/2] pipe: fix race with fcntl Dmitry Monakhov
@ 2015-04-12 17:34   ` Al Viro
  2015-04-12 17:52     ` Dmitry Monakhov
  0 siblings, 1 reply; 5+ messages in thread
From: Al Viro @ 2015-04-12 17:34 UTC (permalink / raw)
  To: Dmitry Monakhov; +Cc: linux-kernel, linux-fsdevel

On Sun, Apr 12, 2015 at 09:08:21PM +0400, Dmitry Monakhov wrote:
> Fix other long standing issues caused by fcntl(,F_SETFL,):
> - User can disable O_DIRECT for pipe[1] (paketized IO), but can not enable it again.
> - Currently we do not set O_APPEND on pipe[1] (IMHO it is wrong, but let it be)
>   so it is reasonable to completely prohibit change O_APPEND flag on both
>   end's of pipe. Add ->check_flags method in order to diallow O_APPEND toggling.
> 
> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
> ---

TBH, all those ->direct_IO != NULL checks seem to be a wrong approach.
If nothing else, it forces several filesystem into inventing a fake
->direct_IO just to fool those tests.  How about we
	* introduce FMODE_MAY_DIRECT and allow ->open() explicitly set it
	* make open_check_o_direct() and fcntl.c check that instead of poking
in ->f_mapping->a_ops, etc.
	* provide a variant of generic_file_open() that would set that
bit and use it on the filesystems that handle dio

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] pipe: fix race with fcntl
  2015-04-12 17:34   ` Al Viro
@ 2015-04-12 17:52     ` Dmitry Monakhov
  0 siblings, 0 replies; 5+ messages in thread
From: Dmitry Monakhov @ 2015-04-12 17:52 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 1584 bytes --]

Al Viro <viro@ZenIV.linux.org.uk> writes:

> On Sun, Apr 12, 2015 at 09:08:21PM +0400, Dmitry Monakhov wrote:
>> Fix other long standing issues caused by fcntl(,F_SETFL,):
>> - User can disable O_DIRECT for pipe[1] (paketized IO), but can not enable it again.
>> - Currently we do not set O_APPEND on pipe[1] (IMHO it is wrong, but let it be)
>>   so it is reasonable to completely prohibit change O_APPEND flag on both
>>   end's of pipe. Add ->check_flags method in order to diallow O_APPEND toggling.
>> 
>> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
>> ---
>
> TBH, all those ->direct_IO != NULL checks seem to be a wrong approach.
> If nothing else, it forces several filesystem into inventing a fake
> ->direct_IO just to fool those tests.  How about we
> 	* introduce FMODE_MAY_DIRECT and allow ->open() explicitly set it
> 	* make open_check_o_direct() and fcntl.c check that instead of poking
> in ->f_mapping->a_ops, etc.
> 	* provide a variant of generic_file_open() that would set that
> bit and use it on the filesystems that handle dio
100% agree. FMODE is perfect place for that.

BTW: I always wondering: why we do not mark pipe[1]->f_flags with O_APPEND?
Probably the answer is that nobody care about ->f_flags since no_llseek
returns -ESPIPE, but f_flags are visiable via fcntl so IMHO it is
reasonable to fix that too.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-04-12 17:52 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-12 17:08 [PATCH 0/2] fs: make pipe/splice fcntl safe Dmitry Monakhov
2015-04-12 17:08 ` [PATCH 1/2] pipe: fix race with fcntl Dmitry Monakhov
2015-04-12 17:34   ` Al Viro
2015-04-12 17:52     ` Dmitry Monakhov
2015-04-12 17:08 ` [PATCH 2/2] splice: fix race beween splice_write vs fcntl Dmitry Monakhov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.