]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: only allow systemd-oomd to use SubscribeManagedOOMCGroups 24919/head
authorAnita Zhang <the.anitazha@gmail.com>
Wed, 5 Oct 2022 08:40:40 +0000 (01:40 -0700)
committerAnita Zhang <the.anitazha@gmail.com>
Fri, 14 Oct 2022 16:57:59 +0000 (09:57 -0700)
Attempt to address
https://github.com/systemd/systemd/issues/20330#issuecomment-1210028422.

Summary of the comment: Unprivileged users can potentially cause a denial of
service during systemd-oomd unit subscriptions by spamming requests to
SubscribeManagedOOMCGroups. As systemd-oomd.service is the only unit that
should be accessing this method, add a check on the caller's unit name to deter
them from successfully using this method.

src/core/core-varlink.c
src/shared/varlink.h

index 031514ead06ff8513861784bc81ace89e6e3ff69..843271593d232cd4c38bd4495c1f1111e0dccc60 100644 (file)
@@ -203,10 +203,25 @@ static int vl_method_subscribe_managed_oom_cgroups(
 
         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
         Manager *m = ASSERT_PTR(userdata);
+        pid_t pid;
+        Unit *u;
         int r;
 
         assert(link);
 
+        r = varlink_get_peer_pid(link, &pid);
+        if (r < 0)
+                return r;
+
+        u = manager_get_unit_by_pid(m, pid);
+        if (!u)
+                return varlink_error(link, VARLINK_ERROR_PERMISSION_DENIED, NULL);
+
+        /* This is meant to be a deterrent and not actual security. The alternative is to check for the systemd-oom
+         * user that this unit runs as, but NSS lookups are blocking and not allowed from PID 1. */
+        if (!streq(u->id, "systemd-oomd.service"))
+                return varlink_error(link, VARLINK_ERROR_PERMISSION_DENIED, NULL);
+
         if (json_variant_elements(parameters) > 0)
                 return varlink_error_invalid_parameter(link, parameters);
 
index 66a1ff630e723f013a3b47c077da754c79380f94..9518cd909844f1d236255641f13565304b2d5850 100644 (file)
@@ -173,3 +173,4 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref);
 #define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
 #define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
 #define VARLINK_ERROR_SUBSCRIPTION_TAKEN "org.varlink.service.SubscriptionTaken"
+#define VARLINK_ERROR_PERMISSION_DENIED "org.varlink.service.PermissionDenied"