This addresses the following issue: if the program exits
after bt_shell_init() has been called, but prior to calling
bt_shell_run() (e.g., failing to start meshctl due to invalid
input configuration), the original shell is messed up after that.
Calling bt_shell_cleanup() on faiure fixes this.
Since mainloop_run() overwrites the exit_status variable even if having
called mainloop_{quit,exit_*}(), such as in case executing btmgmt with
an invalid command, it is initialized in declaration.
This allows to configure bluetoothd to require minimum encryption key
size when accessing GATT server characteristics. It is a global
configuration option affecting whole GATT database.
We should mark service as completed before trying to insert another
characteristic - in case inserting characteristic for new service
fails, previous one won't be discarded.
If local cache of peer's database has gaps where new services appear
after reconnection, GATT client will attempt to discover all included
services and characteristics definitions between starting handle of
first service and end handle of last service. This means the result
will contain also attributes which are already present in active
services in local database and thus attempting to add them again will
fail.
To fix this, instead of discovering whole range we'll only discover
ranges for missing services - starting with included services then
characteristics. To optimize this process we'll merge ranges of
adjacent services and any empty spaces in between - the result is
basically set of ranges without any known service. In most cases this
works the same or very similar to current implementation.
This issue can sometimes be observed with iOS devices as ANCS and CTS
services may not be available all the time.
This releases resources used for shell initialization.
This is needed as a separate function to enable clean shutdown
when an application needs to exit prior to calling bt_shell_run(),
e.g., when failing program initialization based on processed command
line input options.
Returns the FAILURE status since there is no meaning of stay in
non-interactive mode when executing some commands with an invalid
argument or with no controller. Also returns with the SUCCESS status
when getting a scan filtering value or disconnecting a non-default
device.
The index value used for detecting and validating a short option
was not reset after processing a first short option.
This prevented the correct parsing of additional short options.
Fixed by resetting the index value back to original after each
iteration.
This patch adds handling of invalid offset error for gatt database in
case if offset in read blob would be invalid.
"The Read Blob Request is repeated until the Read Blob Response’s Part
Attribute Value parameter is zero or an Error Response is sent by the server
with the Error Code set to Invalid Offset." Bluetooth Core 5.0, 4.12.2
"If the prepare Value Offset is greater than the current length of the attribute
value then all pending prepare write values shall be discarded for this client,
the queue shall be cleared and then an Error Response shall be sent with the
«Invalid Offset»." Bluetooth Core 5.0, 3.4.6.3
While value has more than single MTU can carry long read procedure will
be triggered. In such cases offset need to bo considered while getting
value from storage.
In read_pipe function there was a mishandled case when the msg has
more than one segment. As a result e.g. after provisioning the
capabilities discovery was incorrect parsed.
Since asprintf() allocates new memory when a submenu command is
complemented, the memory leak occurs as below:
8 bytes in 1 blocks are definitely lost in loss record 18 of 179
at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5679C99: strdup (strdup.c:42)
by 0x13B1E7: find_cmd.constprop.2 (shell.c:597)
by 0x13B2D1: cmd_generator (shell.c:646)
by 0x53B976D: rl_completion_matches (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13BA91: shell_completion (shell.c:777)
by 0x53B98B6: ??? (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B9A99: rl_complete_internal (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B02EE: _rl_dispatch_subseq (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B07B5: readline_internal_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53C8F84: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13AD80: input_read (shell.c:1065)
Explicitly returns NULL if asprintf() fails, since the asprintf(3)
man-page says that the contents of the first argument are undefined if
any error occurs.
On device disconnection, net session is not closed. On next
attempt to provision/connect a device, net session proxy is
not updated by net_session_open() as proxy_in is not NULL.
This causes meshctl to use invalid proxy resulting in below
crash.
0 strlen () at ../sysdeps/x86_64/strlen.S:106
1 0x00007f3a3c8b1ac4 in _dbus_string_init_const () from libdbus-1.so.3
2 0x00007f3a3c89ed15 in ?? () from libdbus-1.so.3
3 0x00007f3a3c89fba0 in dbus_message_new_method_call () from libdbus-1.so.3
4 0x0000000000419880 in g_dbus_proxy_method_call at gdbus/client.c:997
5 0x000000000040ab9d in mesh_gatt_write at mesh/gatt.c:347
6 0x000000000040d761 in send_mesh_pkt at mesh/net.c:1227
7 send_seg at mesh/net.c:1325
8 0x000000000040fa60 in net_access_layer_send at mesh/net.c:2163
9 0x0000000000413c74 in config_send at mesh/config-client.c:418
10 0x0000000000414886 in cmd_composition_get at mesh/config-client.c:470
11 0x000000000041ffd9 in cmd_exec at src/shared/shell.c:356
12 menu_exec at src/shared/shell.c:383
13 0x00000000004203a5 in shell_exec at src/shared/shell.c:426
14 0x0000000000420d24 in rl_handler (input=0x2259aa0 "composition-get ")
at src/shared/shell.c:571
15 0x00007f3a3c45d6f5 in rl_callback_read_char () from libreadline.so.6
16 0x0000000000420229 in input_read at src/shared/shell.c:1034
17 0x0000000000421655 in watch_callback at src/shared/io-glib.c:170
18 0x00007f3a3cb1a04a in g_main_context_dispatch () from libglib-2.0.so.0
19 0x00007f3a3cb1a3f0 in ?? () from libglib-2.0.so.0
20 0x00007f3a3cb1a712 in g_main_loop_run () from libglib-2.0.so.0
21 0x0000000000421bf5 in mainloop_run () at src/shared/mainloop-glib.c:73
22 0x000000000042115a in bt_shell_run () at src/shared/shell.c:962
23 0x0000000000405c5d in main at mesh/main.c:1992
This enables command generator to work with submenu commands like:
[bluetooth]# advertise.
advertise.appearance advertise.manufacturer advertise.timeout
advertise.clear advertise.name advertise.tx-power
advertise.duration advertise.service advertise.uuids
Note that by default submenus commands will not be shown until . is
present in the input, that way only one command list is active at time.
If a service was removed an no other service was added it may happen
that pending_svc has not empty but first_svc and last_svc has not been
set causing the following request:
< ACL Data TX: Handle 76 flags 0x00 dlen 11
ATT: Read By Type Request (0x08) len 6
Handle range: 0x0000-0x0000
Attribute type: Include (0x2802)
If the error returned is either BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND or
BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE the discovery shall be marked as
successful and no error shall be printed.
When read multiple includes external characteristic, call to
gatt_db_attribute_read's complete callback is asynchronous.
Fix following crash:
Use of uninitialised value of size 8
at 0x49718A: read_multiple_complete_cb (gatt-server.c:994)
by 0x498999: pending_read_result (gatt-db.c:136)
by 0x49A84B: gatt_db_attribute_read_result (gatt-db.c:1787)
by 0x451F4C: read_reply_cb (gatt-database.c:1712)
by 0x48B221: method_call_reply (client.c:972)
by 0x53AB601: ??? (in /usr/lib64/libdbus-1.so.3.19.3)
by 0x53AEF7E: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.3)
by 0x486FEF: message_dispatch (mainloop.c:72)
by 0x50CB576: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
by 0x50CEB76: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.5400.3)
by 0x50CEF1F: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
by 0x50CF231: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.5400.3)
Invalid read of size 8
at 0x49718A: read_multiple_complete_cb (gatt-server.c:994)
by 0x498999: pending_read_result (gatt-db.c:136)
by 0x49A84B: gatt_db_attribute_read_result (gatt-db.c:1787)
by 0x451F4C: read_reply_cb (gatt-database.c:1712)
by 0x48B221: method_call_reply (client.c:972)
by 0x53AB601: ??? (in /usr/lib64/libdbus-1.so.3.19.3)
by 0x53AEF7E: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.19.3)
by 0x486FEF: message_dispatch (mainloop.c:72)
by 0x50CB576: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
by 0x50CEB76: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.5400.3)
by 0x50CEF1F: ??? (in /usr/lib64/libglib-2.0.so.0.5400.3)
by 0x50CF231: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.5400.3)
Address 0x8 is not stack'd, malloc'd or (recently) free'd
When disconnecting the channel queue shall not be destroyed before
freeeing all requests including those that already have been processed
otherwise the following crash may happen:
4 errors in context 2 of 103:
Invalid read of size 4
at 0x12A5C2: control_req_destroy (avctp.c:762)
by 0x12A539: pending_destroy (avctp.c:517)
by 0x48A0D48: g_slist_foreach (in /usr/lib/libglib-2.0.so.0.3600.0)
by 0x12A77B: avctp_channel_destroy (avctp.c:553)
by 0x12A801: avctp_disconnected (avctp.c:570)
by 0x12A0F1: control_disconnect (control.c:134)
by 0x1306B9: avrcp_disconnect (avrcp.c:4471)
by 0x17DAE9: btd_service_disconnect (service.c:307)
by 0x18437D: dev_disconn_service (device.c:1405)
by 0x48A0D48: g_slist_foreach (in /usr/lib/libglib-2.0.so.0.3600.0)
by 0x187D87: device_request_disconnect (device.c:1437)
by 0x187EC6: dev_disconnect (device.c:1522)
Address 0x4fde068 is 0 bytes inside a block of size 16 free'd
at 0x48252B3: free (vg_replace_malloc.c:446)
by 0x4888172: g_free (in /usr/lib/libglib-2.0.so.0.3600.0)
by 0x12AB64: avctp_queue_destroy (avctp.c:537)
by 0x48A0D48: g_slist_foreach (in /usr/lib/libglib-2.0.so.0.3600.0)
by 0x48A0D91: g_slist_free_full (in /usr/lib/libglib-2.0.so.0.3600.0)
by 0x12A75E: avctp_channel_destroy (avctp.c:552)
by 0x12A801: avctp_disconnected (avctp.c:570)
by 0x12A0F1: control_disconnect (control.c:134)
by 0x1306B9: avrcp_disconnect (avrcp.c:4471)
by 0x17DAE9: btd_service_disconnect (service.c:307)
by 0x18437D: dev_disconn_service (device.c:1405)
by 0x48A0D48: g_slist_foreach (in /usr/lib/libglib-2.0.so.0.3600.0)
This sets the we_offs variable to zero before do wordfree(). Since it
frees from the elements of the we_wordv array pointed to by the we_offs
variable, memory leak occurs as below:
101 bytes in 1 blocks are definitely lost in loss record 122 of 184
at 0x4C2FA3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x4C31D84: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x56E7CD2: w_addchar (wordexp.c:104)
by 0x56E7CD2: parse_dquote (wordexp.c:2200)
by 0x56E7CD2: wordexp (wordexp.c:2349)
by 0x13A6A5: parse_args (shell.c:262)
by 0x13A94D: cmd_exec (shell.c:313)
by 0x13A94D: menu_exec (shell.c:375)
by 0x13AEA4: shell_exec (shell.c:418)
by 0x13BBF1: rl_handler (shell.c:563)
by 0x53C8D72: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13ACE0: input_read (shell.c:1018)
by 0x13C90A: watch_callback (io-glib.c:170)
by 0x4E86E24: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x4E871EF: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
117 (16 direct, 101 indirect) bytes in 1 blocks are definitely lost in loss record 125 of 184
at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x56E81C3: w_addword (wordexp.c:182)
by 0x56E81C3: wordexp (wordexp.c:2447)
by 0x13A6A5: parse_args (shell.c:262)
by 0x13B55A: args_completion (shell.c:656)
by 0x13B55A: menu_completion (shell.c:695)
by 0x13B836: shell_completion (shell.c:723)
by 0x53B98B6: ??? (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B9A99: rl_complete_internal (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B02EE: _rl_dispatch_subseq (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B07B5: readline_internal_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53C8F84: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13ACE0: input_read (shell.c:1018)
by 0x13C90A: watch_callback (io-glib.c:170)
When running the command having mandatory arguments, memory leak occurs
as below:
1 bytes in 1 blocks are definitely lost in loss record 2 of 184
at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5679C99: strdup (strdup.c:42)
by 0x13A976: cmd_exec (shell.c:327)
by 0x13A976: menu_exec (shell.c:375)
by 0x13AEA4: shell_exec (shell.c:418)
by 0x13BBF1: rl_handler (shell.c:563)
by 0x53C8D72: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13ACE0: input_read (shell.c:1018)
by 0x13C90A: watch_callback (io-glib.c:170)
by 0x4E86E24: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x4E871EF: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x4E87501: g_main_loop_run (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x13D244: mainloop_run (mainloop-glib.c:73)
7 bytes in 1 blocks are definitely lost in loss record 12 of 184
at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5679C99: strdup (strdup.c:42)
by 0x139EEA: strdelimit (util.c:991)
by 0x13B66A: args_completion (shell.c:668)
by 0x13B66A: menu_completion (shell.c:695)
by 0x13B836: shell_completion (shell.c:723)
by 0x53B98B6: ??? (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B9A99: rl_complete_internal (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B02EE: _rl_dispatch_subseq (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B07B5: readline_internal_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53C8F84: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13ACE0: input_read (shell.c:1018)
by 0x13C90A: watch_callback (io-glib.c:170)
9 bytes in 1 blocks are definitely lost in loss record 21 of 184
at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5679C99: strdup (strdup.c:42)
by 0x13B53F: args_completion (shell.c:654)
by 0x13B53F: menu_completion (shell.c:695)
by 0x13B836: shell_completion (shell.c:723)
by 0x53B98B6: ??? (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B9A99: rl_complete_internal (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B02EE: _rl_dispatch_subseq (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53B07B5: readline_internal_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x53C8F84: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13ACE0: input_read (shell.c:1018)
by 0x13C90A: watch_callback (io-glib.c:170)
by 0x4E86E24: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
9 bytes in 1 blocks are definitely lost in loss record 22 of 184
at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5679CE9: strndup (strndup.c:43)
by 0x13A9EB: cmd_exec (shell.c:301)
by 0x13A9EB: menu_exec (shell.c:375)
by 0x13AEA4: shell_exec (shell.c:418)
by 0x13BBF1: rl_handler (shell.c:563)
by 0x53C8D72: rl_callback_read_char (in /lib/x86_64-linux-gnu/libreadline.so.7.0)
by 0x13ACE0: input_read (shell.c:1018)
by 0x13C90A: watch_callback (io-glib.c:170)
by 0x4E86E24: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x4E871EF: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x4E87501: g_main_loop_run (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.1)
by 0x13D244: mainloop_run (mainloop-glib.c:73)