]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/6.6.26/fs-pipe-fix-lockdep-false-positive-in-watchqueue-pip.patch
Linux 6.6.26
[thirdparty/kernel/stable-queue.git] / releases / 6.6.26 / fs-pipe-fix-lockdep-false-positive-in-watchqueue-pip.patch
CommitLineData
ea78042b
SL
1From d15cf81e82c6abf559bec243d5de7ae8f6ebf9f4 Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Fri, 24 Nov 2023 16:08:22 +0100
4Subject: fs/pipe: Fix lockdep false-positive in watchqueue pipe_write()
5
6From: Jann Horn <jannh@google.com>
7
8[ Upstream commit 055ca83559912f2cfd91c9441427bac4caf3c74e ]
9
10When you try to splice between a normal pipe and a notification pipe,
11get_pipe_info(..., true) fails, so splice() falls back to treating the
12notification pipe like a normal pipe - so we end up in
13iter_file_splice_write(), which first locks the input pipe, then calls
14vfs_iter_write(), which locks the output pipe.
15
16Lockdep complains about that, because we're taking a pipe lock while
17already holding another pipe lock.
18
19I think this probably (?) can't actually lead to deadlocks, since you'd
20need another way to nest locking a normal pipe into locking a
21watch_queue pipe, but the lockdep annotations don't make that clear.
22
23Bail out earlier in pipe_write() for notification pipes, before taking
24the pipe lock.
25
26Reported-and-tested-by: <syzbot+011e4ea1da6692cf881c@syzkaller.appspotmail.com>
27Closes: https://syzkaller.appspot.com/bug?extid=011e4ea1da6692cf881c
28Fixes: c73be61cede5 ("pipe: Add general notification queue support")
29Signed-off-by: Jann Horn <jannh@google.com>
30Link: https://lore.kernel.org/r/20231124150822.2121798-1-jannh@google.com
31Signed-off-by: Christian Brauner <brauner@kernel.org>
32Signed-off-by: Sasha Levin <sashal@kernel.org>
33---
34 fs/pipe.c | 17 ++++++++++++-----
35 1 file changed, 12 insertions(+), 5 deletions(-)
36
37diff --git a/fs/pipe.c b/fs/pipe.c
38index a234035cc375d..ba4376341ddd2 100644
39--- a/fs/pipe.c
40+++ b/fs/pipe.c
41@@ -425,6 +425,18 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
42 bool was_empty = false;
43 bool wake_next_writer = false;
44
45+ /*
46+ * Reject writing to watch queue pipes before the point where we lock
47+ * the pipe.
48+ * Otherwise, lockdep would be unhappy if the caller already has another
49+ * pipe locked.
50+ * If we had to support locking a normal pipe and a notification pipe at
51+ * the same time, we could set up lockdep annotations for that, but
52+ * since we don't actually need that, it's simpler to just bail here.
53+ */
54+ if (pipe_has_watch_queue(pipe))
55+ return -EXDEV;
56+
57 /* Null write succeeds. */
58 if (unlikely(total_len == 0))
59 return 0;
60@@ -437,11 +449,6 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
61 goto out;
62 }
63
64- if (pipe_has_watch_queue(pipe)) {
65- ret = -EXDEV;
66- goto out;
67- }
68-
69 /*
70 * If it wasn't empty we try to merge new data into
71 * the last buffer.
72--
732.43.0
74