diff options
author | Christian Göttsche <cgzones@googlemail.com> | 2023-01-30 17:53:24 +0100 |
---|---|---|
committer | Christian Göttsche <cgzones@googlemail.com> | 2023-02-28 15:11:18 +0100 |
commit | 19a29268178951988eca29a7830f24bfef300c3c (patch) | |
tree | 23024993a88582f13a3d63a60446c6ab4207b12e /libpam/include/pam_inline.h | |
parent | bde2277d2aa1cd9d4a14a1a1f89241d5e86b0bad (diff) | |
download | pam-19a29268178951988eca29a7830f24bfef300c3c.tar.gz pam-19a29268178951988eca29a7830f24bfef300c3c.tar.bz2 pam-19a29268178951988eca29a7830f24bfef300c3c.zip |
libpam: introduce secure memory erasure helpers
Avoid compiler optimizations to elide the memory erasure by using a
secure method: either memset_explicit() [C23], bzero_explicit() [glibc
2.25] or a manual memory barrier.
Since the current helpers _pam_overwrite*() and _pam_drop_reply() are
publicly exported, create new ones in "pam_inline.h" and deprecate the
old ones.
Diffstat (limited to 'libpam/include/pam_inline.h')
-rw-r--r-- | libpam/include/pam_inline.h | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h index ec2f3bf0..6fe37857 100644 --- a/libpam/include/pam_inline.h +++ b/libpam/include/pam_inline.h @@ -9,6 +9,7 @@ #define PAM_INLINE_H #include "pam_cc_compat.h" +#include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> @@ -33,6 +34,12 @@ * 0, otherwise. */ #define PAM_MUST_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(!PAM_IS_NOT_ARRAY(a_)) +/* + * Evaluates to + * - a syntax error if the argument is an array, + * 0, otherwise. + */ +#define PAM_MUST_NOT_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(PAM_IS_NOT_ARRAY(a_)) /* Evaluates to the number of elements in the specified array. */ #define PAM_ARRAY_SIZE(a_) (sizeof(a_) / sizeof((a_)[0]) + PAM_MUST_BE_ARRAY(a_)) @@ -66,6 +73,59 @@ pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix #define pam_str_skip_icase_prefix(str_, prefix_) \ pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) + +/* + * Macros to securely erase memory + */ + +#ifdef HAVE_MEMSET_EXPLICIT +static inline void pam_overwrite_n(void *ptr, size_t len) +{ + if (ptr) + memset_explicit(ptr, len); +} +#elif defined HAVE_EXPLICIT_BZERO +static inline void pam_overwrite_n(void *ptr, size_t len) +{ + if (ptr) + explicit_bzero(ptr, len); +} +#else +static inline void pam_overwrite_n(void *ptr, size_t len) +{ + if (ptr) { + ptr = memset(ptr, '\0', len); + __asm__ __volatile__ ("" : : "r"(ptr) : "memory"); + } +} +#endif + +#define pam_overwrite_string(x) \ +do { \ + char *xx__ = (x) + PAM_MUST_NOT_BE_ARRAY(x); \ + if (xx__) \ + pam_overwrite_n(xx__, strlen(xx__)); \ +} while(0) + +#define pam_overwrite_array(x) pam_overwrite_n(x, sizeof(x) + PAM_MUST_BE_ARRAY(x)) + +#define pam_overwrite_object(x) pam_overwrite_n(x, sizeof(*(x)) + PAM_MUST_NOT_BE_ARRAY(x)) + +static inline void +pam_drop_response(struct pam_response *reply, int replies) +{ + int reply_i; + + for (reply_i = 0; reply_i < replies; ++reply_i) { + if (reply[reply_i].resp) { + pam_overwrite_string(reply[reply_i].resp); + free(reply[reply_i].resp); + } + } + free(reply); +} + + static inline int pam_read_passwords(int fd, int npass, char **passwords) { |