This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2530: zclParseInWriteRspCmd writes outside allocated memory - ZIGBEE-LINUX-SENSOR-TO-CLOUD_1.0.1 --

Part Number: CC2530

I got the following memory access error during the execution of the gateway:

[2020-11-02 18:00:05.930,116] [GATEWAY/HNDL] MISC1  : Processing Af Incoming Message Indication
[2020-11-02 18:00:05] =================================================================
[2020-11-02 18:00:05] ==16502==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb5a06734 at pc 0x0010e5c9 bp 0xb5b68b38 sp 0xb5b68b3c
[2020-11-02 18:00:05] WRITE of size 2 at 0xb5a06734 thread T2
[2020-11-02 18:00:05]     #0 0x10e5c7 in zclParseInWriteRspCmd ../../../../Components/stack/zcl/zcl.c:3568
[2020-11-02 18:00:05]     #1 0x108189 in zcl_ProcessMessageMSG ../../../../Components/stack/zcl/zcl.c:2044
[2020-11-02 18:00:06]     #2 0x640b9 in processAfIncomingMsgInd .../3rdparty/ti/Zigbee_3_0_Linux_Gateway_1_0_1/source/Projects/zstack/linux/hagateway/gatewaysrvr.c:5769
[2020-11-02 18:00:06]     #3 0x52897 in handleAsyncMsgs .../3rdparty/ti/Zigbee_3_0_Linux_Gateway_1_0_1/source/Projects/zstack/linux/hagateway/gatewaysrvr.c:1111
[2020-11-02 18:00:06]     #4 0xb8873 in asynchMsgCback ../srvwrapper/api_client.c:1372
[2020-11-02 18:00:06]     #5 0xb8181 in SIShandleThreadFunc ../srvwrapper/api_client.c:1296
[2020-11-02 18:00:06]
[2020-11-02 18:00:06] 0xb5a06735 is located 0 bytes to the right of 5-byte region [0xb5a06730,0xb5a06735)
[2020-11-02 18:00:06] allocated by thread T2 here:
[2020-11-02 18:00:06]     #0 0x19943b in __interceptor_malloc /home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/snapshots/gcc-linaro-5.
[2020-11-02 18:00:06]
[2020-11-02 18:00:06] Thread T2 created by T0 here:
[2020-11-02 18:00:06]     #0 0x156a1b in __interceptor_pthread_create /home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/snapshots/gcc-l
[2020-11-02 18:00:06]     #1 0xb5803ebf  (<unknown module>)
[2020-11-02 18:00:06]
[2020-11-02 18:00:06] SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../Components/stack/zcl/zcl.c:3568 zclParseInWriteRspCmd
[2020-11-02 18:00:06] Shadow bytes around the buggy address:
[2020-11-02 18:00:06]   0x36b40c90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40ca0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40cb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40cc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40cd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06] =>0x36b40ce0: fa fa fa fa fa fa[05]fa fa fa 00 07 fa fa 06 fa
[2020-11-02 18:00:06]   0x36b40cf0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
[2020-11-02 18:00:06]   0x36b40d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40d10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40d20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06]   0x36b40d30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[2020-11-02 18:00:06] Shadow byte legend (one shadow byte represents 8 application bytes):
[2020-11-02 18:00:06]   Addressable:           00
[2020-11-02 18:00:06]   Partially addressable: 01 02 03 04 05 06 07
[2020-11-02 18:00:06]   Heap left redzone:       fa
[2020-11-02 18:00:06]   Heap right redzone:      fb

The access error happened on the highlighted line:

static void *zclParseInWriteRspCmd( zclParseCmd_t *pCmd )
{
  zclWriteRspCmd_t *writeRspCmd;
  uint8 *pBuf = pCmd->pData;
  uint8 i = 0;

  writeRspCmd = (zclWriteRspCmd_t *)zcl_mem_alloc( sizeof ( zclWriteRspCmd_t ) + pCmd->dataLen );
  if ( writeRspCmd != NULL )
  {
    if ( pCmd->dataLen == 1 )
    {
      // special case when all writes were successfull
      writeRspCmd->attrList[i++].status = *pBuf;
    }
    else
    {
      while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
      {
        writeRspCmd->attrList[i].status = *pBuf++;
        writeRspCmd->attrList[i++].attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
        pBuf += 2;
      }
    }

    writeRspCmd->numAttr = i;
  }

  return ( (void *)writeRspCmd );
}

