CVE-2020-1712: Use After Free (CWE-416)
value: A heap use-after-free vulnerability was found in systemd before version v245-rc1, where asynchronous Polkit queries are performed while handling dbus messages. A local unprivileged attacker can abuse this flaw to crash systemd services or potentially execute code and elevate their privileges, by sending specially crafted dbus messages.
CWE description: The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
CVSS v3 base score: 7.8
Published: 2020-03-31T17:15Z
Repository: https://github.com/systemd/systemd
Language: C
Files changed: TODO, man/sd_bus_enqueue_for_read.xml, src/libsystemd/libsystemd.sym, src/libsystemd/sd-bus/sd-bus.c, src/shared/bus-polkit.c, src/systemd/sd-bus.h
Commit date: 2020-02-04 18:54:12 +0100
Commit message: Fix typo in function name

Diff: diff --git a/TODO b/TODO
index 4a6c8d3512d..d26b1be4089 100644
--- a/TODO
+++ b/TODO
@@ -326,11 +326,11 @@ Features:
   output of "systemctl list-units" slightly by showing the tree structure of
   the slices, and the units attached to them.
 
 * the a-posteriori stopping of units bound to units that disappeared logic
   should be reworked: there should be a queue of units, and we should only
-  enqeue stop jobs from a defer event that processes queue instead of
+  enqueue stop jobs from a defer event that processes queue instead of
   right-away when we find a unit that is bound to one that doesn't exist
   anymore. (similar to how the stop-unneeded queue has been reworked the same
   way)
 
 * nspawn: make nspawn suitable for shell pipelines: instead of triggering a
diff --git a/man/sd_bus_enqueue_for_read.xml b/man/sd_bus_enqueue_for_read.xml
index 30ccee2ef25..3318a3031bc 100644
--- a/man/sd_bus_enqueue_for_read.xml
+++ b/man/sd_bus_enqueue_for_read.xml
@@ -45,11 +45,11 @@
     is enqueued at the end of the queue, thus will be dispatched after all other already queued messages are
     dispatched.</para>
 
     <para>This call is primarily useful for dealing with incoming method calls that may be processed only
     after an additional asynchronous operation completes. One example are PolicyKit authorization requests
-    that are determined to be necessary to autorize a newly incoming method call: when the PolicyKit response
+    that are determined to be necessary to authorize a newly incoming method call: when the PolicyKit response
     is received the original method call may be re-enqueued to process it again, this time with the
     authorization result known.</para>
   </refsect1>
 
   <refsect1>
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 08b915cf7c5..8b6ebbcf8bf 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -683,11 +683,11 @@ global:
         sd_event_source_disable_unref;
 } LIBSYSTEMD_241;
 
 LIBSYSTEMD_245 {
 global:
-        sd_bus_enqeue_for_read;
+        sd_bus_enqueue_for_read;
         sd_bus_message_dump;
         sd_bus_message_sensitive;
         sd_event_add_child_pidfd;
         sd_event_source_get_child_pidfd;
         sd_event_source_get_child_pidfd_own;
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index c1db48f47a4..7ad03680f48 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -4206,11 +4206,11 @@ _public_ int sd_bus_get_close_on_exit(sd_bus *bus) {
         assert_return(bus = bus_resolve(bus), -ENOPKG);
 
         return bus->close_on_exit;
 }
 
-_public_ int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) {
+_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
         int r;
 
         assert_return(bus, -EINVAL);
         assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(m, -EINVAL);
@@ -4218,13 +4218,13 @@ _public_ int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) {
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (!BUS_IS_OPEN(bus->state))
                 return -ENOTCONN;
 
-        /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication,
-         * where we want accept a message, then determine we need to interactively authenticate the user, and
-         * when we have that process the message again. */
+        /* Re-enqueue a message for reading. This is primarily useful for PolicyKit-style authentication,
+         * where we accept a message, then determine we need to interactively authenticate the user, and then
+         * we want to process the message again. */
 
         r = bus_rqueue_make_room(bus);
         if (r < 0)
                 return r;
 
diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
index bd88e337b7b..0dbf3f60c8c 100644
--- a/src/shared/bus-polkit.c
+++ b/src/shared/bus-polkit.c
@@ -232,11 +232,11 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e
 
         r = sd_bus_message_rewind(q->request, true);
         if (r < 0)
                 goto fail;
 
-        r = sd_bus_enqeue_for_read(sd_bus_message_get_bus(q->request), q->request);
+        r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request);
         if (r < 0)
                 goto fail;
 
         return 1;
 
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 821b06ea926..e6f32987457 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -205,11 +205,11 @@ int sd_bus_get_events(sd_bus *bus);
 int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec);
 int sd_bus_process(sd_bus *bus, sd_bus_message **r);
 int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
 int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
 int sd_bus_flush(sd_bus *bus);
-int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m);
+int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);
 
 sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
 sd_bus_message* sd_bus_get_current_message(sd_bus *bus);
 sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus);
 void* sd_bus_get_current_userdata(sd_bus *bus);

Vulnerable code:   enqeue stop jobs from a defer event that processes queue instead of
    that are determined to be necessary to autorize a newly incoming method call: when the PolicyKit response
        sd_bus_enqeue_for_read;
_public_ int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) {
        /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication,
         * where we want accept a message, then determine we need to interactively authenticate the user, and
         * when we have that process the message again. */
        r = sd_bus_enqeue_for_read(sd_bus_message_get_bus(q->request), q->request);
int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m);
Fixed code:   enqueue stop jobs from a defer event that processes queue instead of
    that are determined to be necessary to authorize a newly incoming method call: when the PolicyKit response
        sd_bus_enqueue_for_read;
_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
        /* Re-enqueue a message for reading. This is primarily useful for PolicyKit-style authentication,
         * where we accept a message, then determine we need to interactively authenticate the user, and then
         * we want to process the message again. */
        r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request);
int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);