]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: ensure varlink Unit.List() can query inactive units
authorLuca Boccassi <luca.boccassi@gmail.com>
Fri, 9 Jan 2026 18:15:06 +0000 (19:15 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 13 Feb 2026 19:16:13 +0000 (19:16 +0000)
manager_get_unit() only returns loaded units, if a unit is
stopped and not referenced by anything it will be GCed, so
this method will return nothing. Use manager_load_unit()
instead so that a stopped unit gets loaded and we can
return its state to the caller, after checking that it
actually exists.

Follow-up for d2a8dbabf5e2676f436515cc821040bd24eb6003

src/core/varlink-unit.c
src/shared/varlink-io.systemd.Unit.c

index aa9a8fb0ede9603382447e27983943e2d2357d4f..71430ca5d38916b6754bd9d002ba7d408514b545 100644 (file)
@@ -361,6 +361,40 @@ static int lookup_unit_by_pidref(sd_varlink *link, Manager *manager, PidRef *pid
         return 0;
 }
 
+static int load_unit_and_check(sd_varlink *link, Manager *manager, const char *name, Unit **ret_unit) {
+        Unit *unit;
+        int r;
+
+        assert(link);
+        assert(manager);
+        assert(name);
+        assert(ret_unit);
+
+        r = manager_load_unit(manager, name, /* path= */ NULL, /* e= */ NULL, &unit);
+        if (r < 0)
+                return r;
+
+        /* manager_load_unit() will create an object regardless of whether the unit actually exists, so
+         * check the state and refuse if it's not in a good state. */
+        if (IN_SET(unit->load_state, UNIT_NOT_FOUND, UNIT_STUB, UNIT_MERGED))
+                return sd_varlink_error(link, "io.systemd.Unit.NoSuchUnit", NULL);
+        if (unit->load_state == UNIT_BAD_SETTING)
+                return sd_varlink_error(link, "io.systemd.Unit.UnitError", NULL);
+        if (unit->load_state == UNIT_ERROR)
+                return sd_varlink_errorbo(
+                        link,
+                        SD_VARLINK_ERROR_SYSTEM,
+                        SD_JSON_BUILD_PAIR_STRING("origin", "linux"),
+                        SD_JSON_BUILD_PAIR_INTEGER("errno", unit->load_error),
+                        JSON_BUILD_PAIR_STRING_NON_EMPTY("errnoName", "io.systemd.Unit.UnitError"));
+        if (unit->load_state == UNIT_MASKED)
+                return sd_varlink_error(link, "io.systemd.Unit.UnitMasked", NULL);
+        assert(UNIT_IS_LOAD_COMPLETE(unit->load_state));
+
+        *ret_unit = unit;
+        return 0;
+}
+
 typedef struct UnitLookupParameters {
         const char *name, *cgroup;
         PidRef pidref;
@@ -400,9 +434,9 @@ static int lookup_unit_by_parameters(
         assert(ret);
 
         if (p->name) {
-                unit = manager_get_unit(manager, p->name);
-                if (!unit)
-                        return varlink_error_no_such_unit(link, "name");
+                r = load_unit_and_check(link, manager, p->name, &unit);
+                if (r < 0)
+                        return r;
         }
 
         if (pidref_is_set_or_automatic(&p->pidref)) {
index 19d384dd9135d8157da57b909299e412b38190bb..b9128e78dfe6914023a460c6acf2e6b452e00b32 100644 (file)
@@ -1025,6 +1025,8 @@ static SD_VARLINK_DEFINE_ERROR(
 
 static SD_VARLINK_DEFINE_ERROR(OnlyByDependency);
 static SD_VARLINK_DEFINE_ERROR(DBusShuttingDown);
+static SD_VARLINK_DEFINE_ERROR(UnitMasked);
+static SD_VARLINK_DEFINE_ERROR(UnitError);
 
 SD_VARLINK_DEFINE_INTERFACE(
                 io_systemd_Unit,
@@ -1091,6 +1093,10 @@ SD_VARLINK_DEFINE_INTERFACE(
                 /* Errors */
                 SD_VARLINK_SYMBOL_COMMENT("No matching unit found"),
                 &vl_error_NoSuchUnit,
+                SD_VARLINK_SYMBOL_COMMENT("The unit is masked"),
+                &vl_error_UnitMasked,
+                SD_VARLINK_SYMBOL_COMMENT("Unit is in a fatal error state"),
+                &vl_error_UnitError,
                 SD_VARLINK_SYMBOL_COMMENT("Job for the unit may only be enqueued by dependencies"),
                 &vl_error_OnlyByDependency,
                 SD_VARLINK_SYMBOL_COMMENT("A unit that requires D-Bus cannot be started as D-Bus is shutting down"),