1. 05 Jun, 2018 5 commits
    • Guillaume Nault's avatar
      l2tp: fix refcount leakage on PPPoL2TP sockets · 3d609342
      Guillaume Nault authored
      Commit d02ba2a6 ("l2tp: fix race in pppol2tp_release with session
      object destroy") tried to fix a race condition where a PPPoL2TP socket
      would disappear while the L2TP session was still using it. However, it
      missed the root issue which is that an L2TP session may accept to be
      reconnected if its associated socket has entered the release process.
      
      The tentative fix makes the session hold the socket it is connected to.
      That saves the kernel from crashing, but introduces refcount leakage,
      preventing the socket from completing the release process. Once stalled,
      everything the socket depends on can't be released anymore, including
      the L2TP session and the l2tp_ppp module.
      
      The root issue is that, when releasing a connected PPPoL2TP socket, the
      session's ->sk pointer (RCU-protected) is reset to NULL and we have to
      wait for a grace period before destroying the socket. The socket drops
      the session in its ->sk_destruct callback function, so the session
      will exist until the last reference on the socket is dropped.
      Therefore, there is a time frame where pppol2tp_connect() may accept
      reconnecting a session, as it only checks ->sk to figure out if the
      session is connected. This time frame is shortened by the fact that
      pppol2tp_release() calls l2tp_session_delete(), making the session
      unreachable before resetting ->sk. However, pppol2tp_connect() may
      grab the session before it gets unhashed by l2tp_session_delete(), but
      it may test ->sk after the later got reset. The race is not so hard to
      trigger and syzbot found a pretty reliable reproducer:
      https://syzkaller.appspot.com/bug?id=418578d2a4389074524e04d641eacb091961b2cf
      
      Before d02ba2a6, another race could let pppol2tp_release()
      overwrite the ->__sk pointer of an L2TP session, thus tricking
      pppol2tp_put_sk() into calling sock_put() on a socket that is different
      than the one for which pppol2tp_release() was originally called. To get
      there, we had to trigger the race described above, therefore having one
      PPPoL2TP socket being released, while the session it is connected to is
      reconnecting to a different PPPoL2TP socket. When releasing this new
      socket fast enough, pppol2tp_release() overwrites the session's
      ->__sk pointer with the address of the new socket, before the first
      pppol2tp_put_sk() call gets scheduled. Then the pppol2tp_put_sk() call
      invoked by the original socket will sock_put() the new socket,
      potentially dropping its last reference. When the second
      pppol2tp_put_sk() finally runs, its socket has already been freed.
      
      With d02ba2a6, the session takes a reference on both sockets.
      Furthermore, the session's ->sk pointer is reset in the
      pppol2tp_session_close() callback function rather than in
      pppol2tp_release(). Therefore, ->__sk can't be overwritten and
      pppol2tp_put_sk() is called only once (l2tp_session_delete() will only
      run pppol2tp_session_close() once, to protect the session against
      concurrent deletion requests). Now pppol2tp_put_sk() will properly
      sock_put() the original socket, but the new socket will remain, as
      l2tp_session_delete() prevented the release process from completing.
      Here, we don't depend on the ->__sk race to trigger the bug. Getting
      into the pppol2tp_connect() race is enough to leak the reference, no
      matter when new socket is released.
      
      So it all boils down to pppol2tp_connect() failing to realise that the
      session has already been connected. This patch drops the unneeded extra
      reference counting (mostly reverting d02ba2a6) and checks that
      neither ->sk nor ->__sk is set before allowing a session to be
      connected.
      
      Fixes: d02ba2a6 ("l2tp: fix race in pppol2tp_release with session object destroy")
      Signed-off-by: default avatarGuillaume Nault <g.nault@alphalink.fr>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      3d609342
    • David S. Miller's avatar
      Merge branch 'net-phy-improve-PM-handling-of-PHY-MDIO' · 7a723099
      David S. Miller authored
      Heiner Kallweit says:
      
      ====================
      net: phy: improve PM handling of PHY/MDIO
      
      Current implementation of MDIO bus PM ops doesn't actually implement
      bus-specific PM ops but just calls PM ops defined on a device level
      what doesn't seem to be fully in line with the core PM model.
      
      When looking e.g. at __device_suspend() the PM core looks for PM ops
      of a device in a specific order:
      1. device PM domain
      2. device type
      3. device class
      4. device bus
      
      I think it has good reason that there's no PM ops on device level.
      The situation can be improved by modeling PHY's as device type of
      a MDIO device. If for some other type of MDIO device PM ops are
      needed, it could be modeled as struct device_type as well.
      ====================
      Tested-by: default avatarAndrew Lunn <andrew@lunn.ch>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      7a723099
    • Heiner Kallweit's avatar
      net: phy: remove PM ops from MDIO bus · 9107c05e
      Heiner Kallweit authored
      Current implementation of MDIO bus PM ops doesn't actually implement
      bus-specific PM ops but just calls PM ops defined on a device level
      what doesn't seem to be fully in line with the core PM model.
      
      When looking e.g. at __device_suspend() the PM core looks for PM ops
      of a device in a specific order:
      1. device PM domain
      2. device type
      3. device class
      4. device bus
      
      I think it has good reason that there's no PM ops on device level.
      
      Now that a device type representation of PHY's as special type of MDIO
      devices was added (only user of MDIO bus PM ops), the MDIO bus
      PM ops can be removed including member pm of struct mdio_device.
      
      If for some other type of MDIO device PM ops are needed, it should be
      modeled as struct device_type as well.
      Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      9107c05e
    • Heiner Kallweit's avatar
      net: phy: add struct device_type representation of a PHY · 7f4828ff
      Heiner Kallweit authored
      A PHY is a type of MDIO device, so let's model it as struct device_type
      and place PM ops, attribute groups and release callback on device type
      level. For this the attribute definitions have to be moved.
      This change allows us to get rid of the PM ops on a bus level in a second
      step.
      Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      7f4828ff
    • David S. Miller's avatar
  2. 04 Jun, 2018 35 commits