Bug 208409
Summary: | segfault in bluetoothd on mouse pairing | ||
---|---|---|---|
Product: | Drivers | Reporter: | David Arroyo (david) |
Component: | Bluetooth | Assignee: | linux-bluetooth (linux-bluetooth) |
Status: | NEW --- | ||
Severity: | normal | ||
Priority: | P1 | ||
Hardware: | Intel | ||
OS: | Linux | ||
Kernel Version: | 5.4.49 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
output of bluetoothd -n -d
btmon trace |
Description
David Arroyo
2020-07-02 05:27:10 UTC
Created attachment 290053 [details]
btmon trace
This appears to be a 'use after free'-type issue. In report_map_read_cb, https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/profiles/input/hog-lib.c?h=5.53&id=1524499483a3678951c0e3059b158836398c4e9b#n950 destroy_gatt_req(req) decrements the reference count for req->hog. When it reaches zero, the call stack destroy_gatt_req -> bt_hog_unref -> bt_hog_free -> bt_hog_detach sets hog->attrib to NULL. Then, later in report_map_read_cb, there is bt_io_get(g_attrib_get_channel(hog->attrib), &gerr, BT_IO_OPT_SOURCE, ev.u.create.phys, BT_IO_OPT_DEST, ev.u.create.uniq, BT_IO_OPT_INVALID); which is invalid if hog's refcount reaches zero. I can see that there is a very common pattern in hog-lib.c: struct bt_hog *hog = req->user_data; ... destroy_gatt_req(req); ... /* Do stuff with hog */ This pattern doesn't seem safe since destroy_gatt_req decrements req->hog's refcount, and several other reference counts. I think the safest thing would be to move destroy_gatt_req to the end of each callback's execution, but I still don't understand the code well enough to be sure. That said, I have a bluetooth keyboard that I can connect to this machine just fine (I'm typing on it now). So clearly some devices do not trigger this behavior. Is the report_map_read_cb callback not triggered by most hardware? The change I described in the previous comment of moving destroy_gatt_req didn't work; the first segfault was avoided, but I eventually got a double-free. Back to the drawing board... |