Fix race in io_output() that can lead to double-free
Move call of ioq_makeiov() to its use, because calling it before empth_select() is racy, as follows. Player thread flushes output by calling io_output(player->iop, 1). io_output() sets up iov[] to point to queued output. empth_select() blocks on output. Another thread sends a C_FLASH or C_INFORM message to this player. This calls io_output(p->iop, 0). The output file descriptor has become writable since the player thread blocked on it, so some output gets written and dequeued. The player thread resumes, writes out iov[] and dequeues. Any output already written by the other thread gets duplicated. If the other thread's dequeue operation freed struct io buffers, there's use after free followed by double-free.
This commit is contained in:
parent
25115f4997
commit
d28fbbb186
1 changed files with 1 additions and 2 deletions
|
@ -209,8 +209,6 @@ io_output(struct iop *iop, int wait)
|
|||
if (iop->flags & IO_ERROR)
|
||||
return -1;
|
||||
|
||||
n = ioq_makeiov(iop->output, iov, IO_BUFSIZE);
|
||||
|
||||
if (wait) {
|
||||
res = empth_select(iop->fd, EMPTH_FD_WRITE, NULL);
|
||||
if (res == 0)
|
||||
|
@ -221,6 +219,7 @@ io_output(struct iop *iop, int wait)
|
|||
}
|
||||
}
|
||||
|
||||
n = ioq_makeiov(iop->output, iov, IO_BUFSIZE);
|
||||
cc = writev(iop->fd, iov, n);
|
||||
if (cc < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue