[PATCH] netfs: break unbuffered write when netfs_alloc_subrequest() fails
Edward Adam Davis <[email protected]>
| Newsgroups | org.kernel.vger.linux-fsdevel,dev.linux.lists.netfs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
syzbot reported a null-ptr-deref below [1] following a fault injection in
netfs_alloc_subrequest(). [0]
When netfs_alloc_subrequest() fails, subreq is NULL.
Later, netfs_prepare_write() tries to initialize members of
subreq(e.g., source), the issue in [1] is triggered.
Let's handle the error of netfs_prepare_write() properly.
[0]
FAULT_INJECTION: forcing a failure.
name failslab, interval 1, probability 0, space 0, times 0
Call Trace:
netfs_alloc_subrequest+0x116/0x3f0
netfs_prepare_write+0x76/0x7b0
netfs_unbuffered_write+0x75c/0x2020
netfs_unbuffered_write_iter_locked+0x7d6/0xa80
netfs_unbuffered_write_iter+0x442/0x720
v9fs_file_write_iter+0xbf/0x100
vfs_write+0x6ac/0x1050
[1]
KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af]
RIP: 0010:netfs_prepare_write+0xbc/0x7b0 fs/netfs/write_issue.c:173
Call Trace:
netfs_unbuffered_write+0x75c/0x2020 fs/netfs/direct_write.c:111
netfs_unbuffered_write_iter_locked+0x7d6/0xa80 fs/netfs/direct_write.c:290
netfs_unbuffered_write_iter+0x442/0x720 fs/netfs/direct_write.c:382
v9fs_file_write_iter+0xbf/0x100 fs/9p/vfs_file.c:409
new_sync_write fs/read_write.c:595 [inline]
Fixes: 288ace2f57c9 ("netfs: New writeback implementation")
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=6a13fc77eb6f0802be2d
Tested-by: [email protected]
Signed-off-by: Edward Adam Davis <[email protected]>
---
fs/netfs/direct_write.c | 4 ++++
fs/netfs/write_issue.c | 2 ++
2 files changed, 6 insertions(+)
diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c
index c16fbad286a1..567b946b7a56 100644
--- a/fs/netfs/direct_write.c
+++ b/fs/netfs/direct_write.c
@@ -110,6 +110,10 @@ static int netfs_unbuffered_write(struct netfs_io_request *wreq)
if (!subreq) {
netfs_prepare_write(wreq, stream, wreq->start + wreq->transferred);
subreq = stream->construct;
+ if (!subreq) {
+ wreq->error = -ENOMEM;
+ break;
+ }
stream->construct = NULL;
}
diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
index 2d9cfcd43658..851f6f93ad45 100644
--- a/fs/netfs/write_issue.c
+++ b/fs/netfs/write_issue.c
@@ -170,6 +170,8 @@ void netfs_prepare_write(struct netfs_io_request *wreq,
rolling_buffer_make_space(&wreq->buffer, wreq->gfp);
subreq = netfs_alloc_subrequest(wreq);
+ if (!subreq)
+ return;
subreq->source = stream->source;
subreq->start = start;
subreq->stream_nr = stream->stream_nr;
--
2.43.0