Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 26 May 2023 11:25:43 +0200
From: Jens Gustedt <>
Subject: [C23 string conversion 1/3] C23: add the new memset_explicit function

This function is meant to work around the fact that C compilers are
allowed to optimize calls to memset out, if they are able to detect
that the byte array will die soon, anyway. This permission for memset
may lead to data leak when non-priveledged parts of an application
would be able to reconstruct secret information from memory received
through malloc or on the stack.

This function here is to force compilers to do the clean up operation
under all circumstances. How to do that is out of the scope of the C
standard, so there is not much help there, it only describes the

By having a slow bytewise copy, we intent also to have predictable
timing, such that we can avoid side-channel attacks. We also do our
best to remove the meta-information, which is the pointer value from
the stack and combine that with a synchronizing operation at the end.
 include/string.h             |  1 +
 src/string/memset_explicit.c | 14 ++++++++++++++
 2 files changed, 15 insertions(+)
 create mode 100644 src/string/memset_explicit.c

diff --git a/include/string.h b/include/string.h
index 05019c03..78ccccbd 100644
--- a/include/string.h
+++ b/include/string.h
@@ -27,6 +27,7 @@ extern "C" {
 void *memcpy (void *__restrict, const void *__restrict, size_t);
 void *memmove (void *, const void *, size_t);
 void *memset (void *, int, size_t);
+void *memset_explicit(void *, int, size_t);
 int memcmp (const void *, const void *, size_t);
 void *(memchr) (const void *, int, size_t);
diff --git a/src/string/memset_explicit.c b/src/string/memset_explicit.c
new file mode 100644
index 00000000..49ced751
--- /dev/null
+++ b/src/string/memset_explicit.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#include <stdlib.h>
+#include <atomic.h>
+void *memset_explicit(void *dest, register int c, register size_t n)
+  register unsigned char volatile *p    = dest;
+  register unsigned char volatile *stop = p + n;
+  for (; p < stop; ++p)
+    *p = c;
+  // the CAS operation serves as memory barrier, and destroys the
+  // information, if it happened to be spilled on the stack
+  return a_cas_p(&dest, dest, 0);

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.