Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Bluetooth share has stopped working" when performing LeScan

I have a bunch of various Android phones in front of me all running 4.3/4.4 and they all seem to be suffering from some bug in Bluetooth. The app I am running is simply scanning for other bluetooth devices around it using this callback: http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html

Just LogCatting the data and still having problems...

Does anyone know about this bug and have a fix for it? I really need to get bluetooth scanning stable for a deadline I have tomorrow for a demo of my application...

Thanks.

EDIT: Supposedly in 4.4.3 (or 4.4.4) this was resolved. (Of course the day of our presentation for the project...did us no good). The main issue was the XML file keeping track of mac addresses growing over the size of 2000 and then crashing...a system reset would clear the xml file, thus solving the problem temporarily.

like image 765
MasterGberry Avatar asked Feb 26 '14 17:02

MasterGberry


2 Answers

This is a bug in the Android bluetooth code which does not appear to have a resolution at present. Since other people keep finding this as well, I'm going to post what I found when tracing the problem through the bluetooth stack, even though it cannot really be applied as a resolution unless one is prepared to make major changes to an AOSP-based install.

Fundamentally, the problem is a SIGSEGV in btif_config.c at find_add_node() when alloc_node() fails after hearing too many unique BTLE hardware addresses.

Informative part of stack trace

D/BtGatt.btif(22509): btif_gattc_upstreams_evt: Event 4096
D/BtGatt.btif(22509): btif_gattc_add_remote_bdaddr device added idx=1
D/BtGatt.btif(22509): btif_gattc_update_properties BLE device name=beacon len=6 dev_type=2
F/libc    (22509): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 22530 (BTIF)
I/DEBUG   (  171): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (  171): Build fingerprint: 'google/occam/mako:4.4.2/KOT49H/937116:user/release-keys'
I/DEBUG   (  171): Revision: '11'
I/DEBUG   (  171): pid: 22509, tid: 22530, name: BTIF  >>> com.android.bluetooth <<<
I/DEBUG   (  171): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
I/DEBUG   (  171):     r0 ffffffff  r1 00007d00  r2 00007c60  r3 74c7cf00
I/DEBUG   (  171):     r4 74c7cf10  r5 00000000  r6 756f95a8  r7 7503c671

I/DEBUG   (  171): backtrace:
I/DEBUG   (  171):     #00  pc 0004e68c  /system/lib/hw/bluetooth.default.so
I/DEBUG   (  171):     #01  pc 0004ea65  /system/lib/hw/bluetooth.default.so (btif_config_set+156)

Disassembling, the code in question is this rather obviously problematic series of clearing r5 and then attempting to de-reference it as a base pointer:

       4e68a:   2500        movs    r5, #0
       4e68c:   6829        ldr r1, [r5, #0]
       4e68e:   b919        cbnz    r1, 4e698 <btif_gattc_test_command_impl+0x74c>
       4e690:   4630        mov r0, r6
       4e692:   f7dd ef78   blx 2c584 <strdup@plt>

This corresponds to the “if(!node->name)” check at the end of find_add_node()

static cfg_node* find_add_node(cfg_node* p, const char* name)
{
    int i = -1;
    cfg_node* node = NULL;
    if((i = find_inode(p, name)) < 0)
    {
        if(!(node = find_free_node(p)))
        {
            int old_size = alloc_node(p, CFG_GROW_SIZE);
            if(old_size >= 0)
            {
                i = GET_NODE_COUNT(old_size);
                node = &p->child[i];
                ADD_CHILD_COUNT(p, 1);
            } /* else clause to handle failure of alloc_node() is missing here */
        } else ADD_CHILD_COUNT(p, 1);
    }
    else node = &p->child[i];
    if(!node->name)   /* this will SIGSEGV if node is still NULL */
        node->name = strdup(name);
    return node;
}

Specifically, there is no else clause to handle the failure of alloc_node(), so when that happens (presumably due to running out of storage after hearing too many device addresses) the code falls through and attempts to dereference the name member of the node pointer without ever having set it to a non-null address.

A fix would presumably need to involve:

  1. non-crash handling of this error case when a new record cannot be allocated

  2. more aggressive discarding of past-heard addresses when new ones keep being heard and the number of records being stored becomes unreasonable

like image 151
Chris Stratton Avatar answered Oct 16 '22 09:10

Chris Stratton


Someone just opened an issue: https://code.google.com/p/android/issues/detail?id=67272 . Any supporting evidence should go there and hopefully Google fixes this in next release.

like image 25
Juha Kuikka Avatar answered Oct 16 '22 09:10

Juha Kuikka