From 197a9a6cfcdcf841793b5e4a2f381837f63c9514 Mon Sep 17 00:00:00 2001 From: Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> Date: Fri, 2 Dec 2022 23:26:22 +0100 Subject: Extend CodeQL configuration and fix two warnings (#1816) ``` Call to `memset` may be deleted Comparison of narrow type with wide type in loop condition ``` See https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf for the new portable function `secure_memzero`. --- src/lib/third_party/include/secure_memzero.h | 194 +++++++++++++++++++++++++++ src/lib/third_party/src/ndpi_sha1.c | 3 +- src/lib/third_party/src/roaring.cc | 2 +- 3 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 src/lib/third_party/include/secure_memzero.h (limited to 'src') diff --git a/src/lib/third_party/include/secure_memzero.h b/src/lib/third_party/include/secure_memzero.h new file mode 100644 index 000000000..f70a163f9 --- /dev/null +++ b/src/lib/third_party/include/secure_memzero.h @@ -0,0 +1,194 @@ +// secure_memzero.h version 1 (October 29, 2016) +// +// This code is released into the public domain. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// The secure_memzero macro/function attempts to ensure that an optimizing +// compiler does not remove the intended operation if cleared memory is not +// accessed again by the program. There are several known ways of doing this, +// however no single one is both universally available and absolutely guranteed +// by the standard. The following code defines secure_memzero as a macro or +// function using one of the known alternatives. The choice of implementation +// can be controlled by defining a preprocessor macro of the form SMZ_impl, +// where is one of the defined implementation names. SMZ_impl should +// expand to an integer indicating the dgeree of preference for the +// implementation, where numerically higher values indicate greater preference. +// Defining SMZ_impl to be 0 disables the implementation even if it is +// available. Not defining any SMZ_impl will result in default (safe) behavior. +// +// The following implementations may be used. +// +// SMZ_SECUREZEROMEMORY +// Uses the SecureZeroMemory macro/function on Windows. Requires a Windows +// environment (_WIN32 must be defined). +// +// SMZ_ASM_BARRIER +// Uses a compiler memory barrier to force the results of a memset to be +// committed to memory. Has been tested to work on: +// - Clang 3.9.0 at all optimization levels. +// - GCC 6.2 at all optimization levels. +// +// SMZ_MEMSET_S +// Uses the C11 function memset_s. Currently not available on many platforms. +// Note that if you want this option, you have to set __STDC_WANT_LIB_EXT1__ +// to 1 before including string.h or any file that includes string.h in a +// compilation unit that includes this header. +// +// SMZ_VDATAPTR +// Uses the volatile data pointer technique to zero one byte at a time. This is +// not guaranteed to work by the C standard, which does not require access to +// non-volatile objects via a pointer-to-volatile to be treated as a volatile +// access. However, it is known to work on the following compilers: +// - Clang 3.9.0 at all optimization levels. +// - GCC 6.2 at all optimization levels. +// +// SMZ_VFUNCPTR +// Uses the volatile function pointer technique to call memset. This is not +// guaranteed to work by the C standard, which does not require the pointed-to +// function to be called. However, it is known to work on the following +// compilers: +// - Clang 3.9.0 at all optimization levels. +// - GCC 6.2 at all optimization levels. + +// The remainder of this file implements the selection logic using the +// specified compile-time preferences. + +#ifndef _SECURE_MEMZERO_H_ +#define _SECURE_MEMZERO_H_ + +// STEP 1. Set default preference for all implementations to 1. + +#ifndef SMZ_SECUREZEROMEMORY +#define SMZ_SECUREZEROMEMORY 1 +#endif + +#ifndef SMZ_MEMSET_S +#define SMZ_MEMSET_S 1 +#endif + +#ifndef SMZ_ASM_BARRIER +#define SMZ_ASM_BARRIER 1 +#endif + +#ifndef SMZ_VDATAPTR +#define SMZ_VDATAPTR 1 +#endif + +#ifndef SMZ_VFUNCPTR +#define SMZ_VFUNCPTR 1 +#endif + +// STEP 2. Check which implementations are available and include any necessary +// header files. + +#if SMZ_SECUREZEROMEMORY > 0 +#ifdef _WIN32 +#include +#else +#undef SMZ_SECUREZEROMEMORY +#define SMZ_SECUREZEROMEMORY 0 +#endif +#endif + +#if SMZ_MEMSET_S > 0 +#if defined(__STDC_WANT_LIB_EXT1__) && (__STDC_WANT_LIB_EXT1__ != 1) +#undef SMZ_MEMSET_S +#define SMZ_MEMSET_S 0 +#endif +#if SMZ_MEMSET_S > 0 +#ifndef __STDC_WANT_LIB_EXT1__ +// Must come before first include of string.h +#define __STDC_WANT_LIB_EXT1__ 1 +#endif +#include +#ifndef __STDC_LIB_EXT1__ +#undef SMZ_MEMSET_S +#define SMZ_MEMSET_S 0 +#endif +#endif +#endif + +#if !defined(__GNUC__) && !defined(__clang__) +#undef SMZ_ASM_BARRIER +#define SMZ_ASM_BARRIER 0 +#endif + +#if SMZ_VFUNCPTR > 0 +#include +#endif + +// STEP 3. Calculate highest preference. + +#define SMZ_PREFERENCE 0 + +#if SMZ_PREFERENCE < SMZ_SECUREZEROMEMORY +#undef SMZ_PREFERENCE +#define SMZ_PREFERENCE SMZ_SECUREZEROMEMORY +#endif + +#if SMZ_PREFERENCE < SMZ_MEMSET_S +#undef SMZ_PREFERENCE +#define SMZ_PREFERENCE SMZ_MEMSET_S +#endif + +#if SMZ_PREFERENCE < SMZ_ASM_BARRIER +#undef SMZ_PREFERENCE +#define SMZ_PREFERENCE SMZ_ASM_BARRIER +#endif + +#if SMZ_PREFERENCE < SMZ_VDATAPTR +#undef SMZ_PREFERENCE +#define SMZ_PREFERENCE SMZ_VDATAPTR +#endif + +#if SMZ_PREFERENCE < SMZ_VFUNCPTR +#undef SMZ_PREFERENCE +#define SMZ_PREFERENCE SMZ_VFUNCPTR +#endif + +// STEP 4. Make sure we have something chosen. + +#if SMZ_PREFERENCE <= 0 +#error No secure_memzero implementation available +#endif + +// STEP 5. Use implementation with highest preference. Ties are broken in +// favor of implementations appearing first, below. + +#if SMZ_PREFERENCE == SMZ_SECUREZEROMEMORY +#define secure_memzero(ptr,len) SecureZeroMemory((ptr),(len)) + +#elif SMZ_PREFERENCE == SMZ_MEMSET_S +#define secure_memzero(ptr,len) memset_s((ptr),(len),0,(len)) + +#elif SMZ_PREFERENCE == SMZ_ASM_BARRIER +#define secure_memzero(ptr,len) do { \ + memset((ptr),0,(len)); \ + __asm__ __volatile__("" ::"r"(ptr): "memory"); \ +} while (0) + +#elif SMZ_PREFERENCE == SMZ_VDATAPTR +static void secure_memzero(void * ptr, size_t len) { + volatile char * p = ptr; + while (len--) *p++ = 0; +} + +#elif SMZ_PREFERENCE == SMZ_VFUNCPTR +static void * (* volatile _smz_memset_fptr)(void*,int,size_t) = &memset; +static void secure_memzero(void * ptr, size_t len) { + _smz_memset_fptr(ptr, 0, len); +} + +#endif + +#endif // _SECURE_MEMZERO_H_ diff --git a/src/lib/third_party/src/ndpi_sha1.c b/src/lib/third_party/src/ndpi_sha1.c index 66e4592e9..60ab6e613 100644 --- a/src/lib/third_party/src/ndpi_sha1.c +++ b/src/lib/third_party/src/ndpi_sha1.c @@ -29,6 +29,7 @@ A million repetitions of "a" #endif #include "ndpi_main.h" #include "ndpi_sha1.h" +#include "../include/secure_memzero.h" #ifdef WIN32 #define BYTE_ORDER LITTLE_ENDIAN @@ -164,7 +165,7 @@ CHAR64LONG16* block = (const CHAR64LONG16*)buffer; /* Wipe variables */ a = b = c = d = e = 0; #ifdef SHA1HANDSOFF - memset(block, '\0', sizeof(block)); + secure_memzero(block, sizeof(block)); #endif } diff --git a/src/lib/third_party/src/roaring.cc b/src/lib/third_party/src/roaring.cc index 36b96bed3..778d36004 100644 --- a/src/lib/third_party/src/roaring.cc +++ b/src/lib/third_party/src/roaring.cc @@ -2302,7 +2302,7 @@ static inline bool bitset_container_get_range(const bitset_container_t *bitset, return false; } - uint16_t i; for (i = start + 1; (i < BITSET_CONTAINER_SIZE_IN_WORDS) && (i < end); ++i){ + uint32_t i; for (i = start + 1; (i < BITSET_CONTAINER_SIZE_IN_WORDS) && (i < end); ++i){ if (bitset->words[i] != UINT64_C(0xFFFFFFFFFFFFFFFF)) return false; } -- cgit v1.2.3