Re: [PATCH 00/16] Rewrite HIDP Session Management

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2013-03-12 at 18:24 +0100, David Herrmann wrote:
> ping?
> 

I looked over the patches, and they seemed sensible to me. Thanks for
the good work!

Regards
Karl

> On Sun, Feb 24, 2013 at 7:36 PM, David Herrmann <dh.herrmann@xxxxxxxxx> wrote:
> > Hi
> >
> > If anyone tested "hotplugging" with HIDP in the last years, there's a 50% chance
> > you get an oops when "unplugging" devices. I never got around fixing it until
> > now. I took the time to thoroughly review HIDP, hci_dev and hci_conn
> > interaction and it turned out to be totally broken. The thing is that HIDP
> > highly depends on the underlying hci_conn object. However, there is no way to
> > notify HIDP when the connection is shut down. So this is where I started fixing
> > things.
> >
> > First, a list of bugs that all played together and are mostly fixed in this
> > series:
> >
> > * hci_conn use after free:
> >   hci_conn_del() calls hci_conn_put_device() which might call
> >   hci_conn_del_sysfs(), which itself calls put_device() which might call
> >   bt_link_release() which calls kfree(hci_conn).
> >   That is, the "conn->handle" check in hci_conn_del() dereferences "conn" after
> >   it has been freed.
> >   Note that the "might"-case is the usual case. So this is a real bug.
> >
> > * kfree() after device_initialize()
> >   During hci_conn_add() we call hci_conn_init_sysfs() which calls
> >   device_initialize() on hci_conn. However, if we never call
> >   hci_conn_add_sysfs(), then hci_conn_del() will not use "put_device()" to drop
> >   the reference but instead call kfree(hci_conn).
> >   This is not allowed (see documentation for device_initialize()).
> >
> > * ref-count for device_del()
> >   We use a "devcnt" reference-count in every hci_conn structure which controls
> >   when we call device_del(hci_conn). This isn't a but itself, but discouraged
> >   behavior. device_del() is supposed to be called when the (virtual) hardware
> >   of the device goes away. So when the hci-connection is closed, we are supposed
> >   to call device_del() immediately. If the direct call to device_del()
> >   introduces bugs, we _must_ fix the bugs instead of delaying
> >   device_del(). The correct fix is to notify all childs that the
> >   device goes away (they can now call device_del(child)) and then call
> >   device_del() afterwards. But this needs to be done synchronously.
> >
> > * device_find_child() + device_move()
> >   This is really wrong. When an hci_conn object goes away, we move all it's
> >   childs to the root node. The code doesn't have a comment to say _why_ we do
> >   this bug digging in commit-messages it said that client RFCOMM-TTY devices
> >   might have a reason to stay alive even though the hci_conn is gone.
> >   Could anyone please tell me _one_ reason, why an RFCOMM-TTY object should stay
> >   even though the hci_conn is gone?
> >
> > * hci_conn use after free
> >   If an hci_conn is grabbed via hci_conn_hold_device(), but the connection
> >   hasn't been added to user-space, yet, then hci_conn_del() might call kfree()
> >   on the device, even though a later call to hci_conn_put_device() will still
> >   access it.
> >   This is a theoretical bug as we have other means to avoid it. But it's still
> >   ugly.
> >
> > * hci_conn_put() called more often than hci_conn_hold()
> >   I added a debug-print to hci_conn_put() and the ref-count dropped below 0
> >   everytime I disconnected a device. It doesn't break anything, but we really
> >   should avoid this!
> >
> > * hci_conn_put_device() doesn't take the parent hci_dev into account.
> >   So the bug we tried to fix with _hold/put_device(), comes up again if we
> >   unplug the adapter instead of disconnecting the remote device.
> >
> > * HIDP doesn't consider "terminate" in wait-conditions
> >   No wait-condition in HIDP watches for "terminate" to become non-zero, even
> >   though it is a _very_ likely condition to terminate HIDP.
> >
> > * HIDP removes the HID/input devices asynchronously from within the session
> >   instead of synchronously when the connection goes down. This causes the
> >   session-thread to use the connection even though it's gone.
> >
> > That's all I can remember for now, but there's some more small bugs that I fixed
> > together with the session-rewrite.
> >
> > This series includes some small fixes/cleanups that can be applied right away
> > (which would simplify this series a lot). The other patches depend on each other
> > so they cannot be cherry-picked.
> >
> > I tested this series and it works perfectly well. 10 connect/disconnect
> > cycles worked without a bug. I can shut down the device, unplug the adapter or
> > do an explicit disconnect without an oops.
> > I haven't tested suspend/resume, yet, though.
> >
> > Please review!
> > Thanks
> > David
> >
> >
> > Overview:
> >
> > Patch 1-3: They remove a bogus return-code in bt_sock_unregister() which doesn't
> >            make sense to me.
> >
> > Patch 4: Add is_l2cap_socket() which allows HIDP to verify that the passed
> >          sockets are real l2cap sockets.
> >
> > Patch 5-7: Introduce ref-counting for hci_conn objects so we can have a
> >            reference to them in the HIDP session. Note that we cannot reuse the
> >            current "refcnt" as this is used for something totally differen: It
> >            counts the number of active users on the underlying connection. It
> >            doesn't ref-count the hci_conn object itself!
> >
> > Patch 8-10: Some small HIDP and HCI-core fixes
> >
> > Patch 11: Add l2cap_sock_get_hci_conn() helper to allow HIDP to use l2cap
> >           sockets and retrieve the underlying hci_conn object instead of using
> >           an unnecessary hash-table lookup.
> >
> > Patch 12: Add hci_conn_user objects. This allows external protocols to bind to
> >           an hci_conn object and get notified whenever the connection is closed
> >           and unlinked from sysfs.
> >
> > Patch 13: Small HIDP cleanup patch
> >
> > Patch 14-15: Rewrite the HIDP session-management based on hci_conn_user objects.
> >              I haven't found an easy way to do this in many small patches as the
> >              new session-management is totally different than the previous one.
> >              Hence, I first add the new helpers and then remove the old helpers
> >              and do the switch in a follow-up patch. This makes reviewing
> >              easier.
> >
> > Patch 16: Again a small fix for HIDP that uses the new session-management
> >           helpers.
> >
> > David Herrmann (16):
> >   Bluetooth: discard bt_sock_unregister() errors
> >   Bluetooth: change bt_sock_unregister() to return void
> >   Bluetooth: hidp: simplify error path in sock-init
> >   Bluetooth: hidp: verify l2cap sockets
> >   Bluetooth: rename hci_conn_put to hci_conn_drop
> >   Bluetooth: remove unneeded hci_conn_hold/put_device()
> >   Bluetooth: introduce hci_conn ref-counting
> >   Bluetooth: hidp: remove unused session->state field
> >   Bluetooth: hidp: test "terminate" before sleeping
> >   Bluetooth: allow constant arguments for bacmp()/bacpy()
> >   Bluetooth: l2cap: add l2cap_sock_get_hci_conn() helper
> >   Bluetooth: add hci_conn_user sub-modules
> >   Bluetooth: hidp: move hidp_schedule() to core.c
> >   Bluetooth: hidp: add new session-management helpers
> >   Bluetooth: hidp: remove old session-management
> >   Bluetooth: hidp: handle kernel_sendmsg() errors correctly
> >
> >  include/net/bluetooth/bluetooth.h |   6 +-
> >  include/net/bluetooth/hci_core.h  |  46 ++-
> >  include/net/bluetooth/l2cap.h     |   2 +
> >  net/bluetooth/af_bluetooth.c      |  15 +-
> >  net/bluetooth/bnep/sock.c         |   4 +-
> >  net/bluetooth/cmtp/sock.c         |   4 +-
> >  net/bluetooth/hci_conn.c          |  92 ++++-
> >  net/bluetooth/hci_event.c         |  40 +-
> >  net/bluetooth/hci_sock.c          |   4 +-
> >  net/bluetooth/hci_sysfs.c         |   1 -
> >  net/bluetooth/hidp/core.c         | 787 +++++++++++++++++++++++++-------------
> >  net/bluetooth/hidp/hidp.h         |  67 ++--
> >  net/bluetooth/hidp/sock.c         |  35 +-
> >  net/bluetooth/l2cap_core.c        |   6 +-
> >  net/bluetooth/l2cap_sock.c        |  31 +-
> >  net/bluetooth/mgmt.c              |   6 +-
> >  net/bluetooth/rfcomm/sock.c       |   3 +-
> >  net/bluetooth/sco.c               |   9 +-
> >  net/bluetooth/smp.c               |   2 +-
> >  19 files changed, 737 insertions(+), 423 deletions(-)
> >
> > --
> > 1.8.1.4


--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux