Skip to content

Commit

Permalink
pipe: Remove assertion from pipe_poll()
Browse files Browse the repository at this point in the history
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: 8cefc10 ("pipe: Use head and tail pointers for the ring, not cursor and length")
Reported-by: [email protected]
Signed-off-by: David Howells <[email protected]>
cc: Eric Biggers <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
dhowells authored and torvalds committed Dec 5, 2019
1 parent 3c0edea commit 8c7b8c3
Showing 1 changed file with 1 addition and 2 deletions.
3 changes: 1 addition & 2 deletions fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 8c7b8c3

Please sign in to comment.