Skip to content

Commit 1263ea6

Browse files
authored
Merge pull request #1519 from ggreer/clear-password-buffer-0.15
Swaylock: Clear password buffer after use.
2 parents af25e8c + 1312db8 commit 1263ea6

1 file changed

Lines changed: 25 additions & 30 deletions

File tree

swaylock/main.c

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <stdio.h>
88
#include <stdlib.h>
99
#include <string.h>
10+
#include <sys/mman.h>
1011
#include <sys/types.h>
1112
#include <pwd.h>
1213
#include <getopt.h>
@@ -56,8 +57,7 @@ void sway_terminate(int exit_code) {
5657
exit(exit_code);
5758
}
5859

59-
char *password;
60-
int password_size;
60+
char password[1024];
6161
enum line_source line_source = LINE_SOURCE_DEFAULT;
6262

6363
struct lock_config *init_config() {
@@ -115,7 +115,7 @@ int function_conversation(int num_msg, const struct pam_message **msg,
115115
switch (msg[i]->msg_style) {
116116
case PAM_PROMPT_ECHO_OFF:
117117
case PAM_PROMPT_ECHO_ON:
118-
pam_reply[i].resp = password;
118+
pam_reply[i].resp = strdup(password); // PAM clears and frees this
119119
break;
120120

121121
case PAM_ERROR_MSG:
@@ -127,9 +127,15 @@ int function_conversation(int num_msg, const struct pam_message **msg,
127127
return PAM_SUCCESS;
128128
}
129129

130-
/**
131-
* Note: PAM will free() 'password' during the process
132-
*/
130+
void clear_password_buffer() {
131+
// Use volatile keyword so so compiler can't optimize this out.
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+
133139
bool verify_password() {
134140
struct passwd *passwd = getpwuid(getuid());
135141
char *username = passwd->pw_name;
@@ -151,8 +157,7 @@ bool verify_password() {
151157

152158
void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) {
153159
int redraw_screen = 0;
154-
char *password_realloc;
155-
int i;
160+
size_t i;
156161

157162
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
158163
switch (sym) {
@@ -165,14 +170,14 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
165170
wl_dispatch_events();
166171

167172
if (verify_password()) {
173+
clear_password_buffer();
168174
exit(0);
169175
}
170176

171177
render_data.auth_state = AUTH_STATE_INVALID;
172178
redraw_screen = 1;
173179

174-
password_size = 1024;
175-
password = malloc(password_size);
180+
clear_password_buffer();
176181
password[0] = '\0';
177182
break;
178183
case XKB_KEY_BackSpace:
@@ -207,9 +212,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
207212
render_data.auth_state = AUTH_STATE_BACKSPACE;
208213
redraw_screen = 1;
209214

210-
password_size = 1024;
211-
free(password);
212-
password = malloc(password_size);
215+
clear_password_buffer();
213216
password[0] = '\0';
214217
break;
215218
}
@@ -218,22 +221,10 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
218221
render_data.auth_state = AUTH_STATE_INPUT;
219222
redraw_screen = 1;
220223
i = strlen(password);
221-
if (i + 1 == password_size) {
222-
password_size += 1024;
223-
password_realloc = realloc(password, password_size);
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-
}
224+
if (i + 1 < sizeof(password)) {
225+
password[i] = (char)codepoint;
226+
password[i + 1] = '\0';
234227
}
235-
password[i] = (char)codepoint;
236-
password[i + 1] = '\0';
237228
break;
238229
}
239230
if (redraw_screen) {
@@ -539,8 +530,12 @@ int main(int argc, char **argv) {
539530
sway_abort("Unsupported scaling mode: %s", scaling_mode_str);
540531
}
541532

542-
password_size = 1024;
543-
password = malloc(password_size);
533+
#ifdef __linux__
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
544539
password[0] = '\0';
545540
render_data.surfaces = create_list();
546541
if (!socket_path) {

0 commit comments

Comments
 (0)