From 007871c35628054bbfdb323e1991da872dd0d17d Mon Sep 17 00:00:00 2001 From: Robert Clausecker Date: Fri, 25 Oct 2024 17:16:27 +0200 Subject: [PATCH] lib/libc/string: add memset_explicit() for compliance with C23 Patterned after explicit_bzero, visible from C23 onwards. Reviewed by: emaste, kevans Differential Revision: https://reviews.freebsd.org/D47286 --- include/string.h | 3 +++ lib/libc/string/Makefile.inc | 4 +++- lib/libc/string/Symbol.map | 4 ++++ lib/libc/string/memset.3 | 18 ++++++++++++++++-- lib/libc/string/memset_explicit.c | 26 ++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 lib/libc/string/memset_explicit.c diff --git a/include/string.h b/include/string.h index d9adcf4e0e41..73b675370c58 100644 --- a/include/string.h +++ b/include/string.h @@ -71,6 +71,9 @@ void *(memmove)(void *, const void *, size_t); void *(mempcpy)(void * __restrict, const void * __restrict, size_t); #endif void *(memset)(void *, int, size_t); +#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 2023 +void *memset_explicit(void *, int, size_t); +#endif #if __POSIX_VISIBLE >= 200809 char *(stpcpy)(char * __restrict, const char * __restrict); char *(stpncpy)(char * __restrict, const char * __restrict, size_t); diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc index c5ded194c78a..5d4a9a6e3eed 100644 --- a/lib/libc/string/Makefile.inc +++ b/lib/libc/string/Makefile.inc @@ -11,6 +11,7 @@ MISRCS+=bcmp.c bcopy.c bzero.c explicit_bzero.c \ ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \ memccpy.c memchr.c memrchr.c memcmp.c \ memcpy.c memmem.c memmove.c mempcpy.c memset.c memset_s.c \ + memset_explicit.c \ stpcpy.c stpncpy.c strcasecmp.c \ strcat.c strcasestr.c strchr.c strchrnul.c strcmp.c strcoll.c strcpy.c\ strcspn.c strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c \ @@ -62,7 +63,8 @@ MLINKS+=ffs.3 ffsl.3 \ MLINKS+=index.3 rindex.3 MLINKS+=memchr.3 memrchr.3 MLINKS+=memcpy.3 mempcpy.3 -MLINKS+=memset.3 memset_s.3 +MLINKS+=memset.3 memset_s.3 \ + memset.3 memset_explicit.3 MLINKS+=strcasecmp.3 strncasecmp.3 \ strcasecmp.3 strcasecmp_l.3 \ strcasecmp.3 strncasecmp_l.3 diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map index fd854d1f9479..6b2c41124adf 100644 --- a/lib/libc/string/Symbol.map +++ b/lib/libc/string/Symbol.map @@ -116,6 +116,10 @@ FBSD_1.7 { wmempcpy; }; +FBSD_1.8 { + memset_explicit; +}; + FBSDprivate_1.0 { __strtok_r; }; diff --git a/lib/libc/string/memset.3 b/lib/libc/string/memset.3 index 3ae485f68a92..f2dba3ec5a48 100644 --- a/lib/libc/string/memset.3 +++ b/lib/libc/string/memset.3 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 19, 2018 +.Dd October 24, 2024 .Dt MEMSET 3 .Os .Sh NAME @@ -41,6 +41,8 @@ .In string.h .Ft void * .Fn memset "void *dest" "int c" "size_t len" +.Ft void * +.Fn memset_explicit "void *dest" "int c" "size_t len" .Fd #define __STDC_WANT_LIB_EXT1__ 1 .Ft errno_t .Fn memset_s "void *dest" "rsize_t destsz" "int c" "rsize_t len" @@ -68,6 +70,13 @@ The behaviour is also undefined if is an invalid pointer. .Pp The +.Fn memset_explicit +function behaves the same as +.Fn memset, but will not be removed by a compiler's dead store +optimization pass, making it useful for clearing sensitive memory +such as a password. +.Pp +The .Fn memset_s function behaves the same as .Fn memset @@ -108,7 +117,9 @@ before .Sh RETURN VALUES The .Fn memset -function returns its first argument. +and +.Fn memset_explicit +functions return their first argument. The .Fn memset_s function returns zero on success, non-zero on error. @@ -128,3 +139,6 @@ conforms to conforms to .St -isoC-2011 K.3.7.4.1. +.Fn memset_explicit +conforms to +.St -isoC-2024 . diff --git a/lib/libc/string/memset_explicit.c b/lib/libc/string/memset_explicit.c new file mode 100644 index 000000000000..ee6be0363981 --- /dev/null +++ b/lib/libc/string/memset_explicit.c @@ -0,0 +1,26 @@ +/*- + * SPDF-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Robert Clausecker + */ + +#include + +__attribute__((weak)) void __memset_explicit_hook(void *, int, size_t); + +__attribute__((weak)) void +__memset_explicit_hook(void *buf, int ch, size_t len) +{ + (void)buf; + (void)ch; + (void)len; +} + +void * +memset_explicit(void *buf, int ch, size_t len) +{ + memset(buf, ch, len); + __memset_explicit_hook(buf, ch, len); + + return (buf); +}