chiark / gitweb /
Implement SocketUser= and SocketGroup= for [Socket]
[elogind.git] / src / core / selinux-access.c
index 3a244ad9ffab422c0bcbd829fe529d01dc778735..6dfe8b45f3e5095d48391db5b63bee5a3ae4b022 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "util.h"
-#include "job.h"
-#include "manager.h"
 #include "selinux-access.h"
 
 #ifdef HAVE_SELINUX
-#include "dbus.h"
-#include "log.h"
-#include "dbus-unit.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
-#include "audit.h"
-#include "selinux-util.h"
 
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
+#include <limits.h>
 #include <selinux/selinux.h>
 #include <selinux/avc.h>
 #ifdef HAVE_AUDIT
 #include <libaudit.h>
 #endif
-#include <limits.h>
+#include <dbus.h>
+
+#include "util.h"
+#include "log.h"
+#include "bus-errors.h"
+#include "dbus-common.h"
+#include "audit.h"
+#include "selinux-util.h"
+#include "audit-fd.h"
 
 static bool initialized = false;
-static int audit_fd = -1;
 
 struct auditstruct {
         const char *path;
@@ -61,6 +59,10 @@ static int bus_get_selinux_security_context(
                 DBusError *error) {
 
         _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+        DBusMessageIter iter, sub;
+        const char *bytes;
+        char *b;
+        int nbytes;
 
         m = dbus_message_new_method_call(
                         DBUS_SERVICE_DBUS,
@@ -87,12 +89,23 @@ static int bus_get_selinux_security_context(
         if (dbus_set_error_from_message(error, reply))
                 return -EIO;
 
-        if (!dbus_message_get_args(
-                            reply, error,
-                            DBUS_TYPE_STRING, scon,
-                            DBUS_TYPE_INVALID))
+        if (!dbus_message_iter_init(reply, &iter))
                 return -EIO;
 
+        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+                return -EIO;
+
+        dbus_message_iter_recurse(&iter, &sub);
+        dbus_message_iter_get_fixed_array(&sub, &bytes, &nbytes);
+
+        b = strndup(bytes, nbytes);
+        if (!b)
+                return -ENOMEM;
+
+        *scon = b;
+
+        log_debug("GetConnectionSELinuxSecurityContext %s (pid %ld)", *scon, (long) bus_get_unix_process_id(connection, name, error));
+
         return 0;
 }
 
@@ -169,11 +182,11 @@ static int log_callback(int type, const char *fmt, ...) {
         va_start(ap, fmt);
 
 #ifdef HAVE_AUDIT
-        if (audit_fd >= 0) {
+        if (get_audit_fd() >= 0) {
                 char buf[LINE_MAX];
 
                 vsnprintf(buf, sizeof(buf), fmt, ap);
-                audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
+                audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
                 va_end(ap);
 
                 return 0;
@@ -210,12 +223,9 @@ static int access_init(void) {
         return r;
 }
 
-static int selinux_init(Manager *m, DBusError *error) {
+static int selinux_access_init(DBusError *error) {
         int r;
 
-#ifdef HAVE_AUDIT
-        audit_fd = m->audit_fd;
-#endif
         if (initialized)
                 return 0;
 
@@ -231,6 +241,14 @@ static int selinux_init(Manager *m, DBusError *error) {
         return 0;
 }
 
+void selinux_access_free(void) {
+        if (!initialized)
+                return;
+
+        avc_destroy();
+        initialized = false;
+}
+
 static int get_audit_data(
                 DBusConnection *connection,
                 DBusMessage *message,
@@ -290,13 +308,17 @@ static int get_calling_context(
         */
         sender = dbus_message_get_sender(message);
         if (sender) {
+                log_error("SELinux Got Sender %s", sender);
+
                 r = bus_get_selinux_security_context(connection, sender, scon, error);
                 if (r >= 0)
                         return r;
 
-                log_debug("bus_get_selinux_security_context failed %m");
+                log_error("bus_get_selinux_security_context failed: %m");
+                return r;
         }
 
+        log_debug("SELinux No Sender");
         if (!dbus_connection_get_unix_fd(connection, &fd)) {
                 log_error("bus_connection_get_unix_fd failed %m");
                 return -EINVAL;
@@ -317,8 +339,7 @@ static int get_calling_context(
    If the machine is in permissive mode it will return ok.  Audit messages will
    still be generated if the access would be denied in enforcing mode.
 */
-static int selinux_access_check(
-                Manager *m,
+int selinux_access_check(
                 DBusConnection *connection,
                 DBusMessage *message,
                 const char *path,
@@ -330,19 +351,18 @@ static int selinux_access_check(
         const char *tclass = NULL;
         struct auditstruct audit;
 
-        assert(m);
         assert(connection);
         assert(message);
         assert(permission);
         assert(error);
 
-        r = selinux_init(m, error);
-        if (r < 0)
-                return r;
-
         if (!use_selinux())
                 return 0;
 
+        r = selinux_access_init(error);
+        if (r < 0)
+                return r;
+
         log_debug("SELinux access check for path=%s permission=%s", strna(path), permission);
 
         audit.uid = audit.loginuid = (uid_t) -1;
@@ -403,69 +423,19 @@ finish:
         return r;
 }
 
-int selinux_unit_access_check(
-                Unit *u,
-                DBusConnection *connection,
-                DBusMessage *message,
-                const char *permission,
-                DBusError *error) {
-
-        assert(u);
-        assert(connection);
-        assert(message);
-        assert(permission);
-        assert(error);
-
-        return selinux_access_check(u->manager, connection, message, u->source_path ? u->source_path : u->fragment_path, permission, error);
-}
-
-int selinux_manager_access_check(
-                Manager *m,
-                DBusConnection *connection,
-                DBusMessage *message,
-                const char *permission,
-                DBusError *error) {
-
-        assert(m);
-        assert(connection);
-        assert(message);
-        assert(permission);
-        assert(error);
-
-        return selinux_access_check(m, connection, message, NULL, permission, error);
-}
-
-void selinux_access_finish(void) {
-        if (!initialized)
-                return;
-
-        avc_destroy();
-        initialized = false;
-}
-
 #else
 
-int selinux_unit_access_check(
-                Unit *u,
-                DBusConnection *connection,
-                DBusMessage *message,
-                const char *permission,
-                DBusError *error) {
-
-        return 0;
-}
-
-int selinux_manager_access_check(
-                Manager *m,
+int selinux_access_check(
                 DBusConnection *connection,
                 DBusMessage *message,
+                const char *path,
                 const char *permission,
                 DBusError *error) {
 
         return 0;
 }
 
-void selinux_access_finish(void) {
+void selinux_access_free(void) {
 }
 
 #endif