* [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.