From 8c7b8c34ae952cc062c12d7db9ee2f298c09dca4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 5 Dec 2019 22:30:30 +0000 Subject: [PATCH] pipe: Remove assertion from pipe_poll() An assertion check was added to pipe_poll() to make sure that the ring occupancy isn't seen to overflow the ring size. However, since no locks are held when the three values are read, it is possible for F_SETPIPE_SZ to intervene and muck up the calculation, thereby causing the oops. Fix this by simply removing the assertion and accepting that the calculation might be approximate. Note that the previous code also had a similar issue, though there was no assertion check, since the occupancy counter and the ring size were not read with a lock held, so it's possible that the poll check might have malfunctioned then too. Also wake up all the waiters so that they can reissue their checks if there was a competing read or write. Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") Reported-by: syzbot+d37abaade33a934f16f2@syzkaller.appspotmail.com Signed-off-by: David Howells cc: Eric Biggers Signed-off-by: Linus Torvalds --- fs/pipe.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index c5e3765465f0..05330fac081f 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -579,8 +579,6 @@ pipe_poll(struct file *filp, poll_table *wait) poll_wait(filp, &pipe->wait, wait); - BUG_ON(pipe_occupancy(head, tail) > pipe->ring_size); - /* Reading only -- no need for acquiring the semaphore. */ mask = 0; if (filp->f_mode & FMODE_READ) { @@ -1174,6 +1172,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg) pipe->max_usage = nr_slots; pipe->tail = tail; pipe->head = head; + wake_up_interruptible_all(&pipe->wait); return pipe->max_usage * PAGE_SIZE; out_revert_acct: -- 2.34.1