[ZBX-22127] Error codes of OpenSSL functions like BIO_get_mem_data() are not checked Created: 2022 Dec 22  Updated: 2022 Dec 23

Status: Confirmed
Project: ZABBIX BUGS AND ISSUES
Component/s: Agent (G), Proxy (P), Server (S)
Affects Version/s: 6.4.0beta5
Fix Version/s: 6.4 (plan)

Type: Incident report Priority: Trivial
Reporter: Artjoms Rimdjonoks Assignee: Zabbix Development Team
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

In the following block of code in tls.c, the "data" variable was not initialised during the call of BIO_get_mem_data() and then mistakenly used uninitialised in zbx_strlcpy():

        if (size <= (len = (size_t)BIO_get_mem_data(bio, &data)))
        {
                *error = zbx_strdup(*error, "output buffer too small");
                goto out;
        }
        zbx_strlcpy(buf, data, len + 1);

Looking at the documentation of the BIO_get_mem_data() function:

BIO_get_mem_data() returns the total number of bytes available on success, 0 if b is NULL, or a negative value in case of other errors.

So, it returns a negative value if error happened.

Example from openssl source code on how to properly handle this function:

ssl3_digest_cached_records()
...
        hdatalen = BIO_get_mem_data(s->s3.handshake_buffer, &hdata);
        if (hdatalen <= 0) {
            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_LENGTH);
            return 0;
        }

We however do not do that, and this is a bug (not related to the current ticket).

Update, Agent 2() independently uses BIO_get_mem_data() and also does not check the return value.
Update 2, other similar functions like BIO_read() also can return negative value in the case of error, but it is not checked, e.g. in tls_error():

                *buf = malloc(sz + 1);
                BIO_read(tls->err, *buf, (int)sz);
                (*buf)[sz] = '\0';
        }

The result of not checking the return values are invalid memory issues and potentially crashes that would be incredibly hard to debug (if not run by Valgrind):

==00:00:00:11.150 226099== Conditional jump or move depends on uninitialised value(s)
==00:00:00:11.150 226099==    at 0x483EFB8: __strlen_sse2 (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:00:11.151 226099==    by 0x408CEE: zbx_strlcpy (common_str.c:128)
==00:00:00:11.151 226099==    by 0x3347C2: zbx_x509_dn_gets.constprop.0 (tls.c:1100)
==00:00:00:11.151 226099==    by 0x337138: zbx_tls_get_attr_cert (tls.c:3875)
==00:00:00:11.151 226099==    by 0x3A6482: zbx_proxy_check_permissions (proxy.c:154)
==00:00:00:11.151 226099==    by 0x1C25C5: zbx_recv_proxy_data (proxydata.c:147)
==00:00:00:11.151 226099==    by 0x1BD61B: process_trap (trapper.c:1120)
==00:00:00:11.151 226099==    by 0x1BEE74: process_trapper_child (trapper.c:1265)
==00:00:00:11.151 226099==    by 0x1BEE74: trapper_thread (trapper.c:1355)
==00:00:00:11.151 226099==    by 0x3280F3: zbx_thread_start (threads.c:115)
==00:00:00:11.151 226099==    by 0x18A8E2: server_startup.constprop.0 (server.c:1501)
==00:00:00:11.151 226099==    by 0x18BA8A: MAIN_ZABBIX_ENTRY (server.c:2000)
==00:00:00:11.151 226099==    by 0x3E1022: zbx_daemon_start (daemon.c:448)
==00:00:00:11.151 226099==  Uninitialised value was created by a heap allocation
==00:00:00:11.151 226099==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:00:11.151 226099==    by 0x4FA7CB9: CRYPTO_clear_realloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4EF7DB8: BUF_MEM_grow_clean (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4ED9C57: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4ED563D: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4ED4653: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4ED4B16: BIO_write (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4EB97C0: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4EB9959: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4EB9BE5: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4EB9DC2: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:00:11.151 226099==    by 0x4EBA278: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)

and

==00:00:03:08.760 226095== Invalid read of size 1
==00:00:03:08.760 226095==    at 0x483EFB4: __strlen_sse2 (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:03:08.760 226095==    by 0x408CEE: zbx_strlcpy (common_str.c:128)
==00:00:03:08.760 226095==    by 0x3347C2: zbx_x509_dn_gets.constprop.0 (tls.c:1100)
==00:00:03:08.760 226095==    by 0x337156: zbx_tls_get_attr_cert (tls.c:3883)
==00:00:03:08.760 226095==    by 0x3A6482: zbx_proxy_check_permissions (proxy.c:154)
==00:00:03:08.760 226095==    by 0x1C25C5: zbx_recv_proxy_data (proxydata.c:147)
==00:00:03:08.760 226095==    by 0x1BD61B: process_trap (trapper.c:1120)
==00:00:03:08.760 226095==    by 0x1BEE74: process_trapper_child (trapper.c:1265)
==00:00:03:08.760 226095==    by 0x1BEE74: trapper_thread (trapper.c:1355)
==00:00:03:08.760 226095==    by 0x3280F3: zbx_thread_start (threads.c:115)
==00:00:03:08.760 226095==    by 0x18A8E2: server_startup.constprop.0 (server.c:1501)
==00:00:03:08.760 226095==    by 0x18BA8A: MAIN_ZABBIX_ENTRY (server.c:2000)
==00:00:03:08.760 226095==    by 0x3E1022: zbx_daemon_start (daemon.c:448)
==00:00:03:08.760 226095==  Address 0x822ba20 is 0 bytes after a block of size 96 alloc'd
==00:00:03:08.760 226095==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:03:08.760 226095==    by 0x4FA7CB9: CRYPTO_clear_realloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4EF7DB8: BUF_MEM_grow_clean (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4ED9C57: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4ED563D: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4ED4653: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4ED4B16: BIO_write (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4EB97C0: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4EB9959: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4EB9BE5: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4EB9DC2: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==00:00:03:08.760 226095==    by 0x4EBA278: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)

Found by solonkins while testing DEV-2255


Generated at Mon Jun 23 06:53:17 EEST 2025 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.