Currently, watch_queue_set_size() modifies the pipe buffers charged to user->pipe_bufs without updating the pipe->nr_accounted on the pipe itself, due to the if (!pipe_has_watch_queue()) test in pipe_resize_ring(). This means that when the pipe is ultimately freed, we decrement user->pipe_bufs by something other than what than we had charged to it, potentially leading to an underflow. This in turn can cause subsequent too_many_pipe_buffers_soft() tests to fail with -EPERM. Fixes: e95aada4cb93d ("pipe: wakeup wr_wait after setting max_usage") Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> --- diff --git a/fs/pipe.c b/fs/pipe.c index 94b59045ab44..072e2e003165 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1317,10 +1317,8 @@ int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots) pipe->tail = tail; pipe->head = head; - if (!pipe_has_watch_queue(pipe)) { - pipe->max_usage = nr_slots; - pipe->nr_accounted = nr_slots; - } + pipe->max_usage = nr_slots; + pipe->nr_accounted = nr_slots; spin_unlock_irq(&pipe->rd_wait.lock);