1
0
Fork 0
remarkable-linux/net/unix
Rainer Weikusat 272d474fc6 af_unix: Fix splice-bind deadlock
[ Upstream commit c845acb324 ]

On 2015/11/06, Dmitry Vyukov reported a deadlock involving the splice
system call and AF_UNIX sockets,

http://lists.openwall.net/netdev/2015/11/06/24

The situation was analyzed as

(a while ago) A: socketpair()
B: splice() from a pipe to /mnt/regular_file
	does sb_start_write() on /mnt
C: try to freeze /mnt
	wait for B to finish with /mnt
A: bind() try to bind our socket to /mnt/new_socket_name
	lock our socket, see it not bound yet
	decide that it needs to create something in /mnt
	try to do sb_start_write() on /mnt, block (it's
	waiting for C).
D: splice() from the same pipe to our socket
	lock the pipe, see that socket is connected
	try to lock the socket, block waiting for A
B:	get around to actually feeding a chunk from
	pipe to file, try to lock the pipe.  Deadlock.

on 2015/11/10 by Al Viro,

http://lists.openwall.net/netdev/2015/11/10/4

The patch fixes this by removing the kern_path_create related code from
unix_mknod and executing it as part of unix_bind prior acquiring the
readlock of the socket in question. This means that A (as used above)
will sb_start_write on /mnt before it acquires the readlock, hence, it
won't indirectly block B which first did a sb_start_write and then
waited for a thread trying to acquire the readlock. Consequently, A
being blocked by C waiting for B won't cause a deadlock anymore
(effectively, both A and B acquire two locks in opposite order in the
situation described above).

Dmitry Vyukov(<dvyukov@google.com>) tested the original patch.

Signed-off-by: Rainer Weikusat <rweikusat@mobileactivedefense.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
2016-07-09 00:16:18 -04:00
..
Kconfig net: Default UDP and UNIX diag to 'n'. 2012-01-07 12:13:06 -08:00
Makefile unix_diag: Write it into kbuild 2011-12-16 13:48:29 -05:00
af_unix.c af_unix: Fix splice-bind deadlock 2016-07-09 00:16:18 -04:00
diag.c unix_diag: fix incorrect sign extension in unix_lookup_by_ino 2016-03-04 10:25:51 -05:00
garbage.c unix: correctly track in-flight fds in sending process user_struct 2016-03-04 10:25:48 -05:00
sysctl_net_unix.c net: Convert uses of typedef ctl_table to struct ctl_table 2013-06-13 02:36:09 -07:00