]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: fix crash in logind on user-specified message string
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 8 May 2022 15:21:09 +0000 (17:21 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 11 May 2022 14:43:31 +0000 (16:43 +0200)
This is trivially exploitable (in the sense of causing a crash from SEGV) e.g.
by 'shutdown now "Message %s %s %n"'. The message is settable through polkit,
but is limited to auth_admin:

<action id="org.freedesktop.login1.set-wall-message">
         <description gettext-domain="systemd">Set a wall message</description>
         <message gettext-domain="systemd">Authentication is required to set a wall message</message>
         <defaults>
                <allow_any>auth_admin_keep</allow_any>
                <allow_inactive>auth_admin_keep</allow_inactive>
                <allow_active>auth_admin_keep</allow_active>
        </defaults>
</action>

Bug introduced in 9ef15026c0e7e6600372056c43442c99ec53746e
('logind/systemctl: introduce SetWallMessage and --message', 2015-09-15).

src/login/logind-dbus.c

index 914e56bd7765f486e044715c3ef5af0901cc05da..5c17d4ec04270e28df488af9f5e1ffb47b200c4f 100644 (file)
@@ -1515,32 +1515,20 @@ static int have_multiple_sessions(
 static int bus_manager_log_shutdown(
                 Manager *m,
                 const HandleActionData *a) {
-
-        const char *message, *log_message;
-
         assert(m);
         assert(a);
 
-        message = a->message;
-        log_message = a->log_message;
-
-        if (message)
-                message = strjoina("MESSAGE=", message);
-        else
-                message = "MESSAGE=System is shutting down";
-
-        if (isempty(m->wall_message))
-                message = strjoina(message, ".");
-        else
-                message = strjoina(message, " (", m->wall_message, ").");
-
-        if (log_message)
-                log_message = strjoina("SHUTDOWN=", log_message);
+        const char *message = a->message ?: "System is shutting down";
+        const char *log_message = a->log_message ? strjoina("SHUTDOWN=", a->log_message) : NULL;
 
         return log_struct(LOG_NOTICE,
-                        "MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR,
-                        message,
-                        log_message);
+                          "MESSAGE_ID=%s", a->message_id ?: SD_MESSAGE_SHUTDOWN_STR,
+                          LOG_MESSAGE("%s%s%s%s.",
+                                      message,
+                                      m->wall_message ? " (" : "",
+                                      strempty(m->wall_message),
+                                      m->wall_message ? ")" : ""),
+                          log_message);
 }
 
 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {