]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.24.1/fix-writev-regression-pan-hanging-unkillable-and-un-straceable.patch
Remove duplicated commits
[thirdparty/kernel/stable-queue.git] / releases / 2.6.24.1 / fix-writev-regression-pan-hanging-unkillable-and-un-straceable.patch
CommitLineData
c9ae5004
GKH
1From mingo@elte.hu Sat Feb 2 06:01:49 2008
2From: Nick Piggin <nickpiggin@yahoo.com.au>
3Date: Sat, 2 Feb 2008 15:01:17 +0100
4Subject: fix writev regression: pan hanging unkillable and un-straceable
5To: Linus Torvalds <torvalds@linux-foundation.org>
6Cc: Andrew Morton <akpm@linux-foundation.org>, Nick Piggin <npiggin@suse.de>, "Rafael J. Wysocki" <rjw@sisk.pl>, Greg Kroah-Hartman <gregkh@suse.de>, stable@kernel.org
7Message-ID: <20080202140117.GA4038@elte.hu>
8Content-Disposition: inline
9
10From: Nick Piggin <nickpiggin@yahoo.com.au>
11
12patch 124d3b7041f9a0ca7c43a6293e1cae4576c32fd5 in mainline.
13
14Frederik Himpe reported an unkillable and un-straceable pan process.
15
16Zero length iovecs can go into an infinite loop in writev, because the
17iovec iterator does not always advance over them.
18
19The sequence required to trigger this is not trivial. I think it
20requires that a zero-length iovec be followed by a non-zero-length iovec
21which causes a pagefault in the atomic usercopy. This causes the writev
22code to drop back into single-segment copy mode, which then tries to
23copy the 0 bytes of the zero-length iovec; a zero length copy looks like
24a failure though, so it loops.
25
26Put a test into iov_iter_advance to catch zero-length iovecs. We could
27just put the test in the fallback path, but I feel it is more robust to
28skip over zero-length iovecs throughout the code (iovec iterator may be
29used in filesystems too, so it should be robust).
30
31Signed-off-by: Nick Piggin <npiggin@suse.de>
32Signed-off-by: Ingo Molnar <mingo@elte.hu>
33Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
34Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
35
36---
37 mm/filemap.c | 8 ++++++--
38 1 file changed, 6 insertions(+), 2 deletions(-)
39
40--- a/mm/filemap.c
41+++ b/mm/filemap.c
42@@ -1733,7 +1733,11 @@ static void __iov_iter_advance_iov(struc
43 const struct iovec *iov = i->iov;
44 size_t base = i->iov_offset;
45
46- while (bytes) {
47+ /*
48+ * The !iov->iov_len check ensures we skip over unlikely
49+ * zero-length segments.
50+ */
51+ while (bytes || !iov->iov_len) {
52 int copy = min(bytes, iov->iov_len - base);
53
54 bytes -= copy;
55@@ -2251,6 +2255,7 @@ again:
56
57 cond_resched();
58
59+ iov_iter_advance(i, copied);
60 if (unlikely(copied == 0)) {
61 /*
62 * If we were unable to copy any data at all, we must
63@@ -2264,7 +2269,6 @@ again:
64 iov_iter_single_seg_count(i));
65 goto again;
66 }
67- iov_iter_advance(i, copied);
68 pos += copied;
69 written += copied;
70