]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
selinux: get_our_contexts()
authorIvan Kruglov <mail@ikruglov.com>
Thu, 3 Jul 2025 13:40:14 +0000 (06:40 -0700)
committerIvan Kruglov <mail@ikruglov.com>
Thu, 10 Jul 2025 19:06:51 +0000 (21:06 +0200)
src/core/selinux-access.c

index 1a0f57d167c15f2f44a04e6ab20e2a417d9dd3ef..b53730963ae145f209c9cc05c77923d16c58cdf1 100644 (file)
@@ -164,6 +164,39 @@ static int access_init(sd_bus_error *error) {
         return 1;
 }
 
+static int get_our_contexts(const Unit *unit, const char **ret_acon, const char **ret_tclass, char **ret_fcon) {
+        _cleanup_freecon_ char *fcon = NULL;
+
+        assert(ret_acon);
+        assert(ret_tclass);
+        assert(ret_fcon);
+
+        if (unit && unit->access_selinux_context) {
+                /* Nice! The unit comes with a SELinux context read from the unit file */
+                *ret_acon = unit->access_selinux_context;
+                *ret_tclass = "service";
+                *ret_fcon = NULL;
+                return 0;
+        }
+
+        /* If no unit context is known, use our own */
+
+        /* Ideally, we should call mac_selinux_get_our_label() here because it
+         * does exactly the same - call getcon_raw(). However, it involves
+         * selinux_init() which opens label DB. It was not part of the
+         * original code. I don't want to change it for now. */
+        if (getcon_raw(&fcon) < 0)
+                return log_debug_errno(errno, "SELinux getcon_raw() failed: %m");
+
+        if (!fcon)
+                return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "SELinux returned no context of the current process");
+
+        *ret_acon = fcon;
+        *ret_tclass = "system";
+        *ret_fcon = TAKE_PTR(fcon);
+        return 0;
+}
+
 /*
    This function communicates with the kernel to check whether or not it should
    allow the access.
@@ -216,30 +249,21 @@ int mac_selinux_access_check_bus_internal(
         if (r < 0)
                 return r;
 
-        if (unit && unit->access_selinux_context) {
-                /* Nice! The unit comes with a SELinux context read from the unit file */
-                acon = unit->access_selinux_context;
-                tclass = "service";
-        } else {
-                /* If no unit context is known, use our own */
-                if (getcon_raw(&fcon) < 0) {
-                        log_warning_errno(errno, "SELinux getcon_raw() failed%s (perm=%s): %m",
-                                          enforce ? "" : ", ignoring",
-                                          permission);
-                        if (!enforce)
-                                return 0;
-
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context: %m");
-                }
-                if (!fcon) {
-                        if (!enforce)
-                                return 0;
+        r = get_our_contexts(unit, &acon, &tclass, &fcon);
+        if (r < 0) {
+                log_selinux_enforcing_errno(
+                                r,
+                                "Failed to retrieves SELinux context of current process (perm=%s)%s: %m",
+                                permission,
+                                enforce ? "" : ", ignoring");
 
+                if (!enforce)
+                        return 0;
+
+                if (r == -EOPNOTSUPP)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "We appear not to have any SELinux context: %m");
-                }
 
-                acon = fcon;
-                tclass = "system";
+                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context: %m");
         }
 
         (void) sd_bus_creds_get_cmdline(creds, &cmdline);