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.

CC2538: Memory Crash with some ZCL APIs

Part Number: CC2538
Other Parts Discussed in Thread: Z-STACK

Hi,

I'm a PhD student and currently learning ZCL APIs. Recently I got some memory crash when sending some valid ZCL messages. I use IAR workbench and its simulator and CC2538 with SmartRF06 evaluation board for study.

1. zclParseInDiscCmdsRspCmd( zclParseCmd_t *pCmd )

The ZCL message I construct is \x00\x01\x12\x00\x00 which means the frame control is 0, transaction sequence number is 1, the command ID is 0x12 that is Discover Commands Received Response. Discovery complete is 0 and command identifier is 0. All the fields are based on ZCL Spec.

In simulator, I just initialize the memory and required system variable. Then I create an afIncomingMSGPacket_t  variable with such message and pass it to zcl_ProcessMessageMSG() which will trigger zclParseInDiscComdsRspCmd(). Then I got memory crash at line of code 4348, pDiscoverRspCmd->pCmdID[i] = *pBuf++. When I use IAR to debug step by step I see the following value:

The crash message says read outside range 0xCDCDCDCD. The variable pCmdID is an array pointer, I think when it's allocated memory, its value should be a valid memory address which I guess should be 0x20043DC in this case. However, the result shows it's not initialized when allocated memory space with structure variable pDiscoverRspCmd.

Also, I send the same message with zcl_SendCommand() on CC2538 as coordinator. And the end device which is also CC2538 receives message and pass ZCL to handle. The end device then freezes. When I debug on device, I also see the similar value. The address 0xFFFF0004 is outside RAM section.

I think there may some issues with ZCL memory allocation. Could anyone please help verify if this is bug or vulnerability?

2. zclProcessInWriteCmd(zclIncoming_t *pInMsg)

For this API call, I think there is a NullPointerReference. The variable writeRspCmd is only initialized when commandID is ZCL_CMD_WRITE. However, this function is also process command ZCL_CMD_WRITE_NO_RSP. When it's a NO_RSP command, this variable is a null pointer. However, line of code 4513 directly uses it to write a value. When I run codes in simulator, it crashes and shows me the address is outside range which I think it's correct. However, on CC2538 it has no issues which I think could be wrong.

On CC2538 I send the following message \x08\x01\x05\x00\x00\x00\x00, where frame control is 0x08, tranSeqNum is 0x01, commandID is 0x05. The payload is a write attribute record  where the identifier is 0x0000, data type is 0x00, and attribute data is 0x00. When I debug on both simulator and CC2538, I see the values of writeRspCmd as the following. Based on my understanding, the code should not write to attrList since 0x0000002 is ROM section and read only. The device should crash in this case. However, it executes without any issues.