This happened when an attribute could not be written (sniffer log extract):

ZigBee Cluster Library Frame, Command: Write Attributes Response, Seq: 0
    Frame Control Field: Profile-wide (0x08)
        .... ..00 = Frame Type: Profile-wide (0x0)
        .... .0.. = Manufacturer Specific: False
        .... 1... = Direction: Server to Client
        ...0 .... = Disable Default Response: False
    Sequence Number: 0
    Command: Write Attributes Response (0x04)
    Status Record
        Status: Invalid Value (0x87)
        Attribute: OccupiedHeatingSetpoint (0x0012)

  • Hi,

    Are there other attributes in this response, other than OccupiedHeatingSetpoint ?

    For convenience, I've copied here the structs involved:

    // Write Attribute Status record
    typedef struct
    {
      uint8  status;             // should be ZCL_STATUS_SUCCESS or error
      uint16 attrID;             // attribute ID
    } zclWriteRspStatus_t;
    
    // Write Attribute Response Command format
    typedef struct
    {
      uint8               numAttr;     // number of attribute status in the list
      zclWriteRspStatus_t attrList[];  // attribute status records
    } zclWriteRspCmd_t;

    For any Write Attributes Response, pCmd->dataLen is assumed to be a multiple of sizeof(zclWriteRspStatus_t). Perhaps an assert check here would be useful (assert( (pCmd->dataLen % sizeof(zclWriteRspStatus_t)    ==    0)).
    If this passes, then I would say that the message you see could be a false positive (since zclWriteRspCmd_t) does include a flexible array member.

    Regards,
    Toby

  • I added a trace to this code.

    It indicates that the sizeof(zclWriteRspCmd_t) equals to 2.

    The output in the trace is

    [2020-11-06 08:30:01.335,566] [GATEWAY/HNDL] UNMSKBL: zclParseInWriteLen 5 = 2 + 3
    [2020-11-06 08:30:01]     #0 0x10e9f9 in zclParseInWriteRspCmd ../../../../Components/stack/zcl/zcl.c:3574
    
      zclWriteRspCmd_t *writeRspCmd;
      uint8 *pBuf = pCmd->pData;
      uint8 i = 0;
    
      uint16 len=sizeof ( zclWriteRspCmd_t ) + pCmd->dataLen;
      uiPrintfEx(trUNMASKABLE, "zclParseInWriteLen %u = %u + %u\n",(int)len, sizeof(zclWriteRspCmd_t), pCmd->dataLen);
    
      writeRspCmd = (zclWriteRspCmd_t *)zcl_mem_alloc( len );
    

    Beyond this specific case, I think that the code relies a bit too much on lengths that should be of a certain size.

    Any incoming packet from another system is subject to a difference between the supposed length and the actual length.  In this case the actual packet length is fine, but the fixed length of the struct is not the one expected.

    As the condition verifies that the start pointer is still within memory space (and not the end pointer), there is one loop too many.

  • The issue is due to alignment, I suppose that the code has to be reviewed for this.

    Using a 32bit gcc compiler, the sizeof results for the types are:

    - zclWriteRspStatus_t 4
    - zclWriteRspCmd_t 2

    For a fast resolution, I am ammending the compilation with the '-fpack-struct' option.  Then the result is:

    - zclWriteRspStatus_t 3
    - zclWriteRspCmd_t 1

    I do not know the the same issue might arise fo the ZNP compilation iitself as zcl.c is inside the Components directory.  I have not investigated that.

    So I do believe that a code review with this issue in mind is needed.  Adding "#pragma pack" may be considered too.

    I do not know if this might also impact the Applicaiton executeable for some functionnalities.  I think that it is safe though.

    I am now updating the compile scripts.

    Note:

    - when adding -fpack-struct, I get warnings like this so the "#pragma_pack" technique is already used but not applied everywhere it  is needed.

    In file included from ipclib/server/hal_spi.h:54:0,
                     from ipclib/server/hal_spi.c:59:
    ipclib/server/hal_gpio.h:112:9: warning: #pragma pack has no effect with -fpack-struct - ignored [-Wpragmas]
     #pragma pack(1)
             ^
    

  • By adding tests to hal_types.h, it also appears that an unsigned long is not 64bit on for the target compiler.

    I included <limits.h> and check LONG_MAX.

    In order to make sure, I defined an uint64 global var and initialised it:

    Compiling ../zstackpb/zstack.pb-c.c ...
    In file included from <command-line>:0:0:
    ./../hal/hal_types.h:77:10: warning: large integer implicitly truncated to unsigned type [-Woverflow]
     uint64 t=0x7FFFFFFFFFFFFFFFULL;
    

    It's not because of the ULL which is needed  o ensure that a big constant is defined.
    "uint64 v=0x7FFFFFFFULL;" works with the above.

  • '-fpack-struct' can't be used in the current conditions, it generates an error in 'api_client'.
    Including "<limits.h>" in 'api_client.c' resulted in the same or similar effect. 'api_client.c_ probably needs to be improved for that.


    .

    ./srvwrapper/api_client.c: In function 'apicInit':
    ../srvwrapper/api_client.c:416:45: error: incompatible type for argument 2 of 'connect'
    if ( connect( pInstance->sAPIconnected, p->ai_addr, p->ai_addrlen ) != -1 )^M
    ^
    In file included from ../srvwrapper/api_client.c:44:0:
    /opt/ti-processor-sdk-linux-am335x-evm-03.03.00.04/linux-devkit/sysroots/armv7ahf-neon-linux-gnueabi/usr/include/sys/socket.h:137:12: note: expected '__CONST_SOCKADDR_ARG {aka union <anonymous>}' but argument is of type 'struct sockaddr *'
    extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
    ^
    Makefile:170: recipe for target 'out/api_client.o' failed
    make[1]: *** [out/api_client.o] Error 1
    make[1]: Leaving directory '/home/mdeweerd/Desktop/workspace/habitat/3rdparty/ti/Zigbee_3_0_Linux_Gateway_1_0_1/source/Projects/zstack/linux/zstackserverznp'
    Makefile:87: recipe for target 'arch-all-arm' failed

    I also note that uint64 is used in the gateway proto file, and UINT64 is typedef'd to it in ZComDef.h . Other than that there does not seem to be any use of it.


    So I removed '#include <limits.h>' from 'hal_types.h' where the 64bit types are defined as long long for the occasion. I have also removed '-fpack-structs' and added '#pragma pack(1)' on all 'typedef struct' and 'typedef enum' in the 'zcl.h' file.

    Unfortunately I get more errors from the gateway with that change.

    Packing all structs in 'zcl.h' is not a solution; I got a misaligned access in './Projects/zstack/linux/nwkmgr/nwkmgrdatabase.c':690, 
    and other locations .

    So I reverted back and changed only the struct with variable length arrays that are not pointers.

    I still ran into trouble there.

    I am now in a situation where the app fails:

    ==5009==ERROR: AddressSanitizer: SEGV on unknown address 0x00000002 (pc 0x003250f4 bp 0x00000000 sp 0xadafdf48 T2)
        #0 0x3250f3 in device_process_local_info_response(pkt_buf_t const*, void*) (/home/root/z-stack_linux_gateway_arm_binaries/Habitat3+0x3250f3)
    
    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV ??:0 device_process_local_info_response(pkt_buf_t const*, void*)
    

    Without a timeline from TI, I have to suppose that there may be an update for this in six months of so, beyond the date where the first systems will be installed (with the COVID crisis, this date is unclear, ).

    While I started fixing the gateway, this does not seem to amount to fixes requiring to know exactly how the structures are used.

    I hope that you can provide some earlier time frame.

  • I ended up by finding the right way of fixing this group of issues by mastering the pragma setup.

    On to other things to solve.