]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/commit
Merge r241129:
authorglebius <glebius@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>
Thu, 11 Oct 2012 01:32:51 +0000 (01:32 +0000)
committerglebius <glebius@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>
Thu, 11 Oct 2012 01:32:51 +0000 (01:32 +0000)
commitc6359ac155caa29d69287c61411f035ec4e3603e
tree8194eafabc6494dc72aec3d13cc79d517d67e412
parent69ab82fe2980c0c7f78b2a63b641e05ff412a465
Merge r241129:
  There is a complex race in in_pcblookup_hash() and in_pcblookup_group().
  Both functions need to obtain lock on the found PCB, and they can't do
  classic inter-lock with the PCB hash lock, due to lock order reversal.
  To keep the PCB stable, these functions put a reference on it and after PCB
  lock is acquired drop it. If the reference was the last one, this means
  we've raced with in_pcbfree() and the PCB is no longer valid.

    This approach works okay only if we are acquiring writer-lock on the PCB.
  In case of reader-lock, the following scenario can happen:

    - 2 threads locate pcb, and do in_pcbref() on it.
    - These 2 threads drop the inp hash lock.
    - Another thread comes to delete pcb via in_pcbfree(), it obtains hash
      lock,   does in_pcbremlists(), drops hash lock, and runs
      in_pcbrele_wlocked(), which  doesn't free the pcb due to two references
      on it. Then it unlocks the pcb.
    - 2 aforementioned threads acquire reader lock on the pcb and run
      in_pcbrele_rlocked(). One gets 1 from in_pcbrele_rlocked() and continues,
      second gets 0 and considers pcb freed, returns.
    - The thread that got 1 continutes working with detached pcb, which later
      leads to panic in the underlying protocol level.

    To plumb that problem an additional INPCB flag introduced - INP_FREED. We
  check for that flag in the in_pcbrele_rlocked() and if it is set, we pretend
  that that was the last reference.

  Discussed with: rwatson, jhb
  Reported by: Vladimir Medvedkin <medved rambler-co.ru>

git-svn-id: svn://svn.freebsd.org/base/stable/9@241435 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
sys/netinet/in_pcb.c
sys/netinet/in_pcb.h