[systemd-devel] [PATCH] selinux: fix selinux check for transient units

Vaclav Pavlin vpavlin at redhat.com
Thu Oct 31 15:51:54 CET 2013


From: Václav Pavlín <vpavlin at redhat.com>

---
 src/core/selinux-access.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/core/selinux-access.h | 15 +++++++++---
 2 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index 0a3ee18..5908a79 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -333,6 +333,50 @@ static int get_calling_context(
         return 0;
 }
 
+static int load_context(
+                const char *path,
+                const char *name,
+                char **context) {
+
+        int r = 0;
+        char l[LINE_MAX];
+        char *p;
+        FILE *fd;
+
+        fd = fopen(path, "r");
+        if (!fd)
+                return -EEXIST;
+
+        if (!fgets(l, sizeof(l), fd)) {
+                if (feof(fd)) {
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                log_error("Failed to read context file '%s': %m", path);
+                r = -errno;
+                goto finish;
+        }
+
+        p = strtok (l, "=");
+        if (p && streq(p, name)) {
+                p = strtok (NULL, "=");
+                if (!p) {
+                        r = -EINVAL;
+                        goto finish;
+                }
+
+                *context = strdup(p);
+        } else
+                r = -EINVAL;
+
+finish:
+        if (fd)
+                fclose(fd);
+
+        return r;
+}
+
 /*
    This function communicates with the kernel to check whether or not it should
    allow the access.
@@ -342,6 +386,7 @@ static int get_calling_context(
 int selinux_access_check(
                 DBusConnection *connection,
                 DBusMessage *message,
+                int class,
                 const char *path,
                 const char *permission,
                 DBusError *error) {
@@ -374,7 +419,7 @@ int selinux_access_check(
                 goto finish;
         }
 
-        if (path) {
+        if (class == CLASS_SERVICE) {
                 tclass = "service";
                 /* get the file context of the unit file */
                 r = getfilecon(path, &fcon);
@@ -384,7 +429,19 @@ int selinux_access_check(
                         log_error("Failed to get security context on %s: %m",path);
                         goto finish;
                 }
+        } else if (class == CLASS_TRANSIENT) {
+                const char *context_path = selinux_systemd_contexts_path();
+
+                tclass = "service";
 
+                /* get the context transient unit */
+                r = load_context(context_path, "runtime", &fcon);
+                if (r < 0) {
+                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get context for transient unit");
+                        r = -errno;
+                        log_error("Failed to get security context on transient unit %s: %m", context_path);
+                        goto finish;
+                }
         } else {
                 tclass = "system";
                 r = getcon(&fcon);
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
index 2d7ac64..79eea6a 100644
--- a/src/core/selinux-access.h
+++ b/src/core/selinux-access.h
@@ -25,7 +25,13 @@
 
 void selinux_access_free(void);
 
-int selinux_access_check(DBusConnection *connection, DBusMessage *message, const char *path, const char *permission, DBusError *error);
+int selinux_access_check(DBusConnection *connection, DBusMessage *message, int class, const char *path, const char *permission, DBusError *error);
+
+enum {
+        CLASS_SYSTEM,
+        CLASS_SERVICE,
+        CLASS_TRANSIENT
+};
 
 #ifdef HAVE_SELINUX
 
@@ -36,7 +42,7 @@ int selinux_access_check(DBusConnection *connection, DBusMessage *message, const
                 DBusConnection *_c = (connection);                      \
                 DBusMessage *_m = (message);                            \
                 dbus_error_init(&_error);                               \
-                _r = selinux_access_check(_c, _m, NULL, (permission), &_error); \
+                _r = selinux_access_check(_c, _m, CLASS_SYSTEM, NULL, (permission), &_error); \
                 if (_r < 0)                                             \
                         return bus_send_error_reply(_c, _m, &_error, _r); \
         } while (false)
@@ -49,7 +55,10 @@ int selinux_access_check(DBusConnection *connection, DBusMessage *message, const
                 DBusMessage *_m = (message);                            \
                 Unit *_u = (unit);                                      \
                 dbus_error_init(&_error);                               \
-                _r = selinux_access_check(_c, _m, _u->source_path ?: _u->fragment_path, (permission), &_error); \
+                if (_u->source_path || _u->fragment_path)              \
+                        _r = selinux_access_check(_c, _m, CLASS_SERVICE, _u->source_path ?: _u->fragment_path, (permission), &_error); \
+                else                                                    \
+                        _r = selinux_access_check(_c, _m, CLASS_TRANSIENT, _u->id, (permission), &_error); \
                 if (_r < 0)                                             \
                         return bus_send_error_reply(_c, _m, &_error, _r); \
         } while (false)
-- 
1.8.3.1



More information about the systemd-devel mailing list