summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-12-16 21:12:36 -0500
committerLibravatar GitHub <noreply@github.com>2017-12-16 21:12:36 -0500
commit1263ea6497c732bfa1835eea4a8ffe2e6ea6e377 (patch)
tree4444227f247f9b7cdb854144eb4332e607c34987
parentMerge pull request #1515 from 4e554c4c/holds_up_fork (diff)
parentSwaylock: Clear password buffer after use. (diff)
downloadsway-1263ea6497c732bfa1835eea4a8ffe2e6ea6e377.tar.gz
sway-1263ea6497c732bfa1835eea4a8ffe2e6ea6e377.tar.zst
sway-1263ea6497c732bfa1835eea4a8ffe2e6ea6e377.zip
Merge pull request #1519 from ggreer/clear-password-buffer-0.15
Swaylock: Clear password buffer after use.
-rw-r--r--swaylock/main.c55
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 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <stdlib.h> 8#include <stdlib.h>
9#include <string.h> 9#include <string.h>
10#include <sys/mman.h>
10#include <sys/types.h> 11#include <sys/types.h>
11#include <pwd.h> 12#include <pwd.h>
12#include <getopt.h> 13#include <getopt.h>
@@ -56,8 +57,7 @@ void sway_terminate(int exit_code) {
56 exit(exit_code); 57 exit(exit_code);
57} 58}
58 59
59char *password; 60char password[1024];
60int password_size;
61enum line_source line_source = LINE_SOURCE_DEFAULT; 61enum line_source line_source = LINE_SOURCE_DEFAULT;
62 62
63struct lock_config *init_config() { 63struct lock_config *init_config() {
@@ -115,7 +115,7 @@ int function_conversation(int num_msg, const struct pam_message **msg,
115 switch (msg[i]->msg_style) { 115 switch (msg[i]->msg_style) {
116 case PAM_PROMPT_ECHO_OFF: 116 case PAM_PROMPT_ECHO_OFF:
117 case PAM_PROMPT_ECHO_ON: 117 case PAM_PROMPT_ECHO_ON:
118 pam_reply[i].resp = password; 118 pam_reply[i].resp = strdup(password); // PAM clears and frees this
119 break; 119 break;
120 120
121 case PAM_ERROR_MSG: 121 case PAM_ERROR_MSG:
@@ -127,9 +127,15 @@ int function_conversation(int num_msg, const struct pam_message **msg,
127 return PAM_SUCCESS; 127 return PAM_SUCCESS;
128} 128}
129 129
130/** 130void clear_password_buffer() {
131 * Note: PAM will free() 'password' during the process 131 // Use volatile keyword so so compiler can't optimize this out.
132 */ 132 volatile char *pw = password;
133 volatile char zero = '\0';
134 for (size_t i = 0; i < sizeof(password); ++i) {
135 pw[i] = zero;
136 }
137}
138
133bool verify_password() { 139bool verify_password() {
134 struct passwd *passwd = getpwuid(getuid()); 140 struct passwd *passwd = getpwuid(getuid());
135 char *username = passwd->pw_name; 141 char *username = passwd->pw_name;
@@ -151,8 +157,7 @@ bool verify_password() {
151 157
152void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { 158void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) {
153 int redraw_screen = 0; 159 int redraw_screen = 0;
154 char *password_realloc; 160 size_t i;
155 int i;
156 161
157 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { 162 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
158 switch (sym) { 163 switch (sym) {
@@ -165,14 +170,14 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
165 wl_dispatch_events(); 170 wl_dispatch_events();
166 171
167 if (verify_password()) { 172 if (verify_password()) {
173 clear_password_buffer();
168 exit(0); 174 exit(0);
169 } 175 }
170 176
171 render_data.auth_state = AUTH_STATE_INVALID; 177 render_data.auth_state = AUTH_STATE_INVALID;
172 redraw_screen = 1; 178 redraw_screen = 1;
173 179
174 password_size = 1024; 180 clear_password_buffer();
175 password = malloc(password_size);
176 password[0] = '\0'; 181 password[0] = '\0';
177 break; 182 break;
178 case XKB_KEY_BackSpace: 183 case XKB_KEY_BackSpace:
@@ -207,9 +212,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
207 render_data.auth_state = AUTH_STATE_BACKSPACE; 212 render_data.auth_state = AUTH_STATE_BACKSPACE;
208 redraw_screen = 1; 213 redraw_screen = 1;
209 214
210 password_size = 1024; 215 clear_password_buffer();
211 free(password);
212 password = malloc(password_size);
213 password[0] = '\0'; 216 password[0] = '\0';
214 break; 217 break;
215 } 218 }
@@ -218,22 +221,10 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
218 render_data.auth_state = AUTH_STATE_INPUT; 221 render_data.auth_state = AUTH_STATE_INPUT;
219 redraw_screen = 1; 222 redraw_screen = 1;
220 i = strlen(password); 223 i = strlen(password);
221 if (i + 1 == password_size) { 224 if (i + 1 < sizeof(password)) {
222 password_size += 1024; 225 password[i] = (char)codepoint;
223 password_realloc = realloc(password, password_size); 226 password[i + 1] = '\0';
224 // reset password if realloc fails.
225 if (password_realloc == NULL) {
226 password_size = 1024;
227 free(password);
228 password = malloc(password_size);
229 password[0] = '\0';
230 break;
231 } else {
232 password = password_realloc;
233 }
234 } 227 }
235 password[i] = (char)codepoint;
236 password[i + 1] = '\0';
237 break; 228 break;
238 } 229 }
239 if (redraw_screen) { 230 if (redraw_screen) {
@@ -539,8 +530,12 @@ int main(int argc, char **argv) {
539 sway_abort("Unsupported scaling mode: %s", scaling_mode_str); 530 sway_abort("Unsupported scaling mode: %s", scaling_mode_str);
540 } 531 }
541 532
542 password_size = 1024; 533#ifdef __linux__
543 password = malloc(password_size); 534 // Most non-linux platforms require root to mlock()
535 if (mlock(password, sizeof(password)) != 0) {
536 sway_abort("Unable to mlock() password memory.");
537 }
538#endif
544 password[0] = '\0'; 539 password[0] = '\0';
545 render_data.surfaces = create_list(); 540 render_data.surfaces = create_list();
546 if (!socket_path) { 541 if (!socket_path) {