[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