From 14887eb7c41c19e8b71a763ed17b60ecc5854bba Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 29 Jun 2022 14:46:27 +0000 Subject: On 'thread-name' branch: Merge changes from trunk. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/thread-name@1902353 13f79535-47bb-0310-9956-ffa450edef68 --- crypto/apr_crypto.c | 31 +------------- crypto/apr_crypto_prng.c | 15 +++---- crypto/apr_md4.c | 7 +--- encoding/apr_base64.c | 100 ++++++++++++++++++++++---------------------- include/apr_strings.h | 10 +++++ network_io/unix/sendrecv.c | 17 ++++---- network_io/win32/sendrecv.c | 33 +++++++++------ strings/apr_strings.c | 32 ++++++++++++++ 8 files changed, 134 insertions(+), 111 deletions(-) diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c index 7572a5904..fa08092e5 100644 --- a/crypto/apr_crypto.c +++ b/crypto/apr_crypto.c @@ -120,7 +120,7 @@ static apr_status_t crypto_clear(void *ptr) { apr_crypto_clear_t *clear = (apr_crypto_clear_t *)ptr; - apr_crypto_memzero(clear->buffer, clear->size); + apr_memzero_explicit(clear->buffer, clear->size); clear->buffer = NULL; clear->size = 0; @@ -141,36 +141,9 @@ APR_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool, return APR_SUCCESS; } -#if defined(HAVE_WEAK_SYMBOLS) -void apr__memzero_explicit(void *buffer, apr_size_t size); - -__attribute__ ((weak)) -void apr__memzero_explicit(void *buffer, apr_size_t size) -{ - memset(buffer, 0, size); -} -#endif - APR_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size) { -#if defined(WIN32) - SecureZeroMemory(buffer, size); -#elif defined(HAVE_MEMSET_S) - if (size) { - return memset_s(buffer, (rsize_t)size, 0, (rsize_t)size); - } -#elif defined(HAVE_EXPLICIT_BZERO) - explicit_bzero(buffer, size); -#elif defined(HAVE_WEAK_SYMBOLS) - apr__memzero_explicit(buffer, size); -#else - apr_size_t i; - volatile unsigned char *volatile ptr = buffer; - for (i = 0; i < size; ++i) { - ptr[i] = 0; - } -#endif - return APR_SUCCESS; + return apr_memzero_explicit(buffer, size); } APR_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2, diff --git a/crypto/apr_crypto_prng.c b/crypto/apr_crypto_prng.c index 842987f95..cd4a2044d 100644 --- a/crypto/apr_crypto_prng.c +++ b/crypto/apr_crypto_prng.c @@ -43,12 +43,13 @@ #include "apr_crypto.h" #include "apr_crypto_internal.h" +#include "apr_strings.h" + #if APU_HAVE_CRYPTO #if APU_HAVE_CRYPTO_PRNG #include "apr_ring.h" #include "apr_pools.h" -#include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_thread_proc.h" @@ -263,7 +264,7 @@ static apr_status_t cprng_cleanup(void *arg) } if (cprng->key) { - apr_crypto_memzero(cprng->key, CPRNG_KEY_SIZE + cprng->len); + apr_memzero_explicit(cprng->key, CPRNG_KEY_SIZE + cprng->len); } if (!cprng->pool) { @@ -435,7 +436,7 @@ static apr_status_t cprng_stream_bytes(apr_crypto_prng_t *cprng, rv = cprng->crypto->provider->cprng_stream_ctx_bytes(&cprng->ctx, cprng->key, to, len, cprng->buf); if (rv != APR_SUCCESS && len) { - apr_crypto_memzero(to, len); + apr_memzero_explicit(to, len); } return rv; } @@ -456,7 +457,7 @@ APR_DECLARE(apr_status_t) apr_crypto_prng_reseed(apr_crypto_prng_t *cprng, cprng_lock(cprng); cprng->pos = cprng->len; - apr_crypto_memzero(cprng->buf, cprng->len); + apr_memzero_explicit(cprng->buf, cprng->len); if (seed) { apr_size_t n = 0; do { @@ -528,7 +529,7 @@ static apr_status_t cprng_bytes(apr_crypto_prng_t *cprng, * both forward secrecy and cleared next mixed data. */ memcpy(ptr, cprng->buf + cprng->pos, n); - apr_crypto_memzero(cprng->buf + cprng->pos, n); + apr_memzero_explicit(cprng->buf + cprng->pos, n); cprng->pos += n; ptr += n; @@ -576,7 +577,7 @@ APR_DECLARE(apr_status_t) apr_crypto_prng_rekey(apr_crypto_prng_t *cprng) /* Clear state and renew the key. */ cprng->pos = cprng->len; - apr_crypto_memzero(cprng->buf, cprng->len); + apr_memzero_explicit(cprng->buf, cprng->len); rv = cprng_stream_bytes(cprng, NULL, 0); cprng_unlock(cprng); @@ -627,7 +628,7 @@ APR_DECLARE(apr_status_t) apr_crypto_prng_after_fork(apr_crypto_prng_t *cprng, * and that nothing is left over from the initial state in both processes. */ cprng->pos = cprng->len; - apr_crypto_memzero(cprng->buf, cprng->len); + apr_memzero_explicit(cprng->buf, cprng->len); if (!is_child) { rv = cprng_stream_bytes(cprng, cprng->key, CPRNG_KEY_SIZE); } diff --git a/crypto/apr_md4.c b/crypto/apr_md4.c index 22a0926e7..aef0a3404 100644 --- a/crypto/apr_md4.c +++ b/crypto/apr_md4.c @@ -41,7 +41,6 @@ #include "apr_strings.h" #include "apr_md4.h" #include "apr_lib.h" -#include "apr_crypto.h" /* for apr_crypto_memzero, if available */ #if APR_HAVE_STRING_H #include @@ -360,11 +359,7 @@ static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64]) state[3] += d; /* Zeroize sensitive information. */ -#if APU_HAVE_CRYPTO - apr_crypto_memzero(x, sizeof(x)); -#else - memset(x, 0, sizeof(x)); -#endif + apr_memzero_explicit(x, sizeof(x)); } /* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is diff --git a/encoding/apr_base64.c b/encoding/apr_base64.c index f5c2786ad..ab200cd7e 100644 --- a/encoding/apr_base64.c +++ b/encoding/apr_base64.c @@ -26,7 +26,7 @@ #include "apr_base64.h" #if APR_CHARSET_EBCDIC #include "apr_xlate.h" -#endif /* APR_CHARSET_EBCDIC */ +#endif /* APR_CHARSET_EBCDIC */ /* Above APR_BASE64_ENCODE_MAX length the encoding can't fit in an int >= 0 */ #define APR_BASE64_ENCODE_MAX 1610612733 @@ -141,7 +141,7 @@ APR_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded) inbytes_left = outbytes_left = len; apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left, bufplain, &outbytes_left); -#endif /* APR_CHARSET_EBCDIC */ +#endif /* APR_CHARSET_EBCDIC */ bufplain[len] = '\0'; return len; } @@ -151,7 +151,7 @@ APR_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded) * - on EBCDIC machines, the conversion of the output to ebcdic is left out */ APR_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain, - const char *bufcoded) + const char *bufcoded) { int nbytesdecoded; register const unsigned char *bufin; @@ -168,24 +168,24 @@ APR_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain, bufin = (const unsigned char *) bufcoded; while (nprbytes >= 4) { - *(bufout++) = - (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); - *(bufout++) = - (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); - *(bufout++) = - (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); - bufin += 4; - nprbytes -= 4; + *(bufout++) = + (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); + *(bufout++) = + (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); + *(bufout++) = + (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); + bufin += 4; + nprbytes -= 4; } /* Note: (nprbytes == 1) would be an error, so just ignore that case */ if (nprbytes > 1) { - *(bufout++) = - (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); + *(bufout++) = + (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); } if (nprbytes > 2) { - *(bufout++) = - (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); + *(bufout++) = + (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); } return nbytesdecoded - (int)((4u - nprbytes) & 3u); @@ -223,30 +223,30 @@ APR_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len) p = encoded; for (i = 0; i < len - 2; i += 3) { - *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F]; - *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | - ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)]; - *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) | - ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)]; - *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F]; + *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F]; + *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | + ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)]; + *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) | + ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)]; + *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F]; } if (i < len) { - *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F]; - if (i == (len - 1)) { - *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)]; - *p++ = '='; - } - else { - *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | - ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)]; - *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)]; - } - *p++ = '='; + *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F]; + if (i == (len - 1)) { + *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)]; + *p++ = '='; + } + else { + *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | + ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)]; + *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)]; + } + *p++ = '='; } *p++ = '\0'; return (unsigned int)(p - encoded); -#endif /* APR_CHARSET_EBCDIC */ +#endif /* APR_CHARSET_EBCDIC */ } /* This is the same as apr_base64_encode() except on EBCDIC machines, where @@ -262,25 +262,25 @@ APR_DECLARE(int) apr_base64_encode_binary(char *encoded, p = encoded; for (i = 0; i < len - 2; i += 3) { - *p++ = basis_64[(string[i] >> 2) & 0x3F]; - *p++ = basis_64[((string[i] & 0x3) << 4) | - ((int) (string[i + 1] & 0xF0) >> 4)]; - *p++ = basis_64[((string[i + 1] & 0xF) << 2) | - ((int) (string[i + 2] & 0xC0) >> 6)]; - *p++ = basis_64[string[i + 2] & 0x3F]; + *p++ = basis_64[(string[i] >> 2) & 0x3F]; + *p++ = basis_64[((string[i] & 0x3) << 4) | + ((int) (string[i + 1] & 0xF0) >> 4)]; + *p++ = basis_64[((string[i + 1] & 0xF) << 2) | + ((int) (string[i + 2] & 0xC0) >> 6)]; + *p++ = basis_64[string[i + 2] & 0x3F]; } if (i < len) { - *p++ = basis_64[(string[i] >> 2) & 0x3F]; - if (i == (len - 1)) { - *p++ = basis_64[((string[i] & 0x3) << 4)]; - *p++ = '='; - } - else { - *p++ = basis_64[((string[i] & 0x3) << 4) | - ((int) (string[i + 1] & 0xF0) >> 4)]; - *p++ = basis_64[((string[i + 1] & 0xF) << 2)]; - } - *p++ = '='; + *p++ = basis_64[(string[i] >> 2) & 0x3F]; + if (i == (len - 1)) { + *p++ = basis_64[((string[i] & 0x3) << 4)]; + *p++ = '='; + } + else { + *p++ = basis_64[((string[i] & 0x3) << 4) | + ((int) (string[i + 1] & 0xF0) >> 4)]; + *p++ = basis_64[((string[i + 1] & 0xF) << 2)]; + } + *p++ = '='; } *p++ = '\0'; diff --git a/include/apr_strings.h b/include/apr_strings.h index d5f8719d2..56f0426fc 100644 --- a/include/apr_strings.h +++ b/include/apr_strings.h @@ -182,6 +182,16 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...) __attribute__((format(printf,2,3))); +/** + * zero out the buffer provided, without being optimized out by + * the compiler. + * + * @param buffer buffer to zero out + * @param size size of the buffer to zero out + * @return APR_SUCCESS or an errno + */ +APR_DECLARE(apr_status_t) apr_memzero_explicit(void *buffer, apr_size_t size); + /** * Copy up to dst_size characters from src to dst; does not copy * past a NUL terminator in src, but always terminates dst with a NUL diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c index b9e580b1b..1b965af50 100644 --- a/network_io/unix/sendrecv.c +++ b/network_io/unix/sendrecv.c @@ -196,13 +196,8 @@ apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec, { #ifdef HAVE_WRITEV apr_ssize_t rv; - apr_size_t requested_len = 0; apr_int32_t i; - for (i = 0; i < nvec; i++) { - requested_len += vec[i].iov_len; - } - if (sock->options & APR_INCOMPLETE_WRITE) { sock->options &= ~APR_INCOMPLETE_WRITE; goto do_select; @@ -231,8 +226,16 @@ do_select: *len = 0; return errno; } - if ((sock->timeout > 0) && (rv < requested_len)) { - sock->options |= APR_INCOMPLETE_WRITE; + if (sock->timeout > 0) { + apr_size_t rv_len = rv; + for (i = 0; i < nvec; ++i) { + apr_size_t iov_len = vec[i].iov_len; + if (rv_len < iov_len) { + sock->options |= APR_INCOMPLETE_WRITE; + break; + } + rv_len -= iov_len; + } } (*len) = rv; return APR_SUCCESS; diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c index 20d802042..eb4dd241a 100644 --- a/network_io/win32/sendrecv.c +++ b/network_io/win32/sendrecv.c @@ -34,7 +34,10 @@ * than 8193 bytes. */ #define MAX_SEGMENT_SIZE 65536 + +/* Maximum number of WSABUF allocated for a single apr_socket_sendv() */ #define WSABUF_ON_STACK 50 +#define WSABUF_ON_HEAP 500 APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len) @@ -91,18 +94,26 @@ APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, apr_status_t rc = APR_SUCCESS; apr_ssize_t rv; apr_size_t cur_len; - apr_int32_t nvec = 0; - int i, j = 0; + apr_size_t nvec = 0; + apr_size_t n; + int i; DWORD dwBytes = 0; WSABUF *pWsaBuf; for (i = 0; i < in_vec; i++) { cur_len = vec[i].iov_len; - nvec++; + while (cur_len > APR_DWORD_MAX) { + if (nvec >= WSABUF_ON_HEAP) { + break; + } nvec++; cur_len -= APR_DWORD_MAX; } + if (nvec >= WSABUF_ON_HEAP) { + break; + } + nvec++; } pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec)) @@ -110,25 +121,23 @@ APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, if (!pWsaBuf) return APR_ENOMEM; - for (i = 0; i < in_vec; i++) { + for (n = i = 0; n < nvec; i++) { char * base = vec[i].iov_base; cur_len = vec[i].iov_len; - + do { if (cur_len > APR_DWORD_MAX) { - pWsaBuf[j].buf = base; - pWsaBuf[j].len = APR_DWORD_MAX; + pWsaBuf[n].buf = base; + pWsaBuf[n].len = APR_DWORD_MAX; cur_len -= APR_DWORD_MAX; base += APR_DWORD_MAX; } else { - pWsaBuf[j].buf = base; - pWsaBuf[j].len = (DWORD)cur_len; + pWsaBuf[n].buf = base; + pWsaBuf[n].len = (DWORD)cur_len; cur_len = 0; } - j++; - - } while (cur_len > 0); + } while (++n < nvec && cur_len > 0); } rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL); if (rv == SOCKET_ERROR) { diff --git a/strings/apr_strings.c b/strings/apr_strings.c index beca6d480..2519f95b9 100644 --- a/strings/apr_strings.c +++ b/strings/apr_strings.c @@ -212,6 +212,38 @@ APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec, return res; } +#if defined(HAVE_WEAK_SYMBOLS) +void apr__memzero_explicit(void *buffer, apr_size_t size); + +__attribute__ ((weak)) +void apr__memzero_explicit(void *buffer, apr_size_t size) +{ + memset(buffer, 0, size); +} +#endif + +APR_DECLARE(apr_status_t) apr_memzero_explicit(void *buffer, apr_size_t size) +{ +#if defined(WIN32) + SecureZeroMemory(buffer, size); +#elif defined(HAVE_EXPLICIT_BZERO) + explicit_bzero(buffer, size); +#elif defined(HAVE_MEMSET_S) + if (size) { + return memset_s(buffer, (rsize_t)size, 0, (rsize_t)size); + } +#elif defined(HAVE_WEAK_SYMBOLS) + apr__memzero_explicit(buffer, size); +#else + apr_size_t i; + volatile unsigned char *volatile ptr = buffer; + for (i = 0; i < size; ++i) { + ptr[i] = 0; + } +#endif + return APR_SUCCESS; +} + #if (!APR_HAVE_MEMCHR) void *memchr(const void *s, int c, size_t n) { -- cgit v1.2.1