Could anyone please help me verify these two issue if they are bugs? Or if I did in wrong way? Thank you so much!

  • Sorry to mention that I use Zigbee 3.0 and use sample project GenericApp on CC2538.

  • Hi Mengfei,

    1. Does this E2E post relate to your observations?

    2. Please further explain this issue by debugging CC2538 hardware (not using the simulator).  The zclFrameHdr includes a two-byte manuCode between the fc and transSeqNum.  I would expect writeRspCmd is NULL and the early return from zclProcessInWriteCmd.

    Regards,
    Ryan

  • Hi Ryan,

    Thanks for update.

    1. Yes, that post is related to my observations. Currently I'm using Z-Stack 3.0 so it has been fixed in the latest version?

    2. Based on Zigbee Spec, the manuCode is only included if manufacturer specific is set to 1 in fc. If fc is 8 then it means this value is set to 0, so I didn't include manuCode field. 

    I use the sample project GenericApp. I use one CC2538 as coordinator to send this command directly with zcl_SendCommand function. When another CC2538 receive this message, I call osal_msg_send(zcl_TaskID, (uint8 *)MSGpkt) to let ZCL process this message. When the program executes, the if condition at line4489 is passed, so writeRspCmd is NULL at line4512 and should return. However, it continues execution the following codes and returns TRUE to zcl_ProcessMessageMSG that means it processes the command successfully. As you said, it should early return a error code or FALSE.

    Here is the codes how I send command and pass it to ZCL.

    Coordinator:

    uint8 cmd[] = {0x00,0x00,0x00,0x00}; 
    afAddrType_t my_DstAddr;
    my_DstAddr.addrMode = (afAddrMode_t)afAddrBroadcast;
    my_DstAddr.endPoint = GENERICAPP_ENDPOINT;
    my_DstAddr.addr.shortAddr = 0xFFFF;
    
    ZStatus_t status = zcl_SendCommand(*(uint8 *)GenericApp_epDesc, &my_DstAddr, 0x0000, 0x05, 0, 1, 0, 0, 1, sizeof(cmd), (uint8 *)&cmd);
          

    End Device:

    uint16 zclGenericApp_event_loop( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
    
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclGenericApp_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case AF_INCOMING_MSG_CMD:
              // Ask ZCL to process foundation messages
              osal_msg_send(zcl_TaskID, (uint8 *)MSGpkt);
              break;
            .....
          

  • 1. No you will need to implement the fix yourself.

    2. Why not use zcl_SendWriteNoRsp or zcl_SendWriteRequest with the cmd parameter set to ZCL_CMD_WRITE_NO_RSP on the ZC?  Can you provide a sniffer log of the over-the-air communication and debug zclProcessInWriteCmd on your ZED for the contents of pInMsg?

    Regards,
    Ryan

  • i Ryan,

    Previously I test many command so I use that general zcl_SendCommand function. With your suggestion, I use zcl_SendWriteNoRsp to send the message. Here is the piece of code.

          zclWriteCmd_t *cmd = (zclWriteCmd_t *)zcl_mem_alloc(sizeof(zclWriteCmd_t)+1);
          zclWriteRec_t rec;
          rec.attrID = 0x0000;
          rec.dataType = 0x00;
          uint8 data = {0};
          rec.attrData = &data;
          cmd->numAttr = 1;
          cmd->attrList[0] = rec;
          afAddrType_t my_DstAddr;
          my_DstAddr.addrMode = (afAddrMode_t)afAddrBroadcast;
          my_DstAddr.endPoint = GENERICAPP_ENDPOINT;
          my_DstAddr.addr.shortAddr = 0xFFFF;
          // Send Testing command
          ZStatus_t status = zcl_SendWriteNoRsp(*(uint8 *)GenericApp_epDesc, &my_DstAddr, 0x0000, cmd, 1, 0, zcl_TransID);
          zcl_mem_free(cmd);

    And here is the sniffer log I capture from Ubiqua. After ZC and ZED are in the same network. I reuse HandleKey function in sample project to send the command message. 8358.Packet.txt

    When I debug, here is the content of pInMsg. Everything is correct (fc is 8, commandID is 0x05, pData is 0). However, writeRspCmd is allocated a memory address(0x200056C4) while the zcl_mem_alloc() inside if condition is not executed in that case. So I don't how it gets a memory. And then attrList is written at line4513. I highlight it in memory view(0x200056C6). But as what we said before, based on the syntax, it should be NULL.

  • Mengfei,

    Can you please provide the sniffer log file instead of a txt?  I do not think you are forming the zcl_SendCommand or zcl_SendWriteNoRsp cmd parameters properly, what is writeCmd?  You can revise the code to not bother with writeRspCmd if the commandID is equal to ZCL_CMD_WRITE_NO_RSP.

    Regards,
    Ryan

  • Hi Ryan,

    Thanks for update! As a beginner of embedded development, I'll look at my codes and revise them. Based on my observation, though writeRspCmd point is allocated a memory address, no response is sent out, thus it behaves as expectation, right? I'm just wondering if this pointer could be a potential memory leakage that someone can utilize it.

    Thank you so much again for clarification.

    Regards,

    Mengfei

  • Since memory is not allocated for writeRspCmd (unless commandID is ZCL_CMD_WRITE) there is no leakage concern.

    Regards,
    Ryan

  • Hi Ryan,

    Sorry for late update. Yes, I finally found that I set the source end point with wrong variable in the command. But after I set to the right end point GENERICAPP_ENDPOINT, I still see the same result during the debugging. I'm not sure if there is still something wrong with my code, could you help me?

    For my understanding, from user's perspective, everything is correct since no response sent back from the server when sending command WRITE_ATTR_NO_RSP. My confusion is that according to the syntax of that code, from server perspective, when line4512 is executed, an exception or error should occur. However, I didn't see such thing happen when I debug on the device. Is it better to add double check to that function?

    Moreover, I have a question with the string data type in zcl. According to the specification, the first octet or the first two octets should be set as the length of the string. If this value is set larger than the actual string length, will there be an overread problem when we copy this string to a memory space? For example, if I declare a string value like the following:

    uint8 data[] = {254,'t','e','s','t'};
    
    // dataPtr has allocated in somewhere
    
    zcl_mem_cpy(dataPtr, data, 254);

    I see most ZCL functions call zclGetAttrDataLength() to get the first value as the string length rather than verify it with the actual length. I understand this should not happen in normal. But it's possible if an attack sends malformed data to the device like that which could trigger a buffer overflow when the device process such data during the copy operation.

  • Hi Mengfei,

    Please provide any specific OTA use cases, including sniffer logs and debug material, for which you are seeing memory issues occur.  Also be aware that you are allowed to modify the ZCL layer as you see fit but you may want to reference the ZCL Specification to stay conformed to this standard.

    Regards,
    Ryan