diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/explicit_bzero.c | 69 | ||||
| -rw-r--r-- | lib/gnulib.mk.in | 15 | ||||
| -rw-r--r-- | lib/memset_explicit.c | 55 | ||||
| -rw-r--r-- | lib/string.in.h | 17 | ||||
| -rw-r--r-- | lib/verify.h | 2 |
5 files changed, 99 insertions, 59 deletions
diff --git a/lib/explicit_bzero.c b/lib/explicit_bzero.c index ad0bfd170ca..fc309f81d61 100644 --- a/lib/explicit_bzero.c +++ b/lib/explicit_bzero.c | |||
| @@ -1,74 +1,27 @@ | |||
| 1 | /* Erasure of sensitive data, generic implementation. | 1 | /* Erasure of sensitive data, generic implementation. |
| 2 | Copyright (C) 2016-2022 Free Software Foundation, Inc. | 2 | Copyright (C) 2016-2022 Free Software Foundation, Inc. |
| 3 | This file is part of the GNU C Library. | ||
| 4 | 3 | ||
| 5 | The GNU C Library is free software; you can redistribute it and/or | 4 | This file is free software: you can redistribute it and/or modify |
| 6 | modify it under the terms of the GNU Lesser General Public | 5 | it under the terms of the GNU Lesser General Public License as |
| 7 | License as published by the Free Software Foundation; either | 6 | published by the Free Software Foundation; either version 2.1 of the |
| 8 | version 2.1 of the License, or (at your option) any later version. | 7 | License, or (at your option) any later version. |
| 9 | 8 | ||
| 10 | The GNU C Library is distributed in the hope that it will be useful, | 9 | This file is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | Lesser General Public License for more details. | 12 | GNU Lesser General Public License for more details. |
| 14 | 13 | ||
| 15 | You should have received a copy of the GNU Lesser General Public | 14 | You should have received a copy of the GNU Lesser General Public License |
| 16 | License along with the GNU C Library; if not, see | 15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
| 17 | <https://www.gnu.org/licenses/>. */ | ||
| 18 | 16 | ||
| 19 | /* An assembler implementation of explicit_bzero can be created as an | 17 | #include <config.h> |
| 20 | assembler alias of an optimized bzero implementation. | ||
| 21 | Architecture-specific implementations also need to define | ||
| 22 | __explicit_bzero_chk. */ | ||
| 23 | |||
| 24 | #if !_LIBC | ||
| 25 | # include <config.h> | ||
| 26 | #endif | ||
| 27 | |||
| 28 | /* memset_s need this define */ | ||
| 29 | #if HAVE_MEMSET_S | ||
| 30 | # define __STDC_WANT_LIB_EXT1__ 1 | ||
| 31 | #endif | ||
| 32 | 18 | ||
| 33 | #include <string.h> | 19 | #include <string.h> |
| 34 | 20 | ||
| 35 | #if defined _WIN32 && !defined __CYGWIN__ | ||
| 36 | # define WIN32_LEAN_AND_MEAN | ||
| 37 | # include <windows.h> | ||
| 38 | #endif | ||
| 39 | |||
| 40 | #if _LIBC | ||
| 41 | /* glibc-internal users use __explicit_bzero_chk, and explicit_bzero | ||
| 42 | redirects to that. */ | ||
| 43 | # undef explicit_bzero | ||
| 44 | #endif | ||
| 45 | |||
| 46 | /* Set LEN bytes of S to 0. The compiler will not delete a call to | 21 | /* Set LEN bytes of S to 0. The compiler will not delete a call to |
| 47 | this function, even if S is dead after the call. */ | 22 | this function, even if S is dead after the call. */ |
| 48 | void | 23 | void |
| 49 | explicit_bzero (void *s, size_t len) | 24 | explicit_bzero (void *s, size_t len) |
| 50 | { | 25 | { |
| 51 | #if defined _WIN32 && !defined __CYGWIN__ | 26 | memset_explicit (s, 0, len); |
| 52 | (void) SecureZeroMemory (s, len); | ||
| 53 | #elif HAVE_EXPLICIT_MEMSET | ||
| 54 | explicit_memset (s, '\0', len); | ||
| 55 | #elif HAVE_MEMSET_S | ||
| 56 | (void) memset_s (s, len, '\0', len); | ||
| 57 | #elif defined __GNUC__ && !defined __clang__ | ||
| 58 | memset (s, '\0', len); | ||
| 59 | /* Compiler barrier. */ | ||
| 60 | asm volatile ("" ::: "memory"); | ||
| 61 | #elif defined __clang__ | ||
| 62 | memset (s, '\0', len); | ||
| 63 | /* Compiler barrier. */ | ||
| 64 | /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the | ||
| 65 | whole thing is dead and eliminates it. Use 'g' to work around this | ||
| 66 | problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */ | ||
| 67 | __asm__ volatile ("" : : "g"(s) : "memory"); | ||
| 68 | #else | ||
| 69 | /* Invoke memset through a volatile function pointer. This defeats compiler | ||
| 70 | optimizations. */ | ||
| 71 | void * (* const volatile volatile_memset) (void *, int, size_t) = memset; | ||
| 72 | (void) volatile_memset (s, '\0', len); | ||
| 73 | #endif | ||
| 74 | } | 27 | } |
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 9af8fd0c579..a3ab50f396f 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in | |||
| @@ -286,6 +286,7 @@ GL_COND_OBJ_LCHMOD_CONDITION = @GL_COND_OBJ_LCHMOD_CONDITION@ | |||
| 286 | GL_COND_OBJ_LSTAT_CONDITION = @GL_COND_OBJ_LSTAT_CONDITION@ | 286 | GL_COND_OBJ_LSTAT_CONDITION = @GL_COND_OBJ_LSTAT_CONDITION@ |
| 287 | GL_COND_OBJ_MEMPCPY_CONDITION = @GL_COND_OBJ_MEMPCPY_CONDITION@ | 287 | GL_COND_OBJ_MEMPCPY_CONDITION = @GL_COND_OBJ_MEMPCPY_CONDITION@ |
| 288 | GL_COND_OBJ_MEMRCHR_CONDITION = @GL_COND_OBJ_MEMRCHR_CONDITION@ | 288 | GL_COND_OBJ_MEMRCHR_CONDITION = @GL_COND_OBJ_MEMRCHR_CONDITION@ |
| 289 | GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION = @GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION@ | ||
| 289 | GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION = @GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION@ | 290 | GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION = @GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION@ |
| 290 | GL_COND_OBJ_MKOSTEMP_CONDITION = @GL_COND_OBJ_MKOSTEMP_CONDITION@ | 291 | GL_COND_OBJ_MKOSTEMP_CONDITION = @GL_COND_OBJ_MKOSTEMP_CONDITION@ |
| 291 | GL_COND_OBJ_NANOSLEEP_CONDITION = @GL_COND_OBJ_NANOSLEEP_CONDITION@ | 292 | GL_COND_OBJ_NANOSLEEP_CONDITION = @GL_COND_OBJ_NANOSLEEP_CONDITION@ |
| @@ -485,6 +486,7 @@ GL_GNULIB_MEMCHR = @GL_GNULIB_MEMCHR@ | |||
| 485 | GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@ | 486 | GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@ |
| 486 | GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@ | 487 | GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@ |
| 487 | GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@ | 488 | GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@ |
| 489 | GL_GNULIB_MEMSET_EXPLICIT = @GL_GNULIB_MEMSET_EXPLICIT@ | ||
| 488 | GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@ | 490 | GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@ |
| 489 | GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@ | 491 | GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@ |
| 490 | GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@ | 492 | GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@ |
| @@ -749,6 +751,7 @@ HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ | |||
| 749 | HAVE_MBSLEN = @HAVE_MBSLEN@ | 751 | HAVE_MBSLEN = @HAVE_MBSLEN@ |
| 750 | HAVE_MBTOWC = @HAVE_MBTOWC@ | 752 | HAVE_MBTOWC = @HAVE_MBTOWC@ |
| 751 | HAVE_MEMPCPY = @HAVE_MEMPCPY@ | 753 | HAVE_MEMPCPY = @HAVE_MEMPCPY@ |
| 754 | HAVE_MEMSET_EXPLICIT = @HAVE_MEMSET_EXPLICIT@ | ||
| 752 | HAVE_MKDIRAT = @HAVE_MKDIRAT@ | 755 | HAVE_MKDIRAT = @HAVE_MKDIRAT@ |
| 753 | HAVE_MKDTEMP = @HAVE_MKDTEMP@ | 756 | HAVE_MKDTEMP = @HAVE_MKDTEMP@ |
| 754 | HAVE_MKFIFO = @HAVE_MKFIFO@ | 757 | HAVE_MKFIFO = @HAVE_MKFIFO@ |
| @@ -2536,6 +2539,16 @@ endif | |||
| 2536 | endif | 2539 | endif |
| 2537 | ## end gnulib module memrchr | 2540 | ## end gnulib module memrchr |
| 2538 | 2541 | ||
| 2542 | ## begin gnulib module memset_explicit | ||
| 2543 | ifeq (,$(OMIT_GNULIB_MODULE_memset_explicit)) | ||
| 2544 | |||
| 2545 | ifneq (,$(GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION)) | ||
| 2546 | libgnu_a_SOURCES += memset_explicit.c | ||
| 2547 | endif | ||
| 2548 | |||
| 2549 | endif | ||
| 2550 | ## end gnulib module memset_explicit | ||
| 2551 | |||
| 2539 | ## begin gnulib module minmax | 2552 | ## begin gnulib module minmax |
| 2540 | ifeq (,$(OMIT_GNULIB_MODULE_minmax)) | 2553 | ifeq (,$(OMIT_GNULIB_MODULE_minmax)) |
| 2541 | 2554 | ||
| @@ -3362,6 +3375,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H | |||
| 3362 | -e 's/@''GNULIB_MEMMEM''@/$(GL_GNULIB_MEMMEM)/g' \ | 3375 | -e 's/@''GNULIB_MEMMEM''@/$(GL_GNULIB_MEMMEM)/g' \ |
| 3363 | -e 's/@''GNULIB_MEMPCPY''@/$(GL_GNULIB_MEMPCPY)/g' \ | 3376 | -e 's/@''GNULIB_MEMPCPY''@/$(GL_GNULIB_MEMPCPY)/g' \ |
| 3364 | -e 's/@''GNULIB_MEMRCHR''@/$(GL_GNULIB_MEMRCHR)/g' \ | 3377 | -e 's/@''GNULIB_MEMRCHR''@/$(GL_GNULIB_MEMRCHR)/g' \ |
| 3378 | -e 's/@''GNULIB_MEMSET_EXPLICIT''@/$(GL_GNULIB_MEMSET_EXPLICIT)/g' \ | ||
| 3365 | -e 's/@''GNULIB_RAWMEMCHR''@/$(GL_GNULIB_RAWMEMCHR)/g' \ | 3379 | -e 's/@''GNULIB_RAWMEMCHR''@/$(GL_GNULIB_RAWMEMCHR)/g' \ |
| 3366 | -e 's/@''GNULIB_STPCPY''@/$(GL_GNULIB_STPCPY)/g' \ | 3380 | -e 's/@''GNULIB_STPCPY''@/$(GL_GNULIB_STPCPY)/g' \ |
| 3367 | -e 's/@''GNULIB_STPNCPY''@/$(GL_GNULIB_STPNCPY)/g' \ | 3381 | -e 's/@''GNULIB_STPNCPY''@/$(GL_GNULIB_STPNCPY)/g' \ |
| @@ -3393,6 +3407,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H | |||
| 3393 | -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ | 3407 | -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ |
| 3394 | -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ | 3408 | -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ |
| 3395 | -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ | 3409 | -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ |
| 3410 | -e 's|@''HAVE_MEMSET_EXPLICIT''@|$(HAVE_MEMSET_EXPLICIT)|g' \ | ||
| 3396 | -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ | 3411 | -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ |
| 3397 | -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ | 3412 | -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ |
| 3398 | -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ | 3413 | -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ |
diff --git a/lib/memset_explicit.c b/lib/memset_explicit.c new file mode 100644 index 00000000000..eabeb3ec2b8 --- /dev/null +++ b/lib/memset_explicit.c | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* Erase sensitive data from memory. | ||
| 2 | Copyright 2022 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU Lesser General Public License as | ||
| 6 | published by the Free Software Foundation; either version 2.1 of the | ||
| 7 | License, or (at your option) any later version. | ||
| 8 | |||
| 9 | This file is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU Lesser General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU Lesser General Public License | ||
| 15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 16 | |||
| 17 | #include <config.h> | ||
| 18 | |||
| 19 | /* memset_s need this define */ | ||
| 20 | #if HAVE_MEMSET_S | ||
| 21 | # define __STDC_WANT_LIB_EXT1__ 1 | ||
| 22 | #endif | ||
| 23 | |||
| 24 | #include <string.h> | ||
| 25 | |||
| 26 | /* Set S's bytes to C, where S has LEN bytes. The compiler will not | ||
| 27 | optimize effects away, even if S is dead after the call. */ | ||
| 28 | void * | ||
| 29 | memset_explicit (void *s, int c, size_t len) | ||
| 30 | { | ||
| 31 | #if HAVE_EXPLICIT_MEMSET | ||
| 32 | return explicit_memset (s, c, len); | ||
| 33 | #elif HAVE_MEMSET_S | ||
| 34 | (void) memset_s (s, len, c, len); | ||
| 35 | return s; | ||
| 36 | #elif defined __GNUC__ && !defined __clang__ | ||
| 37 | memset (s, c, len); | ||
| 38 | /* Compiler barrier. */ | ||
| 39 | __asm__ volatile ("" ::: "memory"); | ||
| 40 | return s; | ||
| 41 | #elif defined __clang__ | ||
| 42 | memset (s, c, len); | ||
| 43 | /* Compiler barrier. */ | ||
| 44 | /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the | ||
| 45 | whole thing is dead and eliminates it. Use 'g' to work around this | ||
| 46 | problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */ | ||
| 47 | __asm__ volatile ("" : : "g"(s) : "memory"); | ||
| 48 | return s; | ||
| 49 | #else | ||
| 50 | /* Invoke memset through a volatile function pointer. This defeats compiler | ||
| 51 | optimizations. */ | ||
| 52 | void * (* const volatile volatile_memset) (void *, int, size_t) = memset; | ||
| 53 | return volatile_memset (s, c, len); | ||
| 54 | #endif | ||
| 55 | } | ||
diff --git a/lib/string.in.h b/lib/string.in.h index e56f6db0c9c..21356914e21 100644 --- a/lib/string.in.h +++ b/lib/string.in.h | |||
| @@ -347,6 +347,23 @@ _GL_WARN_ON_USE (memrchr, "memrchr is unportable - " | |||
| 347 | # endif | 347 | # endif |
| 348 | #endif | 348 | #endif |
| 349 | 349 | ||
| 350 | /* Overwrite a block of memory. The compiler will not optimize | ||
| 351 | effects away, even if the block is dead after the call. */ | ||
| 352 | #if @GNULIB_MEMSET_EXPLICIT@ | ||
| 353 | # if ! @HAVE_MEMSET_EXPLICIT@ | ||
| 354 | _GL_FUNCDECL_SYS (memset_explicit, void *, | ||
| 355 | (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1))); | ||
| 356 | # endif | ||
| 357 | _GL_CXXALIAS_SYS (memset_explicit, void *, (void *__dest, int __c, size_t __n)); | ||
| 358 | _GL_CXXALIASWARN (memset_explicit); | ||
| 359 | #elif defined GNULIB_POSIXCHECK | ||
| 360 | # undef memset_explicit | ||
| 361 | # if HAVE_RAW_DECL_MEMSET_EXPLICIT | ||
| 362 | _GL_WARN_ON_USE (memset_explicit, "memset_explicit is unportable - " | ||
| 363 | "use gnulib module memset_explicit for portability"); | ||
| 364 | # endif | ||
| 365 | #endif | ||
| 366 | |||
| 350 | /* Find the first occurrence of C in S. More efficient than | 367 | /* Find the first occurrence of C in S. More efficient than |
| 351 | memchr(S,C,N), at the expense of undefined behavior if C does not | 368 | memchr(S,C,N), at the expense of undefined behavior if C does not |
| 352 | occur within N bytes. */ | 369 | occur within N bytes. */ |
diff --git a/lib/verify.h b/lib/verify.h index 99af802993e..5225a8e616d 100644 --- a/lib/verify.h +++ b/lib/verify.h | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__))) | 37 | && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__))) |
| 38 | # define _GL_HAVE__STATIC_ASSERT 1 | 38 | # define _GL_HAVE__STATIC_ASSERT 1 |
| 39 | # endif | 39 | # endif |
| 40 | # if (202000 <= __STDC_VERSION__ \ | 40 | # if (202311 <= __STDC_VERSION__ \ |
| 41 | || (!defined __STRICT_ANSI__ && 9 <= __GNUC__)) | 41 | || (!defined __STRICT_ANSI__ && 9 <= __GNUC__)) |
| 42 | # define _GL_HAVE__STATIC_ASSERT1 1 | 42 | # define _GL_HAVE__STATIC_ASSERT1 1 |
| 43 | # endif | 43 | # endif |