From 7cfeceb25537bba01e55fc7fd733375551e030b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Sat, 30 Mar 2024 00:08:56 +0100 Subject: [PATCH] Use explicit_bzero(3) to clear passwords, if it is available Relying on volatile to clear memory is, in many cases, insufficient and may result in the clearing operation being optimized out by the compiler. Recognizing the difficulty of zero'ing memory, many libcs provide an explicit_bzero(3) function (which the libc guarantees not to be optimized out). This is presently implemented by OpenBSD, musl libc and glibc. This patch makes swaylock use this function and, if it is not available, falls back to the existing code and prints a warning during build. For more details on the complexity of zero'ing memory, refer to the following 35c3 talk: https://media.ccc.de/v/35c3-9788-memsad --- meson.build | 10 ++++++++++ password.c | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/meson.build b/meson.build index a0f02a20..fee7cdc7 100644 --- a/meson.build +++ b/meson.build @@ -40,6 +40,15 @@ crypt = cc.find_library('crypt', required: not libpam.found()) math = cc.find_library('m') rt = cc.find_library('rt') +have_explicit_bzero = cc.has_function( + 'explicit_bzero', + args: ['-D_BSD_SOURCE'], + prefix: '#include ' +) +if not have_explicit_bzero + warning('Your system does not support explicit_bzero(3), using precarious fallback function to clear passwords') +endif + git = find_program('git', required: false) scdoc = find_program('scdoc', required: get_option('man-pages')) wayland_scanner_prog = find_program(wayland_scanner.get_variable('wayland_scanner'), native: true) @@ -81,6 +90,7 @@ conf_data = configuration_data() conf_data.set_quoted('SYSCONFDIR', get_option('prefix') / get_option('sysconfdir')) conf_data.set_quoted('SWAYLOCK_VERSION', version) conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found()) +conf_data.set10('HAVE_EXPLICIT_BZERO', have_explicit_bzero) subdir('include') diff --git a/password.c b/password.c index cae568ec..55fd7be3 100644 --- a/password.c +++ b/password.c @@ -1,3 +1,4 @@ +#define _BSD_SOURCE // for explicit_bzero #include #include #include @@ -13,12 +14,16 @@ #include "unicode.h" void clear_buffer(char *buf, size_t size) { +#ifdef HAVE_EXPLICIT_BZERO + explicit_bzero(buf, size); +#else // Use volatile keyword so so compiler can't optimize this out. volatile char *buffer = buf; volatile char zero = '\0'; for (size_t i = 0; i < size; ++i) { buffer[i] = zero; } +#endif } void clear_password_buffer(struct swaylock_password *pw) {