]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
fusefs: multiple interruptility improvements
authorasomers <asomers@FreeBSD.org>
Wed, 17 Jul 2019 22:45:43 +0000 (22:45 +0000)
committerasomers <asomers@FreeBSD.org>
Wed, 17 Jul 2019 22:45:43 +0000 (22:45 +0000)
commit9b3c8b4203fce6c77b48d6247b886778c1a942da
treea5eb2a4a6f55cf959fac803fcc72d990faabda8d
parente39fa23f1762f8f4d041bb2465717811754757e0
fusefs: multiple interruptility improvements

1) Don't explicitly not mask SIGKILL.  kern_sigprocmask won't allow it to be
   masked, anyway.

2) Fix an infinite loop bug.  If a process received both a maskable signal
   lower than 9 (like SIGINT) and then received SIGKILL,
   fticket_wait_answer would spin.  msleep would immediately return EINTR,
   but cursig would return SIGINT, so the sleep would get retried.  Fix it
   by explicitly checking whether SIGKILL has been received.

3) Abandon the sig_isfatal optimization introduced by r346357.  That
   optimization would cause fticket_wait_answer to return immediately,
   without waiting for a response from the server, if the process were going
   to exit anyway.  However, it's vulnerable to a race:

   1) fatal signal is received while fticket_wait_answer is sleeping.
   2) fticket_wait_answer sends the FUSE_INTERRUPT operation.
   3) fticket_wait_answer determines that the signal was fatal and returns
      without waiting for a response.
   4) Another thread changes the signal to non-fatal.
   5) The first thread returns to userspace.  Instead of exiting, the
      process continues.
   6) The application receives EINTR, wrongly believes that the operation
      was successfully interrupted, and restarts it.  This could cause
      problems for non-idempotent operations like FUSE_RENAME.

Reported by:    kib (the race part)
Sponsored by:   The FreeBSD Foundation
sys/fs/fuse/fuse_ipc.c
sys/kern/kern_sig.c
sys/sys/signalvar.h
tests/sys/fs/fusefs/interrupt.cc