mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-02 06:35:36 +00:00
Fix handling of PIPE_EOF in the direct write path.
Suppose a writing thread has pinned its pages and gone to sleep with pipe_map.cnt > 0. Suppose that the thread is woken up by a signal (so error != 0) and the other end of the pipe has simultaneously been closed. In this case, to satisfy the assertion about pipe_map.cnt in pipe_destroy_write_buffer(), we must mark the buffer as empty. Reported by: syzbot+5cce271bf2cb1b1e1876@syzkaller.appspotmail.com Reviewed by: kib Tested by: pho MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D22261
This commit is contained in:
parent
7aff07d914
commit
1cbfe73da5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354629
|
@ -970,15 +970,8 @@ pipe_direct_write(struct pipe *wpipe, struct uio *uio)
|
|||
goto error1;
|
||||
}
|
||||
|
||||
while (wpipe->pipe_map.cnt != 0) {
|
||||
if (wpipe->pipe_state & PIPE_EOF) {
|
||||
wpipe->pipe_map.cnt = 0;
|
||||
pipe_destroy_write_buffer(wpipe);
|
||||
pipeselwakeup(wpipe);
|
||||
pipeunlock(wpipe);
|
||||
error = EPIPE;
|
||||
goto error1;
|
||||
}
|
||||
while (wpipe->pipe_map.cnt != 0 &&
|
||||
(wpipe->pipe_state & PIPE_EOF) == 0) {
|
||||
if (wpipe->pipe_state & PIPE_WANTR) {
|
||||
wpipe->pipe_state &= ~PIPE_WANTR;
|
||||
wakeup(wpipe);
|
||||
|
@ -993,12 +986,16 @@ pipe_direct_write(struct pipe *wpipe, struct uio *uio)
|
|||
break;
|
||||
}
|
||||
|
||||
if (wpipe->pipe_state & PIPE_EOF)
|
||||
error = EPIPE;
|
||||
if (error == EINTR || error == ERESTART)
|
||||
pipe_clone_write_buffer(wpipe);
|
||||
else
|
||||
if ((wpipe->pipe_state & PIPE_EOF) != 0) {
|
||||
wpipe->pipe_map.cnt = 0;
|
||||
pipe_destroy_write_buffer(wpipe);
|
||||
pipeselwakeup(wpipe);
|
||||
error = EPIPE;
|
||||
} else if (error == EINTR || error == ERESTART) {
|
||||
pipe_clone_write_buffer(wpipe);
|
||||
} else {
|
||||
pipe_destroy_write_buffer(wpipe);
|
||||
}
|
||||
pipeunlock(wpipe);
|
||||
KASSERT((wpipe->pipe_state & PIPE_DIRECTW) == 0,
|
||||
("pipe %p leaked PIPE_DIRECTW", wpipe));
|
||||
|
|
Loading…
Reference in a new issue