Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1538998
| From | Al Viro <viro@ZenIV.linux.org.uk> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | Re: fs, net: deadlock between bind/splice on af_unix |
| Date | 2016-12-09 02:40 +0100 |
| Message-ID | <sMiki-5ep-11@gated-at.bofh.it> (permalink) |
| References | <sM8bg-7j1-33@gated-at.bofh.it> <sM9TI-8om-35@gated-at.bofh.it> <sMgVc-4sj-17@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
On Thu, Dec 08, 2016 at 04:08:27PM -0800, Cong Wang wrote: > On Thu, Dec 8, 2016 at 8:30 AM, Dmitry Vyukov <dvyukov@google.com> wrote: > > Chain exists of: > > Possible unsafe locking scenario: > > > > CPU0 CPU1 > > ---- ---- > > lock(sb_writers#5); > > lock(&u->bindlock); > > lock(sb_writers#5); > > lock(&pipe->mutex/1); > > This looks false positive, probably just needs lockdep_set_class() > to set keys for pipe->mutex and unix->bindlock. I'm afraid that it's not a false positive at all. Preparations: * create an AF_UNIX socket. * set SOCK_PASSCRED on it. * create a pipe. Child 1: splice from pipe to socket; locks pipe and proceeds down towards unix_dgram_sendmsg(). Child 2: splice from pipe to /mnt/foo/bar; requests write access to /mnt and blocks on attempt to lock the pipe already locked by (1). Child 3: freeze /mnt; blocks until (2) is done Child 4: bind() the socket to /mnt/barf; grabs ->bindlock on the socket and proceeds to create /mnt/barf, which blocks due to fairness of freezer (no extra write accesses to something that is in process of being frozen). _Now_ (1) gets around to unix_dgram_sendmsg(). We still have NULL u->addr, since bind() has not gotten through yet. We also have SOCK_PASSCRED set, so we attempt autobind; it blocks on the ->bindlock, which won't be released until bind() is done (at which point we'll see non-NULL u->addr and bugger off from autobind), but bind() won't succeed until /mnt goes through the freeze-thaw cycle, which won't happen until (2) finishes, which won't happen until (1) unlocks the pipe. Deadlock. Granted, ->bindlock is taken interruptibly, so it's not that much of a problem (you can kill the damn thing), but you would need to intervene and kill it. Why do we do autobind there, anyway, and why is it conditional on SOCK_PASSCRED? Note that e.g. for SOCK_STREAM we can bloody well get to sending stuff without autobind ever done - just use socketpair() to create that sucker and we won't be going through the connect() at all.
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
fs, net: deadlock between bind/splice on af_unix Dmitry Vyukov <dvyukov@google.com> - 2016-12-08 15:50 +0100
Re: fs, net: deadlock between bind/splice on af_unix Dmitry Vyukov <dvyukov@google.com> - 2016-12-08 17:40 +0100
Re: fs, net: deadlock between bind/splice on af_unix Cong Wang <xiyou.wangcong@gmail.com> - 2016-12-09 01:10 +0100
Re: fs, net: deadlock between bind/splice on af_unix Al Viro <viro@ZenIV.linux.org.uk> - 2016-12-09 02:40 +0100
Re: fs, net: deadlock between bind/splice on af_unix Cong Wang <xiyou.wangcong@gmail.com> - 2016-12-09 07:40 +0100
Re: fs, net: deadlock between bind/splice on af_unix Al Viro <viro@ZenIV.linux.org.uk> - 2016-12-09 07:50 +0100
csiph-web