diff options
| author | Furkan Sahin <furkan-dev@proton.me> | 2017-12-16 21:12:36 -0500 |
|---|---|---|
| committer | Furkan Sahin <furkan-dev@proton.me> | 2017-12-16 21:12:36 -0500 |
| commit | f896cb48106e704a57f93790b46fa7e183d646eb (patch) | |
| tree | 4444227f247f9b7cdb854144eb4332e607c34987 | |
| parent | daf6e0aba0b7c1c84ad3f4cf94c866bc222eb135 (diff) | |
| parent | cb53bb3e265b78e07e0eeba70c3a42503277bb51 (diff) | |
Merge pull request #1519 from ggreer/clear-password-buffer-0.15
Swaylock: Clear password buffer after use.
| -rw-r--r-- | swaylock/main.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index 1ed28c2b..4b486461 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -7,6 +7,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/mman.h> #include <sys/types.h> #include <pwd.h> #include <getopt.h> @@ -56,8 +57,7 @@ void sway_terminate(int exit_code) { exit(exit_code); } -char *password; -int password_size; +char password[1024]; enum line_source line_source = LINE_SOURCE_DEFAULT; struct lock_config *init_config() { @@ -115,7 +115,7 @@ int function_conversation(int num_msg, const struct pam_message **msg, switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_OFF: case PAM_PROMPT_ECHO_ON: - pam_reply[i].resp = password; + pam_reply[i].resp = strdup(password); // PAM clears and frees this break; case PAM_ERROR_MSG: @@ -127,9 +127,15 @@ int function_conversation(int num_msg, const struct pam_message **msg, return PAM_SUCCESS; } -/** - * Note: PAM will free() 'password' during the process - */ +void clear_password_buffer() { + // Use volatile keyword so so compiler can't optimize this out. + volatile char *pw = password; + volatile char zero = '\0'; + for (size_t i = 0; i < sizeof(password); ++i) { + pw[i] = zero; + } +} + bool verify_password() { struct passwd *passwd = getpwuid(getuid()); char *username = passwd->pw_name; @@ -151,8 +157,7 @@ bool verify_password() { void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { int redraw_screen = 0; - char *password_realloc; - int i; + size_t i; if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { switch (sym) { @@ -165,14 +170,14 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod wl_dispatch_events(); if (verify_password()) { + clear_password_buffer(); exit(0); } render_data.auth_state = AUTH_STATE_INVALID; redraw_screen = 1; - password_size = 1024; - password = malloc(password_size); + clear_password_buffer(); password[0] = '\0'; break; case XKB_KEY_BackSpace: @@ -207,9 +212,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod render_data.auth_state = AUTH_STATE_BACKSPACE; redraw_screen = 1; - password_size = 1024; - free(password); - password = malloc(password_size); + clear_password_buffer(); password[0] = '\0'; break; } @@ -218,22 +221,10 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod render_data.auth_state = AUTH_STATE_INPUT; redraw_screen = 1; i = strlen(password); - if (i + 1 == password_size) { - password_size += 1024; - password_realloc = realloc(password, password_size); - // reset password if realloc fails. - if (password_realloc == NULL) { - password_size = 1024; - free(password); - password = malloc(password_size); - password[0] = '\0'; - break; - } else { - password = password_realloc; - } + if (i + 1 < sizeof(password)) { + password[i] = (char)codepoint; + password[i + 1] = '\0'; } - password[i] = (char)codepoint; - password[i + 1] = '\0'; break; } if (redraw_screen) { @@ -539,8 +530,12 @@ int main(int argc, char **argv) { sway_abort("Unsupported scaling mode: %s", scaling_mode_str); } - password_size = 1024; - password = malloc(password_size); +#ifdef __linux__ + // Most non-linux platforms require root to mlock() + if (mlock(password, sizeof(password)) != 0) { + sway_abort("Unable to mlock() password memory."); + } +#endif password[0] = '\0'; render_data.surfaces = create_list(); if (!socket_path) { |
