af_unix: fix unix_dgram_recvmsg entry locking
authorRainer Weikusat <rweikusat@mobileactivedefense.com>
Sun, 6 Dec 2015 21:11:38 +0000 (21:11 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Dec 2015 04:31:54 +0000 (23:31 -0500)
commit64874280889e7c0b2c9266705363627d4c92cf01
tree2e7d955b8093dbd3cfc80a68ae1e4c648a34e74f
parentea3793ee29d3621faf857fa8ef5425e9ff9a756d
af_unix: fix unix_dgram_recvmsg entry locking

The current unix_dgram_recvsmg code acquires the u->readlock mutex in
order to protect access to the peek offset prior to calling
__skb_recv_datagram for actually receiving data. This implies that a
blocking reader will go to sleep with this mutex held if there's
presently no data to return to userspace. Two non-desirable side effects
of this are that a later non-blocking read call on the same socket will
block on the ->readlock mutex until the earlier blocking call releases it
(or the readers is interrupted) and that later blocking read calls
will wait longer than the effective socket read timeout says they
should: The timeout will only start 'ticking' once such a reader hits
the schedule_timeout in wait_for_more_packets (core.c) while the time it
already had to wait until it could acquire the mutex is unaccounted for.

The patch avoids both by using the __skb_try_recv_datagram and
__skb_wait_for_more packets functions created by the first patch to
implement a unix_dgram_recvmsg read loop which releases the readlock
mutex prior to going to sleep and reacquires it as needed
afterwards. Non-blocking readers will thus immediately return with
-EAGAIN if there's no data available regardless of any concurrent
blocking readers and all blocking readers will end up sleeping via
schedule_timeout, thus honouring the configured socket receive timeout.

Signed-off-by: Rainer Weikusat <rweikusat@mobileactivedefense.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/unix/af_unix.c