Bug #6474
closedgetupeercred causes spurious event port wakeups on FIFOs
100%
Description
It turns out that event ports are slightly broken for FIFOs.
Specifically, it is possible for port_getn
to return an event on a FIFO fd (registered via PORT_SOURCE_FD
and POLLIN
) even though there is nothing available for reading.
Attached is a minimal test case.
If you run it with stdin being a file or a tty, port_getn
blocks until bytes are available for reading:
$ ./a.out port = 3, errno = 0 ret = 0, errno = 0 ret = -1, errno = 48 ucred = 803bc88 <waiting>
If, however, stdin is a pipe, port_getn
returns immediately because the fd is marked as readable by the getpeerucred
call.
$ cat | ./a.out port = 3, errno = 0 ret = 0, errno = 0 ret = -1, errno = 48 ucred = 803e258 ret = 0, errno = 48 ev.portev_source = 4 ev.portev_events = 1 ev.portev_object = 0 ev.portev_user = 0
Note that pfiles(1)
injects a getpeerucred
call into the target with the help of the agent lwp.
The getpeerucred
call ends up issuing an ioctl on the FIFO. Since the _I_GETPEERCRED
command is not handled by fastpath mode (http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/fs/fifofs/fifovnops.c#1160), the FIFO is converted to a streams mode FIFO. During this conversion, all poll and event ports waiters are awoken to cause them to re-register with the newly converted FIFO (http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/fs/fifofs/fifosubr.c#1108). The kernel stack of a thread waking up all waiters because of the FIFO conversion looks like this:
genunix`port_send_event+0x131 genunix`pollwakeup+0x86 genunix`strpollwakeup+0x20 fifofs`fifo_fastturnoff+0xae fifofs`fifo_fastoff+0x92 fifofs`fifo_fastioctl+0x19d fifofs`fifo_ioctl+0x3d genunix`fop_ioctl+0x55 genunix`getpeerucred+0xff genunix`ucredsys+0x52 genunix`ucredsys32+0x1b unix`sys_syscall32+0xff
This spurious wakeup can cause userspace applications to end up blocking on a subsequent read/write because they were notified that the file descriptor was ready. (This problem has been spotted in the wild: https://github.com/PowerDNS/pdns/issues/2925) The manpages for event ports don't specify whether spurious events are something an application needs to guard against.
As far as I can tell, there appears to be no good reason for fastpath FIFOs to not handle _I_GETPEERCRED
ioctls directly. Attached is a quick patch which appears to work with my quick test.
Files
Related issues
Updated by Josef Sipek almost 8 years ago
- Assignee set to Josef Sipek
- % Done changed from 0 to 60
Updated by Josef Sipek almost 8 years ago
- Subject changed from event ports are broken with FIFOs to getupeercred causes spurious event port wakeups on FIFOs
Updated by Josef Sipek almost 8 years ago
- Related to Bug #6524: event ports are broken with FIFOs added
Updated by Electric Monk over 4 years ago
- Status changed from New to Closed
- % Done changed from 60 to 100
git commit 430c2cddc92582fc7155aaf65c78f0919d7081c1
commit 430c2cddc92582fc7155aaf65c78f0919d7081c1 Author: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Date: 2019-06-18T18:28:37.000Z 6474 getupeercred causes spurious event port wakeups on FIFOs Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Gergő Doma <domag02@gmail.com> Approved by: Robert Mustacchi <rm@joyent.com>