CVE-2024-29195 (C, published 2024-03-26T03:15Z)
Description: value: The azure-c-shared-utility is a C library for AMQP/MQTT communication to Azure Cloud Services. This library may be used by the Azure IoT C SDK for communication between IoT Hub and IoT Hub devices. An attacker can cause an integer wraparound or under-allocation or heap buffer overflow due to vulnerabilities in parameter checking mechanism, by exploiting the buffer length parameter in Azure C SDK, which may lead to remote code execution. Requirements for RCE are 1. Compromised Azure account allowing malformed payloads to be sent to the device via IoT Hub service, 2. By passing IoT hub service max message payload limit of 128KB, and 3. Ability to overwrite code space with remote code. Fixed in commit https://github.com/Azure/azure-c-shared-utility/commit/1129147c38ac02ad974c4c701a1e01b2141b9fe2.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/Azure/azure-c-shared-utility
Files changed:
adapters/httpapi_compact.c
adapters/httpapi_curl.c
adapters/httpapi_tirtos.c
adapters/httpapi_winhttp.c
adapters/socketio_berkeley.c
adapters/socketio_win32.c
adapters/string_utils.c
adapters/tlsio_mbedtls.c
adapters/tlsio_openssl.c
adapters/tlsio_schannel.c
adapters/tlsio_wolfssl.c
adapters/x509_schannel.c
inc/azure_c_shared_utility/xlogging.h
src/buffer.c
src/constbuffer.c
Commit message: Add malloc size checks (#652)

* Add malloc size checks

* Update adapters/socketio_berkeley.c

Co-authored-by: Valerie Avva Lim <54871851+vaavva@users.noreply.github.com>

* Update adapters/string_utils.c

Co-authored-by: Valerie Avva Lim <54871851+vaavva@users.noreply.github.com>

* PR review

---------

Co-authored-by: Valerie Avva Lim <54871851+vaavva@users.noreply.github.com>

Vulnerable code:
            new_received_bytes = (unsigned char*)realloc(http_instance->received_bytes, http_instance->received_bytes_count + size);
        int len;
        len = (int)strlen((char*)value);
        http_instance->certificate = (char*)malloc((len + 1) * sizeof(char));
        int len;
        len = (int)strlen((char*)value);
        http_instance->x509ClientCertificate = (char*)malloc((len + 1) * sizeof(char));
        int len;
        len = (int)strlen((char*)value);
        http_instance->x509ClientPrivateKey = (char*)malloc((len + 1) * sizeof(char));
        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
            size_t hostURL_size = strlen("https://") + strlen(hostName) + 1;
            httpHandleData->hostURL = malloc(hostURL_size);
        void* newBuffer = realloc(responseContentBuffer->buffer, responseContentBuffer->bufferSize + (size * nmemb));
            LogError("Could not allocate buffer of size %lu", (unsigned long)(responseContentBuffer->bufferSize + (size * nmemb)));
        size_t tempHostURL_size = strlen(httpHandleData->hostURL) + strlen(relativePath) + 1;
        tempHostURL = malloc(tempHostURL_size);
                        size_t authLen = strlen(proxy_data->username)+strlen(proxy_data->password)+1;
                        proxy_auth = malloc(authLen+1);
            hname = (char *)realloc(hname, offset + ret);
    char *result = (char*)malloc(toAlloc * sizeof(char) + 1);
            else if ((*httpHeaders = (wchar_t*)malloc((requiredCharactersForHeaders + 1) * sizeof(wchar_t))) == NULL)
                hostNameTemp = (wchar_t*)malloc(sizeof(wchar_t) * hostNameTemp_size);
    
    else if ((relativePathTemp = (wchar_t*)malloc((requiredCharactersForRelativePath + 1) * sizeof(wchar_t))) == NULL)
    if ((responseHeadersTemp = (wchar_t*)malloc((size_t)responseHeadersTempLength + 2)) == NULL)
            else if ((tokenTemp = (char*)malloc(sizeof(char) * tokenTemp_size)) == NULL)
                if ((result = malloc(sizeof(char) * (strlen((char*)value) + 1))) == NULL)
    else if ((result->name = (char*)malloc(sizeof(char) * (strlen(ifr->ifr_name) + 1))) == NULL)
        if ((result->mac_address = (char*)malloc(sizeof(char) * MAC_ADDRESS_STRING_LENGTH)) == NULL)
            LogError("failed formatting mac address (malloc failed)");
        else if ((result->ip_address = (char*)malloc(sizeof(char) * (strlen(ip_address) + 1))) == NULL)
                    result->hostname = (char*)malloc(strlen(socket_io_config->hostname) + 1);
                    if (result->hostname != NULL)
                        (void)strcpy(result->hostname, socket_io_config->hostname);
            else if ((socket_io_instance->target_mac_address = (char*)malloc(sizeof(char) * (strlen(value) + 1))) == NULL)
                    result->hostname = (char*)malloc(strlen(socket_io_config->hostname) + 1);
                    if (result->hostname != NULL)
                        (void)strcpy(result->hostname, socket_io_config->hostname);
        result = (char*)malloc(((unsigned long long)neededSize + 1) * sizeof(char));
        if (result == NULL)
        result = (wchar_t*)malloc(((unsigned long long)neededSize + 1)*sizeof(wchar_t));
        if (result == NULL)
            result = (wchar_t*)malloc(sizeof(wchar_t)*(nwc+1));
            if (result == NULL)
            result = (char*)malloc(sizeof(char)*(nc + 1));
            if (result == NULL)
        unsigned char *new_socket_io_read_bytes = (unsigned char *)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count + size);

        if (new_socket_io_read_bytes == NULL)
        openssl_locks = malloc(CRYPTO_num_locks() * sizeof(LOCK_HANDLE));
        if (openssl_locks == NULL)
            LogError("Failed to allocate locks");
            tls_io_instance->certificate = malloc(len + 1);
            if (tls_io_instance->certificate == NULL)
                size_t needed_buffer = sizes.cbHeader + size + sizes.cbTrailer;
                unsigned char* out_buffer = (unsigned char*)malloc(needed_buffer);
                if (out_buffer == NULL)
                    LogError("malloc failed");
            result->host_name = (SEC_TCHAR*)malloc(sizeof(SEC_TCHAR) * (1 + strlen(tls_io_config->hostname)));
            if (result->host_name == NULL)
                LogError("malloc failed");
        unsigned char* new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count + size);
        if (new_socket_io_read_bytes == NULL)
            LogError("Failed allocating memory for received bytes");
    DWORD keyBlobSize = sizeof(BCRYPT_ECCKEY_BLOB) + pubSize + privSize;
    BCRYPT_ECCKEY_BLOB* pKeyBlob = (BCRYPT_ECCKEY_BLOB*)malloc(keyBlobSize);
    if (pKeyBlob == NULL)
        LogError("Failed to malloc NCrypt private key blob");
            status = NCryptImportKey(x509_handle->hProv, 0, BCRYPT_ECCPRIVATE_BLOB, &ncBufDesc, &x509_handle->x509hcryptkey, (BYTE*)pKeyBlob, keyBlobSize, NCRYPT_OVERWRITE_KEY_FLAG);
                char* formatWithStack = (char*)logging_malloc(formatSize + sizeof("STACK_PRINT_FORMAT"));                                                               \
                if (formatWithStack == NULL)                                                                                                                            \
            unsigned char* temp = (unsigned char*)realloc(handle->buffer, handle->size + size);
            if (temp == NULL)
                LogError("Failure reallocating temporary buffer");
        unsigned char* temp = (unsigned char*)realloc(b->buffer, b->size + enlargeSize);
        if (temp == NULL)
            LogError("Failure: allocating temp buffer.");
                unsigned char* temp = (unsigned char*)realloc(b1->buffer, b1->size + b2->size);
                if (temp == NULL)
    result = (CONSTBUFFER_HANDLE)calloc(1, (sizeof(CONSTBUFFER_HANDLE_DATA) + size));

