The pipe_write() code was locking the pipe without busying it first in
certain cases, and a close() by another process could potentially rip the pipe out from under the (blocked) locking operation. Reported-by: Alexander Viro <viro@math.psu.edu>
This commit is contained in:
parent
34c4099770
commit
1b3e974a71
@ -777,6 +777,7 @@ pipe_write(fp, uio, cred, flags, p)
|
||||
if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
|
||||
return (EPIPE);
|
||||
}
|
||||
++wpipe->pipe_busy;
|
||||
|
||||
/*
|
||||
* If it is advantageous to resize the pipe buffer, do
|
||||
@ -792,15 +793,27 @@ pipe_write(fp, uio, cred, flags, p)
|
||||
if (pipespace(wpipe, BIG_PIPE_SIZE) == 0)
|
||||
nbigpipe++;
|
||||
pipeunlock(wpipe);
|
||||
} else {
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If an early error occured unbusy and return, waking up any pending
|
||||
* readers.
|
||||
*/
|
||||
if (error) {
|
||||
--wpipe->pipe_busy;
|
||||
if ((wpipe->pipe_busy == 0) &&
|
||||
(wpipe->pipe_state & PIPE_WANT)) {
|
||||
wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
|
||||
wakeup(wpipe);
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
KASSERT(wpipe->pipe_buffer.buffer != NULL, ("pipe buffer gone"));
|
||||
|
||||
++wpipe->pipe_busy;
|
||||
orig_resid = uio->uio_resid;
|
||||
|
||||
while (uio->uio_resid) {
|
||||
int space;
|
||||
|
||||
@ -977,6 +990,7 @@ pipe_write(fp, uio, cred, flags, p)
|
||||
}
|
||||
|
||||
--wpipe->pipe_busy;
|
||||
|
||||
if ((wpipe->pipe_busy == 0) && (wpipe->pipe_state & PIPE_WANT)) {
|
||||
wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
|
||||
wakeup(wpipe);
|
||||
@ -995,9 +1009,10 @@ pipe_write(fp, uio, cred, flags, p)
|
||||
* Don't return EPIPE if I/O was successful
|
||||
*/
|
||||
if ((wpipe->pipe_buffer.cnt == 0) &&
|
||||
(uio->uio_resid == 0) &&
|
||||
(error == EPIPE))
|
||||
(uio->uio_resid == 0) &&
|
||||
(error == EPIPE)) {
|
||||
error = 0;
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
vfs_timestamp(&wpipe->pipe_mtime);
|
||||
|
Loading…
Reference in New Issue
Block a user