Zbigniew Jędrzejewski-Szmek 4b2af1
From 8b0f54c9290564e8c27c9c8ac464cdcc2c659ad5 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 4b2af1
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Zbigniew Jędrzejewski-Szmek 4b2af1
Date: Sat, 6 Mar 2021 19:06:08 +0100
Zbigniew Jędrzejewski-Szmek 4b2af1
Subject: [PATCH 1/3] pid1: return varlink error on the right connection
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
---
Zbigniew Jędrzejewski-Szmek 4b2af1
 src/core/core-varlink.c | 6 +++---
Zbigniew Jędrzejewski-Szmek 4b2af1
 1 file changed, 3 insertions(+), 3 deletions(-)
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c
Zbigniew Jędrzejewski-Szmek 4b2af1
index d695106658b..b3df8cd893c 100644
Zbigniew Jędrzejewski-Szmek 4b2af1
--- a/src/core/core-varlink.c
Zbigniew Jędrzejewski-Szmek 4b2af1
+++ b/src/core/core-varlink.c
Zbigniew Jędrzejewski-Szmek 4b2af1
@@ -142,7 +142,7 @@ static int vl_method_subscribe_managed_oom_cgroups(
Zbigniew Jędrzejewski-Szmek 4b2af1
         /* We only take one subscriber for this method so return an error if there's already an existing one.
Zbigniew Jędrzejewski-Szmek 4b2af1
          * This shouldn't happen since systemd-oomd is the only client of this method. */
Zbigniew Jędrzejewski-Szmek 4b2af1
         if (FLAGS_SET(flags, VARLINK_METHOD_MORE) && m->managed_oom_varlink_request)
Zbigniew Jędrzejewski-Szmek 4b2af1
-                return varlink_error(m->managed_oom_varlink_request, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
Zbigniew Jędrzejewski-Szmek 4b2af1
+                return varlink_error(link, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
         r = json_build(&arr, JSON_BUILD_EMPTY_ARRAY);
Zbigniew Jędrzejewski-Szmek 4b2af1
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 4b2af1
@@ -188,6 +188,7 @@ static int vl_method_subscribe_managed_oom_cgroups(
Zbigniew Jędrzejewski-Szmek 4b2af1
         if (!FLAGS_SET(flags, VARLINK_METHOD_MORE))
Zbigniew Jędrzejewski-Szmek 4b2af1
                 return varlink_reply(link, v);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
+        assert(!m->managed_oom_varlink_request);
Zbigniew Jędrzejewski-Szmek 4b2af1
         m->managed_oom_varlink_request = varlink_ref(link);
Zbigniew Jędrzejewski-Szmek 4b2af1
         return varlink_notify(m->managed_oom_varlink_request, v);
Zbigniew Jędrzejewski-Szmek 4b2af1
 }
Zbigniew Jędrzejewski-Szmek 4b2af1
@@ -475,8 +476,7 @@ void manager_varlink_done(Manager *m) {
Zbigniew Jędrzejewski-Szmek 4b2af1
         assert(m);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
         /* Send the final message if we still have a subscribe request open. */
Zbigniew Jędrzejewski-Szmek 4b2af1
-        if (m->managed_oom_varlink_request)
Zbigniew Jędrzejewski-Szmek 4b2af1
-                m->managed_oom_varlink_request = varlink_close_unref(m->managed_oom_varlink_request);
Zbigniew Jędrzejewski-Szmek 4b2af1
+        m->managed_oom_varlink_request = varlink_close_unref(m->managed_oom_varlink_request);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
         m->varlink_server = varlink_server_unref(m->varlink_server);
Zbigniew Jędrzejewski-Szmek 4b2af1
 }
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
From 39ad3f1c092b5dffcbb4b1d12eb9ca407f010a3c Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 4b2af1
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Zbigniew Jędrzejewski-Szmek 4b2af1
Date: Sun, 7 Mar 2021 16:42:35 +0100
Zbigniew Jędrzejewski-Szmek 4b2af1
Subject: [PATCH 2/3] varlink: avoid using dangling ref in
Zbigniew Jędrzejewski-Szmek 4b2af1
 varlink_close_unref()
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
Fixes #18025, https://bugzilla.redhat.com/show_bug.cgi?id=1931034.
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
We drop the reference stored in Manager.managed_oom_varlink_request in two code paths:
Zbigniew Jędrzejewski-Szmek 4b2af1
vl_disconnect() which is installed as a disconnect callback, and in manager_varlink_done().
Zbigniew Jędrzejewski-Szmek 4b2af1
But we also make a disconnect from manager_varlink_done(). So we end up with the following
Zbigniew Jędrzejewski-Szmek 4b2af1
call stack:
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
(gdb) bt
Zbigniew Jędrzejewski-Szmek 4b2af1
 0  vl_disconnect (s=0x112c7b0, link=0xea0070, userdata=0xe9bcc0) at ../src/core/core-varlink.c:414
Zbigniew Jędrzejewski-Szmek 4b2af1
 1  0x00007f1366e9d5ac in varlink_detach_server (v=0xea0070) at ../src/shared/varlink.c:1210
Zbigniew Jędrzejewski-Szmek 4b2af1
 2  0x00007f1366e9d664 in varlink_close (v=0xea0070) at ../src/shared/varlink.c:1228
Zbigniew Jędrzejewski-Szmek 4b2af1
 3  0x00007f1366e9d6b5 in varlink_close_unref (v=0xea0070) at ../src/shared/varlink.c:1240
Zbigniew Jędrzejewski-Szmek 4b2af1
 4  0x0000000000524629 in manager_varlink_done (m=0xe9bcc0) at ../src/core/core-varlink.c:479
Zbigniew Jędrzejewski-Szmek 4b2af1
 5  0x000000000048ef7b in manager_free (m=0xe9bcc0) at ../src/core/manager.c:1357
Zbigniew Jędrzejewski-Szmek 4b2af1
 6  0x000000000042602c in main (argc=5, argv=0x7fff439c43d8) at ../src/core/main.c:2909
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
When we enter vl_disconnect(), m->managed_oom_varlink_request.n_ref==1.
Zbigniew Jędrzejewski-Szmek 4b2af1
When we exit from vl_discconect(), m->managed_oom_varlink_request==NULL. But
Zbigniew Jędrzejewski-Szmek 4b2af1
varlink_close_unref() has a copy of the pointer in *v. When we continue executing
Zbigniew Jędrzejewski-Szmek 4b2af1
varlink_close_unref(), this pointer is dangling, and the call to varlink_unref()
Zbigniew Jędrzejewski-Szmek 4b2af1
is done with an invalid pointer.
Zbigniew Jędrzejewski-Szmek 4b2af1
---
Zbigniew Jędrzejewski-Szmek 4b2af1
 src/shared/varlink.c | 33 +++++++++++++++++++++++++--------
Zbigniew Jędrzejewski-Szmek 4b2af1
 1 file changed, 25 insertions(+), 8 deletions(-)
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
Zbigniew Jędrzejewski-Szmek 4b2af1
index 31128e02e06..6ed72075ba5 100644
Zbigniew Jędrzejewski-Szmek 4b2af1
--- a/src/shared/varlink.c
Zbigniew Jędrzejewski-Szmek 4b2af1
+++ b/src/shared/varlink.c
Zbigniew Jędrzejewski-Szmek 4b2af1
@@ -1206,8 +1206,9 @@ int varlink_close(Varlink *v) {
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
         varlink_set_state(v, VARLINK_DISCONNECTED);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
-        /* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref
Zbigniew Jędrzejewski-Szmek 4b2af1
-         * which would destroy us before we can call varlink_clear() */
Zbigniew Jędrzejewski-Szmek 4b2af1
+        /* Let's take a reference first, since varlink_detach_server() might drop the final ref from the
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * disconnect callback, which would invalidate the pointer we are holding before we can call
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * varlink_clear(). */
Zbigniew Jędrzejewski-Szmek 4b2af1
         varlink_ref(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
         varlink_detach_server(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
         varlink_clear(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
@@ -1220,17 +1221,33 @@ Varlink* varlink_close_unref(Varlink *v) {
Zbigniew Jędrzejewski-Szmek 4b2af1
         if (!v)
Zbigniew Jędrzejewski-Szmek 4b2af1
                 return NULL;
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
-        (void) varlink_close(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
+        /* A reference is given to us to be destroyed. But when calling varlink_close(), a callback might
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * also drop a reference. We allow this, and will hold a temporary reference to the object to make
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * sure that the object still exists when control returns to us. If there's just one reference
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * remaining after varlink_close(), even though there were at least two right before, we'll handle
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * that gracefully instead of crashing.
Zbigniew Jędrzejewski-Szmek 4b2af1
+         *
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * In other words, this call drops the donated reference, but if the internal call to varlink_close()
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * dropped a reference to, we don't drop the reference afain. This allows the caller to say:
Zbigniew Jędrzejewski-Szmek 4b2af1
+         *     global_object->varlink = varlink_close_unref(global_object->varlink);
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * even though there is some callback which has access to global_object and may drop the reference
Zbigniew Jędrzejewski-Szmek 4b2af1
+         * stored in global_object->varlink. Without this step, the same code would have to be written as:
Zbigniew Jędrzejewski-Szmek 4b2af1
+         *     Varlink *t = TAKE_PTR(global_object->varlink);
Zbigniew Jędrzejewski-Szmek 4b2af1
+         *     varlink_close_unref(t);
Zbigniew Jędrzejewski-Szmek 4b2af1
+         */
Zbigniew Jędrzejewski-Szmek 4b2af1
+                                   /* n_ref >= 1 */
Zbigniew Jędrzejewski-Szmek 4b2af1
+        varlink_ref(v);            /* n_ref >= 2 */
Zbigniew Jędrzejewski-Szmek 4b2af1
+        varlink_close(v);          /* n_ref >= 1 */
Zbigniew Jędrzejewski-Szmek 4b2af1
+        if (v->n_ref > 1)
Zbigniew Jędrzejewski-Szmek 4b2af1
+                v->n_ref--;        /* n_ref >= 1 */
Zbigniew Jędrzejewski-Szmek 4b2af1
         return varlink_unref(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
 }
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
 Varlink* varlink_flush_close_unref(Varlink *v) {
Zbigniew Jędrzejewski-Szmek 4b2af1
-        if (!v)
Zbigniew Jędrzejewski-Szmek 4b2af1
-                return NULL;
Zbigniew Jędrzejewski-Szmek 4b2af1
+        if (v)
Zbigniew Jędrzejewski-Szmek 4b2af1
+                varlink_flush(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
-        (void) varlink_flush(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
-        (void) varlink_close(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
-        return varlink_unref(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
+        return varlink_close_unref(v);
Zbigniew Jędrzejewski-Szmek 4b2af1
 }
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
 static int varlink_enqueue_json(Varlink *v, JsonVariant *m) {
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
From a19c1a4baaa1dadc80885e3ad41f19a6c6c450fd Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 4b2af1
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Zbigniew Jędrzejewski-Szmek 4b2af1
Date: Mon, 8 Mar 2021 09:21:25 +0100
Zbigniew Jędrzejewski-Szmek 4b2af1
Subject: [PATCH 3/3] oomd: "downgrade" level of message
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
PID1 already logs about the service being started, so this line isn't necessary
Zbigniew Jędrzejewski-Szmek 4b2af1
in normal use. Also, by the time it is emitted, the service has already
Zbigniew Jędrzejewski-Szmek 4b2af1
signalled readiness, so let's not say "starting" but "started".
Zbigniew Jędrzejewski-Szmek 4b2af1
---
Zbigniew Jędrzejewski-Szmek 4b2af1
 src/oom/oomd.c | 2 +-
Zbigniew Jędrzejewski-Szmek 4b2af1
 1 file changed, 1 insertion(+), 1 deletion(-)
Zbigniew Jędrzejewski-Szmek 4b2af1
Zbigniew Jędrzejewski-Szmek 4b2af1
diff --git a/src/oom/oomd.c b/src/oom/oomd.c
Zbigniew Jędrzejewski-Szmek 4b2af1
index 674d53fdcfe..6e2a5889d1e 100644
Zbigniew Jędrzejewski-Szmek 4b2af1
--- a/src/oom/oomd.c
Zbigniew Jędrzejewski-Szmek 4b2af1
+++ b/src/oom/oomd.c
Zbigniew Jędrzejewski-Szmek 4b2af1
@@ -170,7 +170,7 @@ static int run(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
         notify_msg = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
-        log_info("systemd-oomd starting%s!", arg_dry_run ? " in dry run mode" : "");
Zbigniew Jędrzejewski-Szmek 4b2af1
+        log_debug("systemd-oomd started%s.", arg_dry_run ? " in dry run mode" : "");
Zbigniew Jędrzejewski-Szmek 4b2af1
 
Zbigniew Jędrzejewski-Szmek 4b2af1
         r = sd_event_loop(m->event);
Zbigniew Jędrzejewski-Szmek 4b2af1
         if (r < 0)