9fc0f6
From 96bb682b6fa33faaff5c3db7506e9864fe5c09dc Mon Sep 17 00:00:00 2001
9fc0f6
From: Dan Walsh <dwalsh@redhat.com>
9fc0f6
Date: Thu, 16 Jan 2014 12:59:10 +0100
9fc0f6
Subject: [PATCH] Fix SELinux check for transient units. (#1008864)
9fc0f6
9fc0f6
SELinux does not have a path to check for a snapshot servic creation.
9fc0f6
This ends up giving us a bogus check.
9fc0f6
9fc0f6
On snapshot creation we should check if the remote process type, has the ability to start a service with the type that systemd is running with.
9fc0f6
---
9fc0f6
 src/core/dbus-manager.c   |  6 +++---
9fc0f6
 src/core/selinux-access.c |  9 +++++----
9fc0f6
 src/core/selinux-access.h | 13 +++++++++++++
9fc0f6
 3 files changed, 21 insertions(+), 7 deletions(-)
9fc0f6
9fc0f6
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
9fc0f6
index 8f4d017..7be5d13 100644
9fc0f6
--- a/src/core/dbus-manager.c
9fc0f6
+++ b/src/core/dbus-manager.c
9fc0f6
@@ -1102,7 +1102,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
9fc0f6
                 dbus_bool_t cleanup;
9fc0f6
                 Snapshot *s;
9fc0f6
 
9fc0f6
-                SELINUX_ACCESS_CHECK(connection, message, "start");
9fc0f6
+                SELINUX_RUNTIME_UNIT_ACCESS_CHECK(connection, message, "start");
9fc0f6
 
9fc0f6
                 if (!dbus_message_get_args(
9fc0f6
                                     message,
9fc0f6
@@ -1155,7 +1155,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
9fc0f6
                         return bus_send_error_reply(connection, message, &error, -ENOENT);
9fc0f6
                 }
9fc0f6
 
9fc0f6
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
9fc0f6
+                SELINUX_RUNTIME_UNIT_ACCESS_CHECK(connection, message, "stop");
9fc0f6
                 snapshot_remove(SNAPSHOT(u));
9fc0f6
 
9fc0f6
                 reply = dbus_message_new_method_return(message);
9fc0f6
@@ -1765,7 +1765,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
9fc0f6
                 if (r < 0)
9fc0f6
                         return bus_send_error_reply(connection, message, &error, r);
9fc0f6
 
9fc0f6
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
9fc0f6
+                SELINUX_RUNTIME_UNIT_ACCESS_CHECK(connection, message, "start");
9fc0f6
 
9fc0f6
                 if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) {
9fc0f6
                         dbus_set_error(&error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
9fc0f6
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
9fc0f6
index 0a3ee18..5d85b26 100644
9fc0f6
--- a/src/core/selinux-access.c
9fc0f6
+++ b/src/core/selinux-access.c
9fc0f6
@@ -374,8 +374,9 @@ int selinux_access_check(
9fc0f6
                 goto finish;
9fc0f6
         }
9fc0f6
 
9fc0f6
-        if (path) {
9fc0f6
-                tclass = "service";
9fc0f6
+
9fc0f6
+        tclass = "service";
9fc0f6
+        if (path && !strneq(path,"system", strlen("system"))) {
9fc0f6
                 /* get the file context of the unit file */
9fc0f6
                 r = getfilecon(path, &fcon);
9fc0f6
                 if (r < 0) {
9fc0f6
@@ -384,9 +385,9 @@ int selinux_access_check(
9fc0f6
                         log_error("Failed to get security context on %s: %m",path);
9fc0f6
                         goto finish;
9fc0f6
                 }
9fc0f6
-
9fc0f6
         } else {
9fc0f6
-                tclass = "system";
9fc0f6
+                if (path)
9fc0f6
+                        tclass = "system";
9fc0f6
                 r = getcon(&fcon);
9fc0f6
                 if (r < 0) {
9fc0f6
                         dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
9fc0f6
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
9fc0f6
index 2d7ac64..92acd69 100644
9fc0f6
--- a/src/core/selinux-access.h
9fc0f6
+++ b/src/core/selinux-access.h
9fc0f6
@@ -36,6 +36,18 @@ int selinux_access_check(DBusConnection *connection, DBusMessage *message, const
9fc0f6
                 DBusConnection *_c = (connection);                      \
9fc0f6
                 DBusMessage *_m = (message);                            \
9fc0f6
                 dbus_error_init(&_error);                               \
9fc0f6
+                _r = selinux_access_check(_c, _m, "system", (permission), &_error); \
9fc0f6
+                if (_r < 0)                                             \
9fc0f6
+                        return bus_send_error_reply(_c, _m, &_error, _r); \
9fc0f6
+        } while (false)
9fc0f6
+
9fc0f6
+#define SELINUX_RUNTIME_UNIT_ACCESS_CHECK(connection, message, permission) \
9fc0f6
+        do {                                                            \
9fc0f6
+                DBusError _error;                                       \
9fc0f6
+                int _r;                                                 \
9fc0f6
+                DBusConnection *_c = (connection);                      \
9fc0f6
+                DBusMessage *_m = (message);                            \
9fc0f6
+                dbus_error_init(&_error);                               \
9fc0f6
                 _r = selinux_access_check(_c, _m, NULL, (permission), &_error); \
9fc0f6
                 if (_r < 0)                                             \
9fc0f6
                         return bus_send_error_reply(_c, _m, &_error, _r); \
9fc0f6
@@ -57,6 +69,7 @@ int selinux_access_check(DBusConnection *connection, DBusMessage *message, const
9fc0f6
 #else
9fc0f6
 
9fc0f6
 #define SELINUX_ACCESS_CHECK(connection, message, permission) do { } while (false)
9fc0f6
+#define SELINUX_RUNTIME_UNIT_ACCESS_CHECK(connection, message, permission) do { } while (false)
9fc0f6
 #define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) do { } while (false)
9fc0f6
 
9fc0f6
 #endif