]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
selinux: cache enforced status and treat retrieve failure as enforced mode 15010/head
authorChristian Göttsche <cgzones@googlemail.com>
Mon, 2 Mar 2020 20:12:18 +0000 (21:12 +0100)
committerChristian Göttsche <cgzones@googlemail.com>
Tue, 3 Mar 2020 19:30:59 +0000 (20:30 +0100)
src/basic/selinux-util.c
src/basic/selinux-util.h
src/core/selinux-access.c

index 5cad56414211bf7b6ea4f7edf517ce19e24685ab..2b5f757134ff249c3aae3179ef7cebe124100dc2 100644 (file)
@@ -35,10 +35,11 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
 static int mac_selinux_reload(int seqno);
 
 static int cached_use = -1;
+static int cached_enforcing = -1;
 static struct selabel_handle *label_hnd = NULL;
 
-#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
-#define log_enforcing_errno(r, ...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_WARNING, r, __VA_ARGS__)
+#define log_enforcing(...) log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
+#define log_enforcing_errno(r, ...) log_full_errno(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, r, __VA_ARGS__)
 #endif
 
 bool mac_selinux_use(void) {
@@ -52,12 +53,37 @@ bool mac_selinux_use(void) {
 #endif
 }
 
+bool mac_selinux_enforcing(void) {
+#if HAVE_SELINUX
+        if (cached_enforcing < 0) {
+                cached_enforcing = security_getenforce();
+                if (cached_enforcing == -1) {
+                        log_error_errno(errno, "Failed to get SELinux enforced status: %m");
+                }
+        }
+
+        /* treat failure as enforced mode */
+        return (cached_enforcing != 0);
+#else
+        return false;
+#endif
+}
+
 void mac_selinux_retest(void) {
 #if HAVE_SELINUX
         cached_use = -1;
+        cached_enforcing = -1;
 #endif
 }
 
+#if HAVE_SELINUX
+static int setenforce_callback(int enforcing) {
+        cached_enforcing = enforcing;
+
+        return 0;
+}
+#endif
+
 int mac_selinux_init(void) {
         int r = 0;
 
@@ -66,6 +92,7 @@ int mac_selinux_init(void) {
         struct mallinfo before_mallinfo, after_mallinfo;
 
         selinux_set_callback(SELINUX_CB_POLICYLOAD, (union selinux_callback) mac_selinux_reload);
+        selinux_set_callback(SELINUX_CB_SETENFORCE, (union selinux_callback) setenforce_callback);
 
         if (label_hnd)
                 return 0;
@@ -79,7 +106,7 @@ int mac_selinux_init(void) {
         label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
         if (!label_hnd) {
                 log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
-                r = security_getenforce() == 1 ? -errno : 0;
+                r = mac_selinux_enforcing() ? -errno : 0;
         } else  {
                 char timespan[FORMAT_TIMESPAN_MAX];
                 int l;
@@ -195,7 +222,7 @@ int mac_selinux_fix(const char *path, LabelFixFlags flags) {
 
 fail:
         log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path);
-        if (security_getenforce() == 1)
+        if (mac_selinux_enforcing())
                 return r;
 #endif
 
@@ -213,7 +240,7 @@ int mac_selinux_apply(const char *path, const char *label) {
 
         if (setfilecon(path, label) < 0) {
                 log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
-                if (security_getenforce() > 0)
+                if (mac_selinux_enforcing())
                         return -errno;
         }
 #endif
@@ -375,7 +402,7 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
                 log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
         }
 
-        if (security_getenforce() > 0)
+        if (mac_selinux_enforcing())
                 return -errno;
 
         return 0;
@@ -456,7 +483,7 @@ int mac_selinux_create_socket_prepare(const char *label) {
         if (setsockcreatecon(label) < 0) {
                 log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
 
-                if (security_getenforce() == 1)
+                if (mac_selinux_enforcing())
                         return -errno;
         }
 #endif
@@ -530,13 +557,13 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
                         goto skipped;
 
                 log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
-                if (security_getenforce() > 0)
+                if (mac_selinux_enforcing())
                         return -errno;
 
         } else {
                 if (setfscreatecon_raw(fcon) < 0) {
                         log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
-                        if (security_getenforce() > 0)
+                        if (mac_selinux_enforcing())
                                 return -errno;
                 } else
                         context_changed = true;
index e3a40478cbc594af1bc34a7055a0828f554187cd..159f3f16c24167fbec99a2f151dbcf7024c87bd3 100644 (file)
@@ -16,6 +16,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
 #endif
 
 bool mac_selinux_use(void);
+bool mac_selinux_enforcing(void);
 void mac_selinux_retest(void);
 
 int mac_selinux_init(void);
index 00f5241cd11dee2fbbe643335ec92b5c387475f9..008a8ba9b6aa92786a81ba83c8b286efcff9f6b1 100644 (file)
@@ -143,16 +143,16 @@ static int access_init(sd_bus_error *error) {
                 return 1;
 
         if (avc_open(NULL, 0) != 0) {
-                int enforce, saved_errno = errno;
+                int saved_errno = errno;
+                const bool enforce = mac_selinux_enforcing();
 
-                enforce = security_getenforce();
-                log_full_errno(enforce != 0 ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m");
+                log_full_errno(enforce ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m");
 
                 /* If enforcement isn't on, then let's suppress this
                  * error, and just don't do any AVC checks. The
                  * warning we printed is hence all the admin will
                  * see. */
-                if (enforce == 0)
+                if (!enforce)
                         return 0;
 
                 /* Return an access denied error, if we couldn't load
@@ -185,7 +185,7 @@ int mac_selinux_generic_access_check(
         _cleanup_free_ char *cl = NULL;
         _cleanup_freecon_ char *fcon = NULL;
         char **cmdline = NULL;
-        bool enforce = false; /* Will be set to the real value later if needed */
+        const bool enforce = mac_selinux_enforcing();
         int r = 0;
 
         assert(message);
@@ -223,7 +223,6 @@ int mac_selinux_generic_access_check(
 
                 if (getfilecon_raw(path, &fcon) < 0) {
                         r = -errno;
-                        enforce = security_getenforce() > 0;
 
                         log_warning_errno(r, "SELinux getfilecon_raw on '%s' failed%s (perm=%s): %m",
                                           path,
@@ -240,7 +239,6 @@ int mac_selinux_generic_access_check(
         } else {
                 if (getcon_raw(&fcon) < 0) {
                         r = -errno;
-                        enforce = security_getenforce() > 0;
 
                         log_warning_errno(r, "SELinux getcon_raw failed%s (perm=%s): %m",
                                           enforce ? "" : ", ignoring",
@@ -266,7 +264,6 @@ int mac_selinux_generic_access_check(
         r = selinux_check_access(scon, fcon, tclass, permission, &audit_info);
         if (r < 0) {
                 r = errno_or_else(EPERM);
-                enforce = security_getenforce() > 0;
 
                 if (enforce)
                         sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");