From 495ae9173ba05a4c57034766687ddb30dcca91ee Mon Sep 17 00:00:00 2001 From: Simon Johnsson Date: Thu, 8 Jan 2026 10:34:54 +0100 Subject: [PATCH 1/6] libply-splash-core: add password cleartext toggle Introduce functions for allowing passwords to optionally be displayed in cleartext. --- .../ply-boot-splash-plugin.h | 3 ++ src/libply-splash-core/ply-boot-splash.c | 27 ++++++++-- src/libply-splash-core/ply-boot-splash.h | 4 ++ src/libply-splash-core/ply-keyboard.c | 49 +++++++++++++++++++ src/libply-splash-core/ply-keyboard.h | 7 +++ 5 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/libply-splash-core/ply-boot-splash-plugin.h b/src/libply-splash-core/ply-boot-splash-plugin.h index d5cd05a7..815a4bef 100644 --- a/src/libply-splash-core/ply-boot-splash-plugin.h +++ b/src/libply-splash-core/ply-boot-splash-plugin.h @@ -103,6 +103,9 @@ typedef struct bool (*validate_input) (ply_boot_splash_plugin_t *plugin, const char *entry_text, const char *add_text); + void (*display_password_clear_text)(ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text); } ply_boot_splash_plugin_interface_t; #endif /* PLY_BOOT_SPLASH_PLUGIN_H */ diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c index 217f455e..bc1d6c41 100644 --- a/src/libply-splash-core/ply-boot-splash.c +++ b/src/libply-splash-core/ply-boot-splash.c @@ -707,17 +707,38 @@ void ply_boot_splash_display_normal (ply_boot_splash_t *splash) splash->plugin_interface->display_normal (splash->plugin); } -void ply_boot_splash_display_password (ply_boot_splash_t *splash, - const char *prompt, - int bullets) +static inline void +assert_password_capable(ply_boot_splash_t *splash) { assert (splash != NULL); assert (splash->plugin_interface != NULL); assert (splash->plugin != NULL); +} + +void ply_boot_splash_display_password (ply_boot_splash_t *splash, + const char *prompt, + int bullets) +{ + assert_password_capable(splash); if (splash->plugin_interface->display_password != NULL) splash->plugin_interface->display_password (splash->plugin, prompt, bullets); } +bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash) +{ + assert_password_capable(splash); + return splash->plugin_interface->display_password_clear_text != NULL; +} + +void ply_boot_splash_display_password_clear_text (ply_boot_splash_t *splash, + const char *prompt, + const char *entry_text) +{ + if (!ply_boot_splash_can_display_password_clear_text (splash)) + return; + splash->plugin_interface->display_password_clear_text (splash->plugin, prompt, entry_text); +} + void ply_boot_splash_display_question (ply_boot_splash_t *splash, const char *prompt, const char *entry_text) diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h index df57b8c9..50d51361 100644 --- a/src/libply-splash-core/ply-boot-splash.h +++ b/src/libply-splash-core/ply-boot-splash.h @@ -79,6 +79,10 @@ void ply_boot_splash_display_normal (ply_boot_splash_t *splash); void ply_boot_splash_display_password (ply_boot_splash_t *splash, const char *prompt, int bullets); +bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash); +void ply_boot_splash_display_password_clear_text (ply_boot_splash_t *splash, + const char *prompt, + const char *entry_text); void ply_boot_splash_display_question (ply_boot_splash_t *splash, const char *prompt, const char *entry_text); diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c index 59f125fe..929833c4 100644 --- a/src/libply-splash-core/ply-keyboard.c +++ b/src/libply-splash-core/ply-keyboard.c @@ -44,6 +44,7 @@ #define KEY_CTRL_W ('\100' ^ 'W') #define KEY_CTRL_V ('\100' ^ 'V') #define KEY_ESCAPE ('\100' ^ '[') +#define KEY_TAB '\t' #define KEY_RETURN '\n' #define KEY_BACKSPACE '\177' @@ -97,6 +98,7 @@ struct _ply_keyboard ply_list_t *keyboard_input_handler_list; ply_list_t *backspace_handler_list; ply_list_t *escape_handler_list; + ply_list_t *tab_handler_list; ply_list_t *enter_handler_list; uint32_t is_active : 1; @@ -114,6 +116,7 @@ ply_keyboard_new_for_terminal (ply_terminal_t *terminal) keyboard->keyboard_input_handler_list = ply_list_new (); keyboard->backspace_handler_list = ply_list_new (); keyboard->escape_handler_list = ply_list_new (); + keyboard->tab_handler_list = ply_list_new (); keyboard->enter_handler_list = ply_list_new (); keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL; keyboard->provider.if_terminal = calloc (1, sizeof(ply_keyboard_terminal_provider_t)); @@ -136,6 +139,7 @@ ply_keyboard_new_for_renderer (ply_renderer_t *renderer) keyboard->keyboard_input_handler_list = ply_list_new (); keyboard->backspace_handler_list = ply_list_new (); keyboard->escape_handler_list = ply_list_new (); + keyboard->tab_handler_list = ply_list_new (); keyboard->enter_handler_list = ply_list_new (); keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_RENDERER; keyboard->provider.if_renderer = calloc (1, sizeof(ply_keyboard_renderer_provider_t)); @@ -219,6 +223,17 @@ process_keyboard_input (ply_keyboard_t *keyboard, ply_trace ("end escape key handler"); return; + case KEY_TAB: + ply_trace ("tab key!"); + for (node = ply_list_get_first_node (keyboard->tab_handler_list); + node; node = ply_list_get_next_node (keyboard->tab_handler_list, node)) { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + ply_keyboard_tab_handler_t tab_handler = (ply_keyboard_tab_handler_t) closure->function; + tab_handler (closure->user_data); + } + ply_trace ("end tab key handler"); + return; + case KEY_BACKSPACE: ply_trace ("backspace key!"); process_backspace (keyboard); @@ -638,6 +653,40 @@ ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, } } +void +ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler, + void *user_data) +{ + ply_keyboard_closure_t *closure; + + assert (keyboard != NULL); + + closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) tab_handler, + user_data); + ply_list_append_data (keyboard->tab_handler_list, closure); +} + + +void +ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler) +{ + ply_list_node_t *node; + + assert (keyboard != NULL); + + for (node = ply_list_get_first_node (keyboard->tab_handler_list); + node; node = ply_list_get_next_node (keyboard->tab_handler_list, node)) { + ply_keyboard_closure_t *closure = ply_list_node_get_data (node); + if ((ply_keyboard_tab_handler_t) closure->function == tab_handler) { + ply_keyboard_closure_free (closure); + ply_list_remove_node (keyboard->tab_handler_list, node); + return; + } + } +} + void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, ply_keyboard_enter_handler_t enter_handler, diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h index 101defdb..de4aaa57 100644 --- a/src/libply-splash-core/ply-keyboard.h +++ b/src/libply-splash-core/ply-keyboard.h @@ -40,6 +40,8 @@ typedef void (*ply_keyboard_backspace_handler_t) (void *user_data); typedef void (*ply_keyboard_escape_handler_t) (void *user_data); +typedef void (*ply_keyboard_tab_handler_t) (void *user_data); + typedef void (*ply_keyboard_enter_handler_t) (void *user_data, const char *line); @@ -63,6 +65,11 @@ void ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard, void *user_data); void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, ply_keyboard_escape_handler_t escape_handler); +void ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler, + void *user_data); +void ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler); void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, ply_keyboard_enter_handler_t enter_handler, void *user_data); From 9d1938060dc000ed542f91bbd1a482155573958b Mon Sep 17 00:00:00 2001 From: Simon Johnsson Date: Thu, 8 Jan 2026 10:42:04 +0100 Subject: [PATCH 2/6] plymouthd: add theme optional cleartext password This commit will introduce a TAB handler that allows themes to optionally implement a way of displaying cleartext passwords. Themes not implementing this behavior should not be affected. --- src/main.c | 145 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 120 insertions(+), 25 deletions(-) diff --git a/src/main.c b/src/main.c index 320fa965..2cf082e1 100644 --- a/src/main.c +++ b/src/main.c @@ -116,6 +116,7 @@ typedef struct uint32_t should_force_details : 1; uint32_t should_force_default_splash : 1; uint32_t splash_is_becoming_idle : 1; + uint32_t should_show_password_clear_text : 1; char *override_splash_path; char *system_default_splash_path; @@ -154,6 +155,7 @@ static void tell_systemd_to_stop_printing_details (state_t *state); #endif static const char *get_cache_file_for_mode (ply_boot_splash_mode_t mode); static void on_escape_pressed (state_t *state); +static void on_tab_pressed (state_t *state); static void on_enter (state_t *state, const char *line); static void on_keyboard_input (state_t *state, @@ -1106,6 +1108,10 @@ on_keyboard_added (state_t *state, ply_keyboard_add_escape_handler (keyboard, (ply_keyboard_escape_handler_t) on_escape_pressed, state); + ply_trace ("listening for tab"); + ply_keyboard_add_tab_handler (keyboard, + (ply_keyboard_tab_handler_t) + on_tab_pressed, state); ply_trace ("listening for backspace"); ply_keyboard_add_backspace_handler (keyboard, (ply_keyboard_backspace_handler_t) @@ -1133,6 +1139,10 @@ on_keyboard_removed (state_t *state, ply_keyboard_remove_escape_handler (keyboard, (ply_keyboard_escape_handler_t) on_escape_pressed); + ply_trace ("no longer listening for tab"); + ply_keyboard_remove_tab_handler (keyboard, + (ply_keyboard_tab_handler_t) + on_tab_pressed); ply_trace ("no longer listening for backspace"); ply_keyboard_remove_backspace_handler (keyboard, (ply_keyboard_backspace_handler_t) @@ -1577,6 +1587,69 @@ validate_input (state_t *state, return input_valid; } +static void +handle_ply_entry_trigger_type_password(state_t *state, + ply_entry_trigger_t *entry_trigger) +{ + bool show_password_clear_text = + state->should_show_password_clear_text && + ply_boot_splash_can_display_password_clear_text (state->boot_splash); + if (show_password_clear_text) + { + /* WARNING: entry_text contains cleartext password. + * Must not be stored beyond immediate rendering. + */ + const char *raw_bytes = (const char*)ply_buffer_get_bytes (state->entry_buffer); + size_t raw_size = ply_buffer_get_size (state->entry_buffer); + + if (!raw_bytes) { + ply_error ("Failed to get bytes from entry buffer"); + return; + } + + char *password_copy = calloc(1, raw_size + 1); + + if (!password_copy) { + ply_error ("Failed to allocate memory for password copy: %m"); + return; + } + + /* Safely copy raw bytes to password_copy and ensure null-termination */ + memcpy(password_copy, raw_bytes, raw_size); + password_copy[raw_size] = '\0'; + + ply_trace ("WARNING: cleartext password display enabled"); + ply_boot_splash_display_password_clear_text (state->boot_splash, + entry_trigger->prompt, + password_copy); + /* Securely erase password copy from memory */ + #ifdef HAVE_EXPLICIT_BZERO + explicit_bzero(password_copy, raw_size); + #else + volatile char *p = (volatile char *)password_copy; + size_t i = 0; + while (i < raw_size) { + p[i] = 0; + i++; + } + #endif + + free(password_copy); + } + else { + int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), + ply_buffer_get_size (state->entry_buffer)); + bullets = MAX (0, bullets); + ply_boot_splash_display_password (state->boot_splash, + entry_trigger->prompt, + bullets); + } + ply_boot_splash_display_prompt (state->boot_splash, + entry_trigger->prompt, + ply_buffer_get_bytes (state->entry_buffer), + true); +} + static void update_display (state_t *state) @@ -1585,32 +1658,24 @@ update_display (state_t *state) ply_list_node_t *node; node = ply_list_get_first_node (state->entry_triggers); - if (node) { - ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node); - if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) { - int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), - ply_buffer_get_size (state->entry_buffer)); - bullets = MAX (0, bullets); - ply_boot_splash_display_password (state->boot_splash, - entry_trigger->prompt, - bullets); - ply_boot_splash_display_prompt (state->boot_splash, - entry_trigger->prompt, - ply_buffer_get_bytes (state->entry_buffer), - true); - } else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) { - ply_boot_splash_display_question (state->boot_splash, - entry_trigger->prompt, - ply_buffer_get_bytes (state->entry_buffer)); - ply_boot_splash_display_prompt (state->boot_splash, - entry_trigger->prompt, - ply_buffer_get_bytes (state->entry_buffer), - false); - } else { - ply_trace ("unkown entry type"); - } - } else { + if (!node) { ply_boot_splash_display_normal (state->boot_splash); + return; + } + + ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node); + if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) + handle_ply_entry_trigger_type_password(state, entry_trigger); + else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) { + ply_boot_splash_display_question (state->boot_splash, + entry_trigger->prompt, + ply_buffer_get_bytes (state->entry_buffer)); + ply_boot_splash_display_prompt (state->boot_splash, + entry_trigger->prompt, + ply_buffer_get_bytes (state->entry_buffer), + false); + } else { + ply_trace ("unknown entry type"); } } @@ -1651,6 +1716,36 @@ on_escape_pressed (state_t *state) toggle_between_splash_and_details (state); } +static void +toggle_between_bullets_and_clear_text (state_t *state) +{ + ply_trace ("toggling between bullets and clear text"); + + if (!state->should_show_password_clear_text) { + state->should_show_password_clear_text = true; + } else { + state->should_show_password_clear_text = false; + } + update_display (state); +} + +static void +on_tab_pressed (state_t *state) +{ + ply_trace ("tab key pressed"); + bool has_vt_consoles = true; + + if (state->local_console_terminal != NULL) { + if (!ply_terminal_is_vt (state->local_console_terminal)) + has_vt_consoles = false; + } else { + has_vt_consoles = false; + } + + if (validate_input (state, "", "\t") && has_vt_consoles == true) + toggle_between_bullets_and_clear_text(state); +} + static void on_keyboard_input (state_t *state, const char *keyboard_input, From a14e3e4cb3c98ce63a4670eff2c1686fff109a93 Mon Sep 17 00:00:00 2001 From: Simon Johnsson Date: Thu, 8 Jan 2026 10:47:11 +0100 Subject: [PATCH 3/6] two-step: implement password cleartext option Introduce the option "AllowPasswordClearTextToggle" in the two-step module configuration such that TAB can toggle viewing the password in cleartext. --- src/plugins/splash/two-step/plugin.c | 73 ++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index c810564e..638f4776 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -195,6 +195,7 @@ struct _ply_boot_splash_plugin uint32_t background_image_is_scaled : 1; uint32_t dialog_clears_firmware_background : 1; uint32_t message_below_animation : 1; + uint32_t allow_password_clear_text_toggle : 1; char *monospace_font; uint32_t plugin_console_messages_updating : 1; @@ -699,6 +700,8 @@ view_load (view_t *view) ply_trace ("loading entry"); if (!ply_entry_load (view->entry)) return false; + else + ply_entry_set_text_color(view->entry, 1.0, 1.0, 1.0, 1.0); ply_keymap_icon_load (view->keymap_icon); ply_capslock_icon_load (view->capslock_icon); @@ -1360,6 +1363,9 @@ create_plugin (ply_key_file_t *key_file) plugin->message_below_animation = ply_key_file_get_bool (key_file, "two-step", "MessageBelowAnimation"); + plugin->allow_password_clear_text_toggle = + ply_key_file_get_bool(key_file, "two-step", "AllowPasswordClearTextToggle"); + progress_function = ply_key_file_get_value (key_file, "two-step", "ProgressFunction"); if (progress_function != NULL) { @@ -2222,16 +2228,17 @@ display_normal (ply_boot_splash_plugin_t *plugin) } static void -display_password (ply_boot_splash_plugin_t *plugin, - const char *prompt, - int bullets) +display_password_internal(ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text, + int bullets) { pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) stop_animation (plugin); plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; - show_prompt (plugin, prompt, NULL, bullets); + show_prompt (plugin, prompt, entry_text, bullets); redraw_views (plugin); if (plugin->should_show_console_messages) @@ -2241,6 +2248,29 @@ display_password (ply_boot_splash_plugin_t *plugin, unpause_views (plugin); } +static void +display_password (ply_boot_splash_plugin_t *plugin, + const char *prompt, + int bullets) +{ + display_password_internal(plugin, prompt, NULL, bullets); +} + +static void +display_password_clear_text (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + if (!plugin->allow_password_clear_text_toggle) + { + // if function is disabled, fall back to masked bullet mode, + // as dynamically setting function to NULL is not possible + display_password_internal(plugin, prompt, NULL, 0); + return; + } + display_password_internal(plugin, prompt, entry_text, -1); +} + static void display_question (ply_boot_splash_plugin_t *plugin, const char *prompt, @@ -2379,23 +2409,24 @@ ply_boot_splash_plugin_get_interface (void) { static ply_boot_splash_plugin_interface_t plugin_interface = { - .create_plugin = create_plugin, - .destroy_plugin = destroy_plugin, - .add_pixel_display = add_pixel_display, - .remove_pixel_display = remove_pixel_display, - .show_splash_screen = show_splash_screen, - .update_status = update_status, - .on_boot_progress = on_boot_progress, - .hide_splash_screen = hide_splash_screen, - .on_root_mounted = on_root_mounted, - .become_idle = become_idle, - .display_normal = display_normal, - .display_password = display_password, - .display_question = display_question, - .display_message = display_message, - .system_update = system_update, - .on_boot_output = on_boot_output, - .validate_input = validate_input, + .create_plugin = create_plugin, + .destroy_plugin = destroy_plugin, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, + .show_splash_screen = show_splash_screen, + .update_status = update_status, + .on_boot_progress = on_boot_progress, + .hide_splash_screen = hide_splash_screen, + .on_root_mounted = on_root_mounted, + .become_idle = become_idle, + .display_normal = display_normal, + .display_password = display_password, + .display_password_clear_text = display_password_clear_text, + .display_question = display_question, + .display_message = display_message, + .system_update = system_update, + .on_boot_output = on_boot_output, + .validate_input = validate_input, }; return &plugin_interface; From 89c1c174707cbd781dd3d86b91ce0755dadfb4c6 Mon Sep 17 00:00:00 2001 From: Simon Johnsson Date: Thu, 8 Jan 2026 11:50:15 +0100 Subject: [PATCH 4/6] fix: apply formatting --- src/libply-splash-core/ply-boot-splash.c | 7 ++-- src/libply-splash-core/ply-keyboard.c | 10 +++--- src/libply-splash-core/ply-keyboard.h | 7 ++-- src/main.c | 44 +++++++++++------------- src/plugins/splash/two-step/plugin.c | 22 ++++++------ 5 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c index bc1d6c41..900bf9f7 100644 --- a/src/libply-splash-core/ply-boot-splash.c +++ b/src/libply-splash-core/ply-boot-splash.c @@ -708,7 +708,7 @@ void ply_boot_splash_display_normal (ply_boot_splash_t *splash) } static inline void -assert_password_capable(ply_boot_splash_t *splash) +assert_password_capable (ply_boot_splash_t *splash) { assert (splash != NULL); assert (splash->plugin_interface != NULL); @@ -719,14 +719,14 @@ void ply_boot_splash_display_password (ply_boot_splash_t *splash, const char *prompt, int bullets) { - assert_password_capable(splash); + assert_password_capable (splash); if (splash->plugin_interface->display_password != NULL) splash->plugin_interface->display_password (splash->plugin, prompt, bullets); } bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash) { - assert_password_capable(splash); + assert_password_capable (splash); return splash->plugin_interface->display_password_clear_text != NULL; } @@ -845,4 +845,3 @@ ply_boot_splash_uses_pixel_displays (ply_boot_splash_t *splash) { return splash->plugin_interface->add_pixel_display != NULL; } - diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c index 929833c4..525ad062 100644 --- a/src/libply-splash-core/ply-keyboard.c +++ b/src/libply-splash-core/ply-keyboard.c @@ -654,9 +654,9 @@ ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, } void -ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, - ply_keyboard_tab_handler_t tab_handler, - void *user_data) +ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler, + void *user_data) { ply_keyboard_closure_t *closure; @@ -669,8 +669,8 @@ ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, void -ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, - ply_keyboard_tab_handler_t tab_handler) +ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, + ply_keyboard_tab_handler_t tab_handler) { ply_list_node_t *node; diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h index de4aaa57..8bd1d46b 100644 --- a/src/libply-splash-core/ply-keyboard.h +++ b/src/libply-splash-core/ply-keyboard.h @@ -65,10 +65,10 @@ void ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard, void *user_data); void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, ply_keyboard_escape_handler_t escape_handler); -void ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, +void ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard, ply_keyboard_tab_handler_t tab_handler, - void *user_data); -void ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, + void *user_data); +void ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard, ply_keyboard_tab_handler_t tab_handler); void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, ply_keyboard_enter_handler_t enter_handler, @@ -85,4 +85,3 @@ bool ply_keyboard_get_capslock_state (ply_keyboard_t *keyboard); #endif #endif /* PLY_KEYBOARD_H */ - diff --git a/src/main.c b/src/main.c index 2cf082e1..c7778a9f 100644 --- a/src/main.c +++ b/src/main.c @@ -1110,8 +1110,8 @@ on_keyboard_added (state_t *state, on_escape_pressed, state); ply_trace ("listening for tab"); ply_keyboard_add_tab_handler (keyboard, - (ply_keyboard_tab_handler_t) - on_tab_pressed, state); + (ply_keyboard_tab_handler_t) + on_tab_pressed, state); ply_trace ("listening for backspace"); ply_keyboard_add_backspace_handler (keyboard, (ply_keyboard_backspace_handler_t) @@ -1588,18 +1588,17 @@ validate_input (state_t *state, } static void -handle_ply_entry_trigger_type_password(state_t *state, - ply_entry_trigger_t *entry_trigger) +handle_ply_entry_trigger_type_password (state_t *state, + ply_entry_trigger_t *entry_trigger) { bool show_password_clear_text = state->should_show_password_clear_text && ply_boot_splash_can_display_password_clear_text (state->boot_splash); - if (show_password_clear_text) - { + if (show_password_clear_text) { /* WARNING: entry_text contains cleartext password. - * Must not be stored beyond immediate rendering. - */ - const char *raw_bytes = (const char*)ply_buffer_get_bytes (state->entry_buffer); + * Must not be stored beyond immediate rendering. + */ + const char *raw_bytes = (const char *) ply_buffer_get_bytes (state->entry_buffer); size_t raw_size = ply_buffer_get_size (state->entry_buffer); if (!raw_bytes) { @@ -1607,7 +1606,7 @@ handle_ply_entry_trigger_type_password(state_t *state, return; } - char *password_copy = calloc(1, raw_size + 1); + char *password_copy = calloc (1, raw_size + 1); if (!password_copy) { ply_error ("Failed to allocate memory for password copy: %m"); @@ -1615,7 +1614,7 @@ handle_ply_entry_trigger_type_password(state_t *state, } /* Safely copy raw bytes to password_copy and ensure null-termination */ - memcpy(password_copy, raw_bytes, raw_size); + memcpy (password_copy, raw_bytes, raw_size); password_copy[raw_size] = '\0'; ply_trace ("WARNING: cleartext password display enabled"); @@ -1623,20 +1622,19 @@ handle_ply_entry_trigger_type_password(state_t *state, entry_trigger->prompt, password_copy); /* Securely erase password copy from memory */ - #ifdef HAVE_EXPLICIT_BZERO - explicit_bzero(password_copy, raw_size); - #else - volatile char *p = (volatile char *)password_copy; +#ifdef HAVE_EXPLICIT_BZERO + explicit_bzero (password_copy, raw_size); +#else + volatile char *p = (volatile char *) password_copy; size_t i = 0; while (i < raw_size) { p[i] = 0; i++; } - #endif +#endif - free(password_copy); - } - else { + free (password_copy); + } else { int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), ply_buffer_get_size (state->entry_buffer)); bullets = MAX (0, bullets); @@ -1664,9 +1662,9 @@ update_display (state_t *state) } ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node); - if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) - handle_ply_entry_trigger_type_password(state, entry_trigger); - else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) { + if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) { + handle_ply_entry_trigger_type_password (state, entry_trigger); + } else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) { ply_boot_splash_display_question (state->boot_splash, entry_trigger->prompt, ply_buffer_get_bytes (state->entry_buffer)); @@ -1743,7 +1741,7 @@ on_tab_pressed (state_t *state) } if (validate_input (state, "", "\t") && has_vt_consoles == true) - toggle_between_bullets_and_clear_text(state); + toggle_between_bullets_and_clear_text (state); } static void diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 638f4776..cb62a0f1 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -701,7 +701,7 @@ view_load (view_t *view) if (!ply_entry_load (view->entry)) return false; else - ply_entry_set_text_color(view->entry, 1.0, 1.0, 1.0, 1.0); + ply_entry_set_text_color (view->entry, 1.0, 1.0, 1.0, 1.0); ply_keymap_icon_load (view->keymap_icon); ply_capslock_icon_load (view->capslock_icon); @@ -1364,7 +1364,7 @@ create_plugin (ply_key_file_t *key_file) ply_key_file_get_bool (key_file, "two-step", "MessageBelowAnimation"); plugin->allow_password_clear_text_toggle = - ply_key_file_get_bool(key_file, "two-step", "AllowPasswordClearTextToggle"); + ply_key_file_get_bool (key_file, "two-step", "AllowPasswordClearTextToggle"); progress_function = ply_key_file_get_value (key_file, "two-step", "ProgressFunction"); @@ -2228,10 +2228,10 @@ display_normal (ply_boot_splash_plugin_t *plugin) } static void -display_password_internal(ply_boot_splash_plugin_t *plugin, - const char *prompt, - const char *entry_text, - int bullets) +display_password_internal (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text, + int bullets) { pause_views (plugin); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) @@ -2253,7 +2253,7 @@ display_password (ply_boot_splash_plugin_t *plugin, const char *prompt, int bullets) { - display_password_internal(plugin, prompt, NULL, bullets); + display_password_internal (plugin, prompt, NULL, bullets); } static void @@ -2261,14 +2261,13 @@ display_password_clear_text (ply_boot_splash_plugin_t *plugin, const char *prompt, const char *entry_text) { - if (!plugin->allow_password_clear_text_toggle) - { + if (!plugin->allow_password_clear_text_toggle) { // if function is disabled, fall back to masked bullet mode, // as dynamically setting function to NULL is not possible - display_password_internal(plugin, prompt, NULL, 0); + display_password_internal (plugin, prompt, NULL, 0); return; } - display_password_internal(plugin, prompt, entry_text, -1); + display_password_internal (plugin, prompt, entry_text, -1); } static void @@ -2431,4 +2430,3 @@ ply_boot_splash_plugin_get_interface (void) return &plugin_interface; } - From f9b428d29a90ed429741ff500480b79dc363d768 Mon Sep 17 00:00:00 2001 From: Simon Johnsson Date: Thu, 8 Jan 2026 15:44:49 +0100 Subject: [PATCH 5/6] fix: address merge comments * Re-add accidental EOF newline deletions * Remove unnecessary entry text null-termination assertion * Remove unnecessary has_vt_consoles check * Make display_password_clear_text use regular bulleted behavior when allow_password_clear_text_toggle is false --- src/libply-splash-core/ply-boot-splash.c | 1 + src/libply-splash-core/ply-keyboard.h | 1 + src/main.c | 12 +----------- src/plugins/splash/two-step/plugin.c | 6 +++++- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c index 900bf9f7..ab3d322d 100644 --- a/src/libply-splash-core/ply-boot-splash.c +++ b/src/libply-splash-core/ply-boot-splash.c @@ -845,3 +845,4 @@ ply_boot_splash_uses_pixel_displays (ply_boot_splash_t *splash) { return splash->plugin_interface->add_pixel_display != NULL; } + diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h index 8bd1d46b..cb88ae8a 100644 --- a/src/libply-splash-core/ply-keyboard.h +++ b/src/libply-splash-core/ply-keyboard.h @@ -85,3 +85,4 @@ bool ply_keyboard_get_capslock_state (ply_keyboard_t *keyboard); #endif #endif /* PLY_KEYBOARD_H */ + diff --git a/src/main.c b/src/main.c index c7778a9f..ddbd7df9 100644 --- a/src/main.c +++ b/src/main.c @@ -1613,9 +1613,7 @@ handle_ply_entry_trigger_type_password (state_t *state, return; } - /* Safely copy raw bytes to password_copy and ensure null-termination */ memcpy (password_copy, raw_bytes, raw_size); - password_copy[raw_size] = '\0'; ply_trace ("WARNING: cleartext password display enabled"); ply_boot_splash_display_password_clear_text (state->boot_splash, @@ -1731,16 +1729,8 @@ static void on_tab_pressed (state_t *state) { ply_trace ("tab key pressed"); - bool has_vt_consoles = true; - if (state->local_console_terminal != NULL) { - if (!ply_terminal_is_vt (state->local_console_terminal)) - has_vt_consoles = false; - } else { - has_vt_consoles = false; - } - - if (validate_input (state, "", "\t") && has_vt_consoles == true) + if (validate_input (state, "", "\t")) toggle_between_bullets_and_clear_text (state); } diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index cb62a0f1..1ae088ed 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -2264,7 +2264,10 @@ display_password_clear_text (ply_boot_splash_plugin_t *plugin, if (!plugin->allow_password_clear_text_toggle) { // if function is disabled, fall back to masked bullet mode, // as dynamically setting function to NULL is not possible - display_password_internal (plugin, prompt, NULL, 0); + int bullets = ply_utf8_string_get_length (entry_text, + strlen (entry_text)); + bullets = MAX (0, bullets); + display_password_internal (plugin, prompt, NULL, bullets); return; } display_password_internal (plugin, prompt, entry_text, -1); @@ -2430,3 +2433,4 @@ ply_boot_splash_plugin_get_interface (void) return &plugin_interface; } + From 9fdbe795e47e17f2315a62c3b09a0295ed55a80e Mon Sep 17 00:00:00 2001 From: Simon Johnsson Date: Thu, 8 Jan 2026 16:56:03 +0100 Subject: [PATCH 6/6] plymouthd: remove entry text duplicate Per Merge Request #373 comment, this duplicate might not have an essential function as if a threat actor can access it, they can likely already access the entry text. --- src/main.c | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/src/main.c b/src/main.c index ddbd7df9..99e70adc 100644 --- a/src/main.c +++ b/src/main.c @@ -1595,43 +1595,11 @@ handle_ply_entry_trigger_type_password (state_t *state, state->should_show_password_clear_text && ply_boot_splash_can_display_password_clear_text (state->boot_splash); if (show_password_clear_text) { - /* WARNING: entry_text contains cleartext password. - * Must not be stored beyond immediate rendering. - */ - const char *raw_bytes = (const char *) ply_buffer_get_bytes (state->entry_buffer); - size_t raw_size = ply_buffer_get_size (state->entry_buffer); - - if (!raw_bytes) { - ply_error ("Failed to get bytes from entry buffer"); - return; - } - - char *password_copy = calloc (1, raw_size + 1); - - if (!password_copy) { - ply_error ("Failed to allocate memory for password copy: %m"); - return; - } - - memcpy (password_copy, raw_bytes, raw_size); - + const char *entry_text = (const char *) ply_buffer_get_bytes (state->entry_buffer); ply_trace ("WARNING: cleartext password display enabled"); ply_boot_splash_display_password_clear_text (state->boot_splash, entry_trigger->prompt, - password_copy); - /* Securely erase password copy from memory */ -#ifdef HAVE_EXPLICIT_BZERO - explicit_bzero (password_copy, raw_size); -#else - volatile char *p = (volatile char *) password_copy; - size_t i = 0; - while (i < raw_size) { - p[i] = 0; - i++; - } -#endif - - free (password_copy); + entry_text); } else { int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), ply_buffer_get_size (state->entry_buffer));