1ff636
From e3f34eb2e0edc9cefe92e58e2ad4c98bcccf2090 Mon Sep 17 00:00:00 2001
1ff636
From: Lukas Nykryn <lnykryn@redhat.com>
1ff636
Date: Thu, 27 Aug 2015 10:33:15 +0200
1ff636
Subject: [PATCH] selinux: fix check for transient units
1ff636
1ff636
SELinux does not have a path to check for a snapshot service creation.
1ff636
This ends up giving us a bogus check.
1ff636
1ff636
On snapshot creation we should check if the remote process type, has the
1ff636
ability to start a service with the type that systemd is running with.
1ff636
1ff636
Based on patch from Vaclav Pavlin and Dan Walsh
1ff636
http://lists.freedesktop.org/archives/systemd-devel/2013-November/014021.html
1ff636
1ff636
RHEL only
1ff636
Resolves: #1255129
1ff636
---
1ff636
 src/core/dbus-manager.c   |  4 ++--
1ff636
 src/core/selinux-access.c | 11 ++++++-----
1ff636
 src/core/selinux-access.h |  9 ++++++---
1ff636
 3 files changed, 14 insertions(+), 10 deletions(-)
1ff636
1ff636
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
1ff636
index 2bc37ba..1ec350e 100644
1ff636
--- a/src/core/dbus-manager.c
1ff636
+++ b/src/core/dbus-manager.c
1ff636
@@ -734,7 +734,7 @@ static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, voi
1ff636
         if (mode < 0)
1ff636
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
1ff636
 
1ff636
-        r = mac_selinux_access_check(message, "start", error);
1ff636
+        r = mac_selinux_runtime_unit_access_check(message, "start", error);
1ff636
         if (r < 0)
1ff636
                 return r;
1ff636
 
1ff636
@@ -1092,7 +1092,7 @@ static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *us
1ff636
         assert(message);
1ff636
         assert(m);
1ff636
 
1ff636
-        r = mac_selinux_access_check(message, "start", error);
1ff636
+        r = mac_selinux_runtime_unit_access_check(message, "start", error);
1ff636
         if (r < 0)
1ff636
                 return r;
1ff636
 
1ff636
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
1ff636
index ce4f394..91460b8 100644
1ff636
--- a/src/core/selinux-access.c
1ff636
+++ b/src/core/selinux-access.c
1ff636
@@ -175,6 +175,7 @@ void mac_selinux_access_free(void) {
1ff636
 */
1ff636
 int mac_selinux_generic_access_check(
1ff636
                 sd_bus_message *message,
1ff636
+                bool system,
1ff636
                 const char *path,
1ff636
                 const char *permission,
1ff636
                 sd_bus_error *error) {
1ff636
@@ -213,7 +214,9 @@ int mac_selinux_generic_access_check(
1ff636
         if (r < 0)
1ff636
                 goto finish;
1ff636
 
1ff636
-        if (path) {
1ff636
+        tclass = "service";
1ff636
+
1ff636
+        if (path && !system) {
1ff636
                 /* Get the file context of the unit file */
1ff636
 
1ff636
                 r = getfilecon(path, &fcon);
1ff636
@@ -221,16 +224,14 @@ int mac_selinux_generic_access_check(
1ff636
                         r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
1ff636
                         goto finish;
1ff636
                 }
1ff636
-
1ff636
-                tclass = "service";
1ff636
         } else {
1ff636
                 r = getcon(&fcon);
1ff636
                 if (r < 0) {
1ff636
                         r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
1ff636
                         goto finish;
1ff636
                 }
1ff636
-
1ff636
-                tclass = "system";
1ff636
+                if (system)
1ff636
+                        tclass = "system";
1ff636
         }
1ff636
 
1ff636
         sd_bus_creds_get_cmdline(creds, &cmdline);
1ff636
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
1ff636
index dd1e8bb..7dc271b 100644
1ff636
--- a/src/core/selinux-access.h
1ff636
+++ b/src/core/selinux-access.h
1ff636
@@ -28,21 +28,24 @@
1ff636
 
1ff636
 void mac_selinux_access_free(void);
1ff636
 
1ff636
-int mac_selinux_generic_access_check(sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error);
1ff636
+int mac_selinux_generic_access_check(sd_bus_message *message, bool system, const char *path, const char *permission, sd_bus_error *error);
1ff636
 
1ff636
 int mac_selinux_unit_access_check_strv(char **units, sd_bus_message *message, Manager *m, const char *permission, sd_bus_error *error);
1ff636
 
1ff636
 #ifdef HAVE_SELINUX
1ff636
 
1ff636
 #define mac_selinux_access_check(message, permission, error) \
1ff636
-        mac_selinux_generic_access_check((message), NULL, (permission), (error))
1ff636
+        mac_selinux_generic_access_check((message), true, NULL, (permission), (error))
1ff636
 
1ff636
 #define mac_selinux_unit_access_check(unit, message, permission, error) \
1ff636
         ({                                                              \
1ff636
                 Unit *_unit = (unit);                                   \
1ff636
-                mac_selinux_generic_access_check((message), _unit->source_path ?: _unit->fragment_path, (permission), (error)); \
1ff636
+                mac_selinux_generic_access_check((message), false, _unit->source_path ?: _unit->fragment_path, (permission), (error)); \
1ff636
         })
1ff636
 
1ff636
+#define mac_selinux_runtime_unit_access_check(message, permission, error) \
1ff636
+        mac_selinux_generic_access_check((message), false, NULL, (permission), (error))
1ff636
+
1ff636
 #else
1ff636
 
1ff636
 #define mac_selinux_access_check(message, permission, error) 0