Fixed code:
#include "azure_c_shared_utility/safe_math.h"
            size_t malloc_size = http_instance->received_bytes_count + size;
            if (malloc_size < size)
            {
                // check for int overflow
                new_received_bytes = NULL;
                LogError("Invalid size parameter");
            }
            else
            {
                new_received_bytes = (unsigned char*)realloc(http_instance->received_bytes, malloc_size);
            }

        size_t len = strlen((char*)value);
        size_t malloc_size = safe_add_size_t(len, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            LogError("Invalid malloc size");
            http_instance->certificate = NULL;
        }
        else
        {
            http_instance->certificate = (char*)malloc(malloc_size);
        }

        size_t len = strlen((char*)value);
        size_t malloc_size = safe_add_size_t(len, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            LogError("Invalid malloc size");
            http_instance->x509ClientCertificate = NULL;
        }
        else
        {
            http_instance->x509ClientCertificate = (char*)malloc(malloc_size);
        }

        size_t len = strlen((char*)value);
        size_t malloc_size = safe_add_size_t(len, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            LogError("Invalid malloc size");
            http_instance->x509ClientPrivateKey = NULL;
        }
        else
        {
            http_instance->x509ClientPrivateKey = (char*)malloc(malloc_size);
        }

        size_t malloc_size = safe_add_size_t(certLen, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            tempCert = NULL;
        }
        else
        {
            tempCert = (char*)malloc(malloc_size);
        }

        size_t malloc_size = safe_add_size_t(certLen, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            LogError("Invalid malloc size");
            tempCert = NULL;
        }
        else
        {
            tempCert = (char*)malloc(malloc_size);
        }

        size_t malloc_size = safe_add_size_t(certLen, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            LogError("Invalid malloc size");
            tempCert = NULL;
        }
        else
        {
            tempCert = (char*)malloc(malloc_size);
        }

#include "azure_c_shared_utility/safe_math.h"
            size_t hostURL_size = safe_add_size_t(strlen("https://"), strlen(hostName));
            hostURL_size = safe_add_size_t(hostURL_size, 1);

            if (hostURL_size == SIZE_MAX)
            {
                LogError("invalid malloc size");
                httpHandleData->hostURL = NULL;
            }
            else
            {
                httpHandleData->hostURL = malloc(hostURL_size);
            }
        size_t malloc_size = safe_multiply_size_t(size, nmemb);
        malloc_size = safe_add_size_t(malloc_size, responseContentBuffer->bufferSize);

        void* newBuffer;
        if (malloc_size == SIZE_MAX)
        {
            LogError("Invalid buffer size");
            newBuffer = NULL;
        }
        else
        {
            newBuffer = realloc(responseContentBuffer->buffer, malloc_size);
        }

            LogError("Could not allocate buffer of size %lu", (unsigned long)(malloc_size));
        size_t tempHostURL_size = safe_add_size_t(strlen(httpHandleData->hostURL), strlen(relativePath));
        tempHostURL_size = safe_add_size_t(tempHostURL_size, 1);
        if (tempHostURL_size == SIZE_MAX)
        {
            LogError("Invalid malloc size");
            tempHostURL = NULL;
        }
        else
        {
            tempHostURL = malloc(tempHostURL_size);
        }

                        size_t authLen = safe_add_size_t(strlen(proxy_data->username), strlen(proxy_data->password));
                        authLen = safe_add_size_t(authLen, 2);
                        if (authLen == SIZE_MAX)
                        {
                            LogError("Invalid malloc size");
                            proxy_auth = NULL;
                        }
                        else
                        {
                            proxy_auth = malloc(authLen);
                        }

#include "azure_c_shared_utility/safe_math.h"
            size_t malloc_size = safe_add_size_t(offset, ret);
            if (malloc_size == SIZE_MAX)
            {
                LogError("invalid realloc size");
                hname = NULL;
            }
            else
            {
                hname = (char*)realloc(hname, malloc_size);
            }

#include "azure_c_shared_utility/safe_math.h"
    char* result;

    size_t malloc_size = safe_multiply_size_t(toAlloc, sizeof(char));
    malloc_size = safe_add_size_t(malloc_size, 1);
    if (malloc_size == SIZE_MAX)
    {
        LogError("Invalid malloc size");
        result = NULL;
    }
    else
    {
        result = (char*)malloc(malloc_size);
    }
            size_t malloc_size;
            else if ((malloc_size = safe_multiply_size_t(safe_add_size_t(requiredCharactersForHeaders, 1), sizeof(wchar_t))) == SIZE_MAX ||
                (*httpHeaders = (wchar_t*)malloc(malloc_size)) == NULL)
                size_t malloc_size = safe_multiply_size_t(sizeof(wchar_t), hostNameTemp_size);
                if (malloc_size == SIZE_MAX)
                {
                    LogError("Invalid malloc size");
                    hostNameTemp = NULL;
                }
                else
                {
                    hostNameTemp = (wchar_t*)malloc(malloc_size);
                }

    size_t malloc_size;

    else if ((malloc_size = safe_multiply_size_t(safe_add_size_t(requiredCharactersForRelativePath, 1), sizeof(wchar_t))) == SIZE_MAX)
    {
        LogError("malloc invalid size");
        result = HTTPAPI_ALLOC_FAILED;
    }
    else if ((relativePathTemp = (wchar_t*)malloc(malloc_size)) == NULL)
    size_t malloc_size = safe_add_size_t((size_t)responseHeadersTempLength, 2);
    if (malloc_size == SIZE_MAX)
    {
        LogError("Invalid malloc size");
        responseHeadersTemp = NULL;
    }
    else
    {
        responseHeadersTemp = (wchar_t*)malloc(malloc_size);
    }

    if (responseHeadersTemp == NULL)
            else if ((malloc_size = safe_multiply_size_t(sizeof(char), tokenTemp_size)) == SIZE_MAX)
            {
                result = HTTPAPI_ALLOC_FAILED;
                LogError("invalid malloc size");
                break;
            }
            else if ((tokenTemp = (char*)malloc(malloc_size)) == NULL)
#include "azure_c_shared_utility/safe_math.h"
                size_t malloc_size = safe_add_size_t(strlen((char*)value), 1);
                malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
                if (malloc_size == SIZE_MAX)
                {
                    LogError("Invalid malloc size");
                }
                else if ((result = malloc(malloc_size)) == NULL)
    size_t malloc_size;
    else if ((malloc_size = safe_multiply_size_t(safe_add_size_t(strlen(ifr->ifr_name), 1), sizeof(char))) == SIZE_MAX)
    {
        LogError("invalid malloc size");
        destroy_network_interface_descriptions(result);
        result = NULL;
    }
    else if ((result->name = (char*)malloc(malloc_size)) == NULL)
        size_t malloc_size = safe_multiply_size_t(sizeof(char), MAC_ADDRESS_STRING_LENGTH);
        if (malloc_size == SIZE_MAX ||
                (result->mac_address = (char*)malloc(malloc_size)) == NULL)
            LogError("failed formatting mac address (malloc failed) size:%zu", malloc_size);
        else if ((malloc_size = safe_multiply_size_t(safe_add_size_t(strlen(ip_address), 1), sizeof(char))) == SIZE_MAX)
        {
            LogError("invalid malloc size");
            destroy_network_interface_descriptions(result);
            result = NULL;
        }
        else if ((result->ip_address = (char*)malloc(malloc_size)) == NULL)
                    size_t malloc_size = safe_add_size_t(strlen(socket_io_config->hostname), 1);
                    if (malloc_size == SIZE_MAX)
                        LogError("invalid malloc size");
                        result->hostname = NULL;
                    }
                    else
                    {
                        result->hostname = (char*)malloc(malloc_size);
                        if (result->hostname != NULL)
                        {
                            (void)strcpy(result->hostname, socket_io_config->hostname);
                        }
            size_t malloc_size;
            else if ((malloc_size = safe_multiply_size_t(safe_add_size_t(strlen(value), 1), sizeof(char))) == SIZE_MAX)
            {
                LogError("invalid malloc size");
                result = MU_FAILURE;
                socket_io_instance->target_mac_address = NULL;
            }
            else if ((socket_io_instance->target_mac_address = (char*)malloc(malloc_size)) == NULL)
#include "azure_c_shared_utility/safe_math.h"
                    size_t malloc_size = safe_add_size_t(strlen(socket_io_config->hostname), 1);
                    if (malloc_size == SIZE_MAX)
                        LogError("Invalid malloc size");
                        result->hostname = NULL;
                    }
                    else
                    {
                        result->hostname = (char*)malloc(malloc_size);
                        if (result->hostname != NULL)
                        {
                            (void)strcpy(result->hostname, socket_io_config->hostname);
                        }
#include "azure_c_shared_utility/safe_math.h"
        size_t malloc_size = safe_add_size_t((unsigned long long)neededSize, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
        if (malloc_size == SIZE_MAX)
        {
            LogError("invalid malloc size");
            result = NULL;
            /*return as is*/
        }
        else if ((result = (char*)malloc(malloc_size)) == NULL)
        size_t malloc_size = safe_add_size_t((unsigned long long)neededSize, 1);
        malloc_size = safe_multiply_size_t(malloc_size, sizeof(wchar_t));
        if (malloc_size == SIZE_MAX)
        {
            LogError("invalid malloc size");
            result = NULL;
            /*return as is*/
        }
        else if ((result = (wchar_t*)malloc(malloc_size)) == NULL)
            size_t malloc_size = safe_add_size_t(nwc, 1);
            malloc_size = safe_multiply_size_t(malloc_size, sizeof(wchar_t));
            if (malloc_size == SIZE_MAX)
            {
                LogError("invalid malloc size");
                result = NULL;
                /*return as is*/
            }
            else if ((result = (wchar_t*)malloc(malloc_size)) == NULL)
            size_t malloc_size = safe_add_size_t(nc, 1);
            malloc_size = safe_multiply_size_t(malloc_size, sizeof(char));
            if (malloc_size == SIZE_MAX)
            {
                LogError("invalid malloc size");
                result = NULL;
                /*return as is*/
            }
            else if ((result = (char*)malloc(malloc_size)) == NULL)
#include "azure_c_shared_utility/safe_math.h"
        unsigned char* new_socket_io_read_bytes;
        size_t realloc_size = safe_add_size_t(tls_io_instance->socket_io_read_byte_count, size);
        if (realloc_size == SIZE_MAX)
        {
            LogError("Invalid realloc size");
            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
            indicate_error(tls_io_instance);
        }
        else if ((new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, realloc_size)) == NULL)
            LogError("realloc failed");
#include "azure_c_shared_utility/safe_math.h"
        size_t malloc_size = safe_multiply_size_t(CRYPTO_num_locks(), sizeof(LOCK_HANDLE));
        if (malloc_size == SIZE_MAX ||
            (openssl_locks = malloc(malloc_size)) == NULL)
            LogError("Failed to allocate locks, size:%zu", malloc_size);
            size_t malloc_size = safe_add_size_t(len, 1);
            if (malloc_size == SIZE_MAX ||
                (tls_io_instance->certificate = malloc(malloc_size)) == NULL)
                LogError("malloc failure, size:%zu", malloc_size);
#include "azure_c_shared_utility/safe_math.h"
                unsigned char* out_buffer;
                size_t needed_buffer = safe_add_size_t(sizes.cbHeader, size);
                needed_buffer = safe_add_size_t(needed_buffer, sizes.cbTrailer);
                if (needed_buffer == SIZE_MAX ||
                    (out_buffer = (unsigned char*)malloc(needed_buffer)) == NULL)
                    LogError("malloc failed, size:%zu", needed_buffer);
            size_t malloc_size = safe_add_size_t(strlen(tls_io_config->hostname), 1);
            malloc_size = safe_multiply_size_t(malloc_size, sizeof(SEC_TCHAR));
            if (malloc_size == SIZE_MAX ||
                (result->host_name = (SEC_TCHAR*)malloc(malloc_size)) == NULL)
                LogError("malloc failed, size:%zu", malloc_size);
#include "azure_c_shared_utility/safe_math.h"
        unsigned char* new_socket_io_read_bytes;
        size_t realloc_size = safe_add_size_t(tls_io_instance->socket_io_read_byte_count, size);
        if (realloc_size == SIZE_MAX ||
            (new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, realloc_size)) == NULL)
            LogError("Failed allocating memory for received bytes, size:%zu", realloc_size);
#include "azure_c_shared_utility/safe_math.h"

    BCRYPT_ECCKEY_BLOB* pKeyBlob;
    size_t keyBlobSize = safe_add_size_t(safe_add_size_t(sizeof(BCRYPT_ECCKEY_BLOB), pubSize), privSize);

    if (keyBlobSize == SIZE_MAX ||
        (pKeyBlob = (BCRYPT_ECCKEY_BLOB*)malloc(keyBlobSize)) == NULL)
        LogError("Failed to malloc NCrypt private key blob, size:%zu", keyBlobSize);
            status = NCryptImportKey(x509_handle->hProv, 0, BCRYPT_ECCPRIVATE_BLOB, &ncBufDesc, &x509_handle->x509hcryptkey, (BYTE*)pKeyBlob, (DWORD)keyBlobSize, NCRYPT_OVERWRITE_KEY_FLAG);
                char* formatWithStack;                                                                                                                                  \
                size_t mallocSize = formatSize + sizeof("STACK_PRINT_FORMAT");                                                                                          \
                if (mallocSize < formatSize ||   /* int overflow check */                                                                                               \
                    (formatWithStack = (char*)logging_malloc(mallocSize)) == NULL)                                                                                      \
            unsigned char* temp;
            size_t malloc_size = safe_add_size_t(handle->size, size);
            if (malloc_size == SIZE_MAX || 
                (temp = (unsigned char*)realloc(handle->buffer, malloc_size)) == NULL)
                LogError("Failure reallocating temporary buffer, size:%zu", malloc_size);
        unsigned char* temp;
        size_t malloc_size = safe_add_size_t(b->size, enlargeSize);
        if (malloc_size == SIZE_MAX ||
            (temp = (unsigned char*)realloc(b->buffer, malloc_size)) == NULL)
            LogError("Failure: allocating temp buffer, size:%zu", malloc_size);
                unsigned char* temp;
                size_t malloc_size = safe_add_size_t(b1->size, b2->size);
                if (malloc_size == SIZE_MAX || 
                    (temp = (unsigned char*)realloc(b1->buffer, malloc_size)) == NULL)
    size_t malloc_size = sizeof(CONSTBUFFER_HANDLE_DATA) + size;
    if (malloc_size < size)
    {
        result = NULL;
        LogError("invalid size parameter");
        /*return as is*/
    }
    else
    {
        result = (CONSTBUFFER_HANDLE)calloc(1, malloc_size);
    }