]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
service: don't try to determine selinux label for socket activation if RootImage...
authorLennart Poettering <lennart@poettering.net>
Thu, 21 Dec 2023 13:12:09 +0000 (14:12 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 22 Dec 2023 02:51:51 +0000 (11:51 +0900)
We cannot determine the SELinux label ahead of time if RootImage= is
used, since we'd have to mount the image then, hence don't, and handle
this cleanly, and gracefully.

While we are at it, stop "reaching over" so much from the socket code to
the service code, and instead provide function that most of the hard
work in service.c that socket.c just calls.

While we are at it, add debug logging and stuff.

I noticed the issue when also noticing #30560, but that one is harder to
fix, hence I avoided it for now.

src/core/service.c
src/core/service.h
src/core/socket.c

index b9eb40c5559c1c17928bb50eb17207b8ddec1d63..7bd4e99b11fb64f97cb873debcb41204e09dc0d7 100644 (file)
@@ -34,6 +34,7 @@
 #include "path-util.h"
 #include "process-util.h"
 #include "random-util.h"
+#include "selinux-util.h"
 #include "serialize.h"
 #include "service.h"
 #include "signal-util.h"
@@ -4975,6 +4976,57 @@ static void service_release_resources(Unit *u) {
                 service_set_state(s, SERVICE_DEAD);
 }
 
+int service_determine_exec_selinux_label(Service *s, char **ret) {
+        int r;
+
+        assert(s);
+        assert(ret);
+
+        if (!mac_selinux_use())
+                return -ENODATA;
+
+        /* Returns the SELinux label used for execution of the main service binary */
+
+        if (s->exec_context.selinux_context) { /* Prefer the explicitly configured label if there is one */
+                char *con = strdup(s->exec_context.selinux_context);
+                if (!con)
+                        return -ENOMEM;
+
+                *ret = con;
+                return 0;
+        }
+
+        if (s->exec_context.root_image ||
+            s->exec_context.n_extension_images > 0 ||
+            !strv_isempty(s->exec_context.extension_directories)) /* We cannot chase paths through images */
+                return log_unit_debug_errno(UNIT(s), SYNTHETIC_ERRNO(ENODATA), "Service with RootImage=, ExtensionImages= or ExtensionDirectories= set, cannot determine socket SELinux label before activation, ignoring.");
+
+        ExecCommand *c = s->exec_command[SERVICE_EXEC_START];
+        if (!c)
+                return -ENODATA;
+
+        _cleanup_free_ char *path = NULL;
+        r = chase(c->path, s->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL);
+        if (r < 0) {
+                log_unit_debug_errno(UNIT(s), r, "Failed to resolve service binary '%s', ignoring.", c->path);
+                return -ENODATA;
+        }
+
+        r = mac_selinux_get_create_label_from_exe(path, ret);
+        if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
+                log_unit_debug_errno(UNIT(s), r, "Reading SELinux label off binary '%s' is not supported, ignoring.", path);
+                return -ENODATA;
+        }
+        if (ERRNO_IS_NEG_PRIVILEGE(r)) {
+                log_unit_debug_errno(UNIT(s), r, "Can't read SELinux label off binary '%s', due to privileges, ignoring.", path);
+                return -ENODATA;
+        }
+        if (r < 0)
+                return log_unit_debug_errno(UNIT(s), r, "Failed to read SELinux label off binary '%s': %m", path);
+
+        return 0;
+}
+
 static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
         [SERVICE_RESTART_NO]          = "no",
         [SERVICE_RESTART_ON_SUCCESS]  = "on-success",
index e85302e616663cad2ef5c7a0ab12e5b41f2f0cba..364cd6885b8759b9f6d2fc0553fd5985ffdf2f33 100644 (file)
@@ -255,6 +255,8 @@ void service_release_socket_fd(Service *s);
 
 usec_t service_restart_usec_next(Service *s);
 
+int service_determine_exec_selinux_label(Service *s, char **ret);
+
 const char* service_restart_to_string(ServiceRestart i) _const_;
 ServiceRestart service_restart_from_string(const char *s) _pure_;
 
index c42a94d046dccccdd1b944a67d10cd63dedfa212..93faccf6ffca9c862df2ccd1b2daed01e0d73f5a 100644 (file)
@@ -1385,50 +1385,26 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {
 }
 
 static int socket_determine_selinux_label(Socket *s, char **ret) {
+        Unit *service;
         int r;
 
         assert(s);
         assert(ret);
 
-        Unit *service;
-        ExecCommand *c;
-        const char *exec_context;
-        _cleanup_free_ char *path = NULL;
-
-        r = socket_load_service_unit(s, -1, &service);
-        if (r == -ENODATA)
-                goto no_label;
+        r = socket_load_service_unit(s, /* cfd= */ -EBADF, &service);
+        if (r == -ENODATA) {
+                *ret = NULL;
+                return 0;
+        }
         if (r < 0)
                 return r;
 
-        exec_context = SERVICE(service)->exec_context.selinux_context;
-        if (exec_context) {
-                char *con;
-
-                con = strdup(exec_context);
-                if (!con)
-                        return -ENOMEM;
-
-                *ret = TAKE_PTR(con);
+        r = service_determine_exec_selinux_label(SERVICE(service), ret);
+        if (r == -ENODATA) {
+                *ret = NULL;
                 return 0;
         }
-
-        c = SERVICE(service)->exec_command[SERVICE_EXEC_START];
-        if (!c)
-                goto no_label;
-
-        r = chase(c->path, SERVICE(service)->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL);
-        if (r < 0)
-                goto no_label;
-
-        r = mac_selinux_get_create_label_from_exe(path, ret);
-        if (IN_SET(r, -EPERM, -EOPNOTSUPP))
-                goto no_label;
         return r;
-
-no_label:
-        *ret = NULL;
-        return 0;
 }
 
 static int socket_address_listen_do(