Skip to content

Commit ad910e3

Browse files
committed
pipe: fix poll/select race introduced by the pipe rework
The kernel wait queues have a basic rule to them: you add yourself to the wait-queue first, and then you check the things that you're going to wait on. That avoids the races with the event you're waiting for. The same goes for poll/select logic: the "poll_wait()" goes first, and then you check the things you're polling for. Of course, if you use locking, the ordering doesn't matter since the lock will serialize with anything that changes the state you're looking at. That's not the case here, though. So move the poll_wait() first in pipe_poll(), before you start looking at the pipe state. Fixes: 8cefc10 ("pipe: Use head and tail pointers for the ring, not cursor and length") Cc: David Howells <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent eea2d5d commit ad910e3

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

fs/pipe.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,12 +574,24 @@ pipe_poll(struct file *filp, poll_table *wait)
574574
{
575575
__poll_t mask;
576576
struct pipe_inode_info *pipe = filp->private_data;
577-
unsigned int head = READ_ONCE(pipe->head);
578-
unsigned int tail = READ_ONCE(pipe->tail);
577+
unsigned int head, tail;
579578

579+
/*
580+
* Reading only -- no need for acquiring the semaphore.
581+
*
582+
* But because this is racy, the code has to add the
583+
* entry to the poll table _first_ ..
584+
*/
580585
poll_wait(filp, &pipe->wait, wait);
581586

582-
/* Reading only -- no need for acquiring the semaphore. */
587+
/*
588+
* .. and only then can you do the racy tests. That way,
589+
* if something changes and you got it wrong, the poll
590+
* table entry will wake you up and fix it.
591+
*/
592+
head = READ_ONCE(pipe->head);
593+
tail = READ_ONCE(pipe->tail);
594+
583595
mask = 0;
584596
if (filp->f_mode & FMODE_READ) {
585597
if (!pipe_empty(head, tail))

0 commit comments

Comments
 (0)