-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Puzzled by HID-over-GATT, feature, report ID #15
Comments
|
I wonder if the original intend was to actually skip the report_id in case there are multiple reports over the same characteristic, which I believe it would be against the spec, so I guess we either have to fix has_report_id to really detect the presence of report_id on the payload or just assume there is never suppose to be a report_id which is basically what you did. |
|
Hi @Vudentz thanks for reading me and for maintaining this project! That would makes sense. I wonder how many client rely on this specific behaviour, I expected plenty, but maybe getting features report are not so common. I would actually not really need it for writing this device driver and was just hacking around when I discovered it. How easy it would be to safely detect if report_id is actually there? |
|
I just ran into this as well - in my case, I have a conformant device that does not include the report ID in the bluetooth characteristic, and as a result the returned report data has the first data byte lost entirely. I suggest that we don't massage the returned buffer, just give back the read bytes as-is. This is perhaps safest as it gives the widest range of compatibility and moves the responsibility of dealing with device-specific quirks upstream where it it more able to handle it. In Linux, that means either the regular As it stands now we have the worst of both worlds: non-compliant devices' data is returned correctly, while compliant devices have the first data byte discarded, breaking user applications. |
|
This should now be resolved by 35a2c50. |
|
Awesome! Thanks @abcminiuser. |
This fixes the following error for invalid read access when registering
filter for incoming messages:
140632==ERROR: AddressSanitizer: stack-buffer-overflow on address...
#0 0x7f60c185741d in MemcmpInterceptorCommon(...
#1 0x7f60c1857af8 in __interceptor_memcmp (/lib64/libasan.so...
#2 0x55a10101536e in find_by_filter mesh/mesh-io-unit.c:494
#3 0x55a1010d8c46 in l_queue_remove_if ell/queue.c:517
#4 0x55a101014ebd in recv_register mesh/mesh-io-unit.c:506
#5 0x55a10102946f in mesh_net_attach mesh/net.c:2885
#6 0x55a101086f64 in send_reply mesh/dbus.c:153
#7 0x55a101124c3d in handle_method_return ell/dbus.c:216
#8 0x55a10112c8ef in message_read_handler ell/dbus.c:276
#9 0x55a1010dae20 in io_callback ell/io.c:120
#10 0x55a1010dff7e in l_main_iterate ell/main.c:478
#11 0x55a1010e06e3 in l_main_run ell/main.c:525
#12 0x55a1010e06e3 in l_main_run ell/main.c:507
#13 0x55a1010e0bfc in l_main_run_with_signal ell/main.c:647
#14 0x55a10100316e in main mesh/main.c:292
#15 0x7f60c0c6855f in __libc_start_call_main (/lib64/libc.so.6+...
#16 0x7f60c0c6860b in __libc_start_main_alias_1 (/lib64/libc.so.6+...
#17 0x55a101003ce4 in _start (/home/istotlan/bluez/mesh/bluetooth-m...
Primary/Secundary Counters are supposed to be 16 bytes values, if the
server has implemented them incorrectly it may lead to the following
crash:
=================================================================
==31860==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x607000001878 at pc 0x7f95a1575638 bp 0x7fff58c6bb80 sp 0x7fff58c6b328
READ of size 48 at 0x607000001878 thread T0
#0 0x7f95a1575637 in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:860
#1 0x7f95a1575ba6 in __interceptor_memcmp ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:892
#2 0x7f95a1575ba6 in __interceptor_memcmp ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:887
#3 0x564df69c77a0 in read_version obexd/client/pbap.c:288
#4 0x564df69c77a0 in read_return_apparam obexd/client/pbap.c:352
#5 0x564df69c77a0 in phonebook_size_callback obexd/client/pbap.c:374
#6 0x564df69bea3c in session_terminate_transfer obexd/client/session.c:921
#7 0x564df69d56b0 in get_xfer_progress_first obexd/client/transfer.c:729
#8 0x564df698b9ee in handle_response gobex/gobex.c:1140
#9 0x564df698cdea in incoming_data gobex/gobex.c:1385
#10 0x7f95a12fdc43 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x55c43)
#11 0x7f95a13526c7 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0xaa6c7)
#12 0x7f95a12fd2b2 in g_main_loop_run (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x552b2)
#13 0x564df6977d41 in main obexd/src/main.c:307
#14 0x7f95a10a7d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#15 0x7f95a10a7e3f in __libc_start_main_impl ../csu/libc-start.c:392
#16 0x564df6978704 in _start (/usr/local/libexec/bluetooth/obexd+0x8b704)
0x607000001878 is located 0 bytes to the right of 72-byte region [0x607000001830,0x607000001878)
allocated by thread T0 here:
#0 0x7f95a1595a37 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
#1 0x564df69c8b6a in pbap_probe obexd/client/pbap.c:1259
This fixes the following crash when a broadcast stream setup is pending and the device is remove: bluetoothd[37]: src/device.c:device_free() 0x89a500 bluetoothd[37]: GLib: Invalid file descriptor. bluetoothd[37]: ++++++++ backtrace ++++++++ bluetoothd[37]: #1 g_logv+0x270 (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557e3120] bluetoothd[37]: #2 g_log+0x93 (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557e3403] bluetoothd[37]: #3 g_io_channel_error_from_errno+0x4a (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557cd9da] bluetoothd[37]: #4 g_io_unix_close+0x53 (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb55839d53] bluetoothd[37]: #5 g_io_channel_shutdown+0x10f (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557cdf7f] bluetoothd[37]: #6 g_io_channel_unref+0x39 (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557ce1e9] bluetoothd[37]: #7 g_source_unref_internal+0x24f (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557db79f] bluetoothd[37]: #8 g_main_context_dispatch+0x288 (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557dd638] bluetoothd[37]: #9 g_main_context_iterate.isra.0+0x318 (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb5583b6b8] bluetoothd[37]: #10 g_main_loop_run+0x7f (/usr/lib64/libglib-2.0.so.0.7600.6) [0x7feb557dcaff] bluetoothd[37]: #11 mainloop_run+0x15 (src/shared/mainloop-glib.c:68) [0x662e65] bluetoothd[37]: #12 mainloop_run_with_signal+0x128 (src/shared/mainloop-notify.c:190) [0x663368] bluetoothd[37]: #13 main+0x154b (src/main.c:1454) [0x41521b] bluetoothd[37]: #14 __libc_start_call_main+0x7a (/usr/lib64/libc.so.6) [0x7feb54e1fb8a] bluetoothd[37]: #15 __libc_start_main@@GLIBC_2.34+0x8b (/usr/lib64/libc.so.6) [0x7feb54e1fc4b] bluetoothd[37]: #16 _start+0x25 (src/main.c:1197) [0x416305] bluetoothd[37]: +++++++++++++++++++++++++++
I have been playing a bit with a HOGP device (microsoft surface dial) under linux and found a strange behavior when using linux's hidraw interface to get and send feature reports. I am sharing this with you because it is puzzling me, and because I might have found a bug in bluez but do not have enough familiarity with Bluetooth stack to recognize it.
What I do:
[255, 0, 1, 3, 1, 80, 0]as payload. This is a totally valid payload for the device, although its meaning does not matter here.What I expect:
The buffer should contain the byte I just sent
[255, 0, 1, 3, 1, 80, 0]as detailed in hidraw docs :What I observe:
The returned buffer contains
[0, 1, 3, 1, 80, 0, 0]. It seems to be shifted by one byte and truncated (255 is not here anymore).I did some investigation, and ended up -- after trying to find anything in linux hidp module 🤦♂️ -- in the implementation of HOGP in bluez.
I found this in
get_report_cb:bluez/profiles/input/hog-lib.c
Lines 823 to 828 in a106a3a
I am not familiar at all with the bluetooth stack so I don't quite understand why the two first bytes are removed from the buffer here. However, this seems to be the only place that could cause my issue in the entire stack.
After digging a bit more, I also read here that in the case of HOGP, the report id of HID are not serialized with the data sent over the air. (which I also kind of decrypt from the section 4.8.1 of the HOGP spec but it is not clear).
That makes me wonder if the report_id is really present in
pdubuffer, and if the code should rather be:--len; ++pdu; // the following is useless as the HID is not returned over GATT //if (hog->has_report_id && len > 0) { // --len; // ++pdu; //}And indeed, testing this gives me the expected behavior.
This solution looks very hacky dark magic to me : I guess such a deep change in the stack would break other things.
What do you think? Should I look elsewhere? The only alternative I can think of is that I am dealing with a non-compliant device. 🙃
The following python code snippet can be used to reproduce. It will be surely not useful for someone without the device, posting it for completeness.
print
The text was updated successfully, but these errors were encountered: