Re: [PATCH] fs: export kern_path_locked
From: Al Viro <viro@zeniv.linux.org.uk>
Date: 2021-02-16 18:01:34
Also in:
lkml
On Tue, Feb 16, 2021 at 05:31:33PM +0300, Denis Kirjanov wrote:
We had a change like that:
Author: WANG Cong [off-list ref]
Date: Mon Jan 23 11:17:35 2017 -0800
af_unix: move unix_mknod() out of bindlock
Dmitry reported a deadlock scenario:
unix_bind() path:
u->bindlock ==> sb_writer
do_splice() path:
sb_writer ==> pipe->mutex ==> u->bindlock
In the unix_bind() code path, unix_mknod() does not have to
be done with u->bindlock held, since it is a pure fs operation,
so we can just move unix_mknod() out.*cringe* I remember now... Process set: P1: bind() of AF_UNIX socket to /mnt/sock P2: splice() from pipe to /mnt/foo P3: freeze /mnt P4: splice() from pipe to AF_UNIX socket P1 grabs ->bindlock P2 sb_start_write() for what's on /mnt P2 grabs rwsem shared P3 blocks in sb_wait_write() trying to grab the same rwsem exclusive P1 sb_start_write() blocks trying to grab the same rwsem shared P4 calls ->splice_write(), aka generic_splice_sendpage() P4 grabs pipe->mutex P4 calls ->sendpage(), aka sock_no_sendpage() P4 calls ->sendmsg(), aka unix_dgram_sendmsg() P4 calls unix_autobind() P4 blocks trying to grab ->bindlock P2 ->splice_write(), aka iter_file_splice_write() P2 blocks trying to grab pipe->mutex DEADLOCK Sigh... OK, so we want something like user_path_create() vfs_mknod() created = true grab bindlock .... drop bindlock if failed && created vfs_unlink() done_path_create() in unix_bind()... That would push ->bindlock all way down in the hierarchy, so that should be deadlock-free, but it looks like that'll be fucking ugly ;-/ Let me try and play with that a bit, maybe it can be massaged to something relatively sane...