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 ];
6161enum line_source line_source = LINE_SOURCE_DEFAULT ;
6262
6363struct 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+
133139bool verify_password () {
134140 struct passwd * passwd = getpwuid (getuid ());
135141 char * username = passwd -> pw_name ;
@@ -151,8 +157,7 @@ bool verify_password() {
151157
152158void 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