/* Erasure of sensitive data, generic implementation.
Copyright (C) 2016-2022 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
+ This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
-/* An assembler implementation of explicit_bzero can be created as an
- assembler alias of an optimized bzero implementation.
- Architecture-specific implementations also need to define
- __explicit_bzero_chk. */
-
-#if !_LIBC
-# include <config.h>
-#endif
-
-/* memset_s need this define */
-#if HAVE_MEMSET_S
-# define __STDC_WANT_LIB_EXT1__ 1
-#endif
+#include <config.h>
#include <string.h>
-#if defined _WIN32 && !defined __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#if _LIBC
-/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero
- redirects to that. */
-# undef explicit_bzero
-#endif
-
/* Set LEN bytes of S to 0. The compiler will not delete a call to
this function, even if S is dead after the call. */
void
explicit_bzero (void *s, size_t len)
{
-#if defined _WIN32 && !defined __CYGWIN__
- (void) SecureZeroMemory (s, len);
-#elif HAVE_EXPLICIT_MEMSET
- explicit_memset (s, '\0', len);
-#elif HAVE_MEMSET_S
- (void) memset_s (s, len, '\0', len);
-#elif defined __GNUC__ && !defined __clang__
- memset (s, '\0', len);
- /* Compiler barrier. */
- asm volatile ("" ::: "memory");
-#elif defined __clang__
- memset (s, '\0', len);
- /* Compiler barrier. */
- /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the
- whole thing is dead and eliminates it. Use 'g' to work around this
- problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */
- __asm__ volatile ("" : : "g"(s) : "memory");
-#else
- /* Invoke memset through a volatile function pointer. This defeats compiler
- optimizations. */
- void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
- (void) volatile_memset (s, '\0', len);
-#endif
+ memset_explicit (s, 0, len);
}
GL_COND_OBJ_LSTAT_CONDITION = @GL_COND_OBJ_LSTAT_CONDITION@
GL_COND_OBJ_MEMPCPY_CONDITION = @GL_COND_OBJ_MEMPCPY_CONDITION@
GL_COND_OBJ_MEMRCHR_CONDITION = @GL_COND_OBJ_MEMRCHR_CONDITION@
+GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION = @GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION@
GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION = @GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION@
GL_COND_OBJ_MKOSTEMP_CONDITION = @GL_COND_OBJ_MKOSTEMP_CONDITION@
GL_COND_OBJ_NANOSLEEP_CONDITION = @GL_COND_OBJ_NANOSLEEP_CONDITION@
GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@
GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@
GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@
+GL_GNULIB_MEMSET_EXPLICIT = @GL_GNULIB_MEMSET_EXPLICIT@
GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@
GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@
GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@
HAVE_MBSLEN = @HAVE_MBSLEN@
HAVE_MBTOWC = @HAVE_MBTOWC@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
+HAVE_MEMSET_EXPLICIT = @HAVE_MEMSET_EXPLICIT@
HAVE_MKDIRAT = @HAVE_MKDIRAT@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
HAVE_MKFIFO = @HAVE_MKFIFO@
endif
## end gnulib module memrchr
+## begin gnulib module memset_explicit
+ifeq (,$(OMIT_GNULIB_MODULE_memset_explicit))
+
+ifneq (,$(GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION))
+libgnu_a_SOURCES += memset_explicit.c
+endif
+
+endif
+## end gnulib module memset_explicit
+
## begin gnulib module minmax
ifeq (,$(OMIT_GNULIB_MODULE_minmax))
-e 's/@''GNULIB_MEMMEM''@/$(GL_GNULIB_MEMMEM)/g' \
-e 's/@''GNULIB_MEMPCPY''@/$(GL_GNULIB_MEMPCPY)/g' \
-e 's/@''GNULIB_MEMRCHR''@/$(GL_GNULIB_MEMRCHR)/g' \
+ -e 's/@''GNULIB_MEMSET_EXPLICIT''@/$(GL_GNULIB_MEMSET_EXPLICIT)/g' \
-e 's/@''GNULIB_RAWMEMCHR''@/$(GL_GNULIB_RAWMEMCHR)/g' \
-e 's/@''GNULIB_STPCPY''@/$(GL_GNULIB_STPCPY)/g' \
-e 's/@''GNULIB_STPNCPY''@/$(GL_GNULIB_STPNCPY)/g' \
-e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \
-e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \
-e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \
+ -e 's|@''HAVE_MEMSET_EXPLICIT''@|$(HAVE_MEMSET_EXPLICIT)|g' \
-e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \
-e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \
-e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
--- /dev/null
+/* Erase sensitive data from memory.
+ Copyright 2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* memset_s need this define */
+#if HAVE_MEMSET_S
+# define __STDC_WANT_LIB_EXT1__ 1
+#endif
+
+#include <string.h>
+
+/* Set S's bytes to C, where S has LEN bytes. The compiler will not
+ optimize effects away, even if S is dead after the call. */
+void *
+memset_explicit (void *s, int c, size_t len)
+{
+#if HAVE_EXPLICIT_MEMSET
+ return explicit_memset (s, c, len);
+#elif HAVE_MEMSET_S
+ (void) memset_s (s, len, c, len);
+ return s;
+#elif defined __GNUC__ && !defined __clang__
+ memset (s, c, len);
+ /* Compiler barrier. */
+ __asm__ volatile ("" ::: "memory");
+ return s;
+#elif defined __clang__
+ memset (s, c, len);
+ /* Compiler barrier. */
+ /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the
+ whole thing is dead and eliminates it. Use 'g' to work around this
+ problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */
+ __asm__ volatile ("" : : "g"(s) : "memory");
+ return s;
+#else
+ /* Invoke memset through a volatile function pointer. This defeats compiler
+ optimizations. */
+ void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
+ return volatile_memset (s, c, len);
+#endif
+}
# endif
#endif
+/* Overwrite a block of memory. The compiler will not optimize
+ effects away, even if the block is dead after the call. */
+#if @GNULIB_MEMSET_EXPLICIT@
+# if ! @HAVE_MEMSET_EXPLICIT@
+_GL_FUNCDECL_SYS (memset_explicit, void *,
+ (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (memset_explicit, void *, (void *__dest, int __c, size_t __n));
+_GL_CXXALIASWARN (memset_explicit);
+#elif defined GNULIB_POSIXCHECK
+# undef memset_explicit
+# if HAVE_RAW_DECL_MEMSET_EXPLICIT
+_GL_WARN_ON_USE (memset_explicit, "memset_explicit is unportable - "
+ "use gnulib module memset_explicit for portability");
+# endif
+#endif
+
/* Find the first occurrence of C in S. More efficient than
memchr(S,C,N), at the expense of undefined behavior if C does not
occur within N bytes. */
&& (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__)))
# define _GL_HAVE__STATIC_ASSERT 1
# endif
-# if (202000 <= __STDC_VERSION__ \
+# if (202311 <= __STDC_VERSION__ \
|| (!defined __STRICT_ANSI__ && 9 <= __GNUC__))
# define _GL_HAVE__STATIC_ASSERT1 1
# endif
HAVE_EXPLICIT_BZERO=0
fi
])
-
-AC_DEFUN([gl_PREREQ_EXPLICIT_BZERO],
-[
- AC_CHECK_FUNCS([explicit_memset])
- AC_CHECK_FUNCS_ONCE([memset_s])
-])
# Code from module memmem-simple:
# Code from module mempcpy:
# Code from module memrchr:
+ # Code from module memset_explicit:
# Code from module minmax:
# Code from module mkostemp:
# Code from module mktime:
gl_CONDITIONAL([GL_COND_OBJ_EXECINFO], [$GL_GENERATE_EXECINFO_H])
gl_FUNC_EXPLICIT_BZERO
gl_CONDITIONAL([GL_COND_OBJ_EXPLICIT_BZERO], [test $HAVE_EXPLICIT_BZERO = 0])
- AM_COND_IF([GL_COND_OBJ_EXPLICIT_BZERO], [
- gl_PREREQ_EXPLICIT_BZERO
- ])
gl_STRING_MODULE_INDICATOR([explicit_bzero])
AC_REQUIRE([gl_EXTERN_INLINE])
gl_FUNC_FACCESSAT
gl_PREREQ_MEMRCHR
])
gl_STRING_MODULE_INDICATOR([memrchr])
+ gl_FUNC_MEMSET_EXPLICIT
+ gl_CONDITIONAL([GL_COND_OBJ_MEMSET_EXPLICIT], [test $HAVE_MEMSET_EXPLICIT = 0])
+ AM_COND_IF([GL_COND_OBJ_MEMSET_EXPLICIT], [
+ gl_PREREQ_MEMSET_EXPLICIT
+ ])
+ gl_STRING_MODULE_INDICATOR([memset_explicit])
gl_MINMAX
gl_FUNC_MKOSTEMP
gl_CONDITIONAL([GL_COND_OBJ_MKOSTEMP], [test $HAVE_MKOSTEMP = 0])
lib/memmem.c
lib/mempcpy.c
lib/memrchr.c
+ lib/memset_explicit.c
lib/mini-gmp-gnulib.c
lib/mini-gmp.c
lib/mini-gmp.h
m4/memmem.m4
m4/mempcpy.m4
m4/memrchr.m4
+ m4/memset_explicit.m4
m4/minmax.m4
m4/mkostemp.m4
m4/mktime.m4
--- /dev/null
+dnl Copyright 2022 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_MEMSET_EXPLICIT],
+[
+ AC_REQUIRE([gl_STRING_H_DEFAULTS])
+
+ AC_CHECK_FUNCS_ONCE([memset_explicit])
+ if test $ac_cv_func_memset_explicit = no; then
+ HAVE_MEMSET_EXPLICIT=0
+ fi
+])
+
+AC_DEFUN([gl_PREREQ_MEMSET_EXPLICIT],
+[
+ AC_CHECK_FUNCS([explicit_memset])
+ AC_CHECK_FUNCS_ONCE([memset_s])
+])
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 34
+# serial 35
# Written by Paul Eggert.
dnl guaranteed by C89.
gl_WARN_ON_USE_PREPARE([[#include <string.h>
]],
- [ffsl ffsll memmem mempcpy memrchr rawmemchr stpcpy stpncpy strchrnul
+ [explicit_bzero ffsl ffsll memmem mempcpy memrchr memset_explicit
+ rawmemchr stpcpy stpncpy strchrnul
strdup strncat strndup strnlen strpbrk strsep strcasestr strtok_r
strerror_r strerrorname_np sigabbrev_np sigdescr_np strsignal strverscmp])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMMEM])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMPCPY])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMRCHR])
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMSET_EXPLICIT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_RAWMEMCHR])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STPCPY])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STPNCPY])
HAVE_FFSLL=1; AC_SUBST([HAVE_FFSLL])
HAVE_DECL_MEMMEM=1; AC_SUBST([HAVE_DECL_MEMMEM])
HAVE_MEMPCPY=1; AC_SUBST([HAVE_MEMPCPY])
+ HAVE_MEMSET_EXPLICIT=1; AC_SUBST([HAVE_MEMSET_EXPLICIT])
HAVE_DECL_MEMRCHR=1; AC_SUBST([HAVE_DECL_MEMRCHR])
HAVE_RAWMEMCHR=1; AC_SUBST([HAVE_RAWMEMCHR])
HAVE_STPCPY=1; AC_SUBST([HAVE_STPCPY])