X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fselinux-access.c;h=8513634f965bc9758d4e7d32cb8ed79d155545f0;hb=7f1736f73619fcadcb974640dc1052aa0c654850;hp=30eab68336b76f41c7e2b9005ecb10d26099a093;hpb=e2417e4143bb892e4599b01de7b031763421bb64;p=elogind.git diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 30eab6833..8513634f9 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -1,4 +1,3 @@ - /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*** @@ -31,6 +30,7 @@ #include "dbus-unit.h" #include "bus-errors.h" #include "dbus-common.h" +#include "audit.h" #include #include @@ -65,79 +65,77 @@ struct auditstruct { check will be called. */ -static const char * const unit_methods[][2] = {{ "DisableUnitFiles", "disable" }, - { "EnableUnitFiles", "enable" }, - { "GetUnit", "status" }, - { "GetUnitFileState", "status" }, - { "Kill", "stop" }, - { "KillUnit", "stop" }, - { "LinkUnitFiles", "enable" }, - { "MaskUnitFiles", "disable" }, - { "PresetUnitFiles", "enable" }, - { "ReenableUnitFiles", "enable" }, - { "Reexecute", "start" }, - { "ReloadOrRestart", "start" }, - { "ReloadOrRestartUnit", "start" }, - { "ReloadOrTryRestart", "start" }, - { "ReloadOrTryRestartUnit", "start" }, - { "ReloadUnit", "reload" }, - { "ResetFailedUnit", "stop" }, - { "Restart", "start" }, - { "RestartUnit", "start" }, - { "Start", "start" }, - { "StartUnit", "start" }, - { "StartUnitReplace", "start" }, - { "Stop", "stop" }, - { "StopUnit", "stop" }, - { "TryRestart", "start" }, - { "TryRestartUnit", "start" }, - { "UnmaskUnitFiles", "enable" }, - { NULL, NULL } -}; - -static const char * const system_methods[][2] = { { "ClearJobs", "reboot" }, - { "CreateSnapshot", "status" }, - { "Dump", "status" }, - { "Exit", "halt" }, - { "FlushDevices", "halt" }, - { "Get", "status" }, - { "GetAll", "status" }, - { "GetJob", "status" }, - { "GetSeat", "status" }, - { "GetSession", "status" }, - { "GetSessionByPID", "status" }, - { "GetUnitByPID", "status" }, - { "GetUser", "status" }, - { "Halt", "halt" }, - { "Introspect", "status" }, - { "KExec", "reboot" }, - { "KillSession", "halt" }, - { "KillUser", "halt" }, - { "LoadUnit", "reload" }, - { "ListJobs", "status" }, - { "ListSeats", "status" }, - { "ListSessions", "status" }, - { "ListUnits", "status" }, - { "ListUnitFiles", "status" }, - { "ListUsers", "status" }, - { "LockSession", "halt" }, - { "PowerOff", "halt" }, - { "Reboot", "reboot" }, - { "Reload", "reload" }, - { "Reexecute", "reload" }, - { "ResetFailed", "reload" }, - { "Subscribe", "status" }, - { "SwithcRoot", "reboot" }, - { "SetEnvironment", "status" }, - { "SetUserLinger", "halt" }, - { "TerminateSeat", "halt" }, - { "TerminateSession", "halt" }, - { "TerminateUser", "halt" }, - { "Unsubscribe", "status" }, - { "UnsetEnvironment", "status" }, - { "UnsetAndSetEnvironment", "status" }, - { NULL, NULL } -}; +static const char unit_methods[] = + "DisableUnitFiles\0" "disable\0" + "EnableUnitFiles\0" "enable\0" + "GetUnit\0" "status\0" + "GetUnitFileState\0" "status\0" + "Kill\0" "stop\0" + "KillUnit\0" "stop\0" + "LinkUnitFiles\0" "enable\0" + "MaskUnitFiles\0" "disable\0" + "PresetUnitFiles\0" "enable\0" + "ReenableUnitFiles\0" "enable\0" + "ReloadOrRestart\0" "start\0" + "ReloadOrRestartUnit\0" "start\0" + "ReloadOrTryRestart\0" "start\0" + "ReloadOrTryRestartUnit\0" "start\0" + "Reload\0" "reload\0" + "ReloadUnit\0" "reload\0" + "ResetFailedUnit\0" "stop\0" + "Restart\0" "start\0" + "RestartUnit\0" "start\0" + "Start\0" "start\0" + "StartUnit\0" "start\0" + "StartUnitReplace\0" "start\0" + "Stop\0" "stop\0" + "StopUnit\0" "stop\0" + "TryRestart\0" "start\0" + "TryRestartUnit\0" "start\0" + "UnmaskUnitFiles\0" "enable\0"; + +static const char system_methods[] = + "ClearJobs\0" "reboot\0" + "CreateSnapshot\0" "status\0" + "Dump\0" "status\0" + "Exit\0" "halt\0" + "FlushDevices\0" "halt\0" + "Get\0" "status\0" + "GetAll\0" "status\0" + "GetJob\0" "status\0" + "GetSeat\0" "status\0" + "GetSession\0" "status\0" + "GetSessionByPID\0" "status\0" + "GetUnitByPID\0" "status\0" + "GetUser\0" "status\0" + "Halt\0" "halt\0" + "Introspect\0" "status\0" + "KExec\0" "reboot\0" + "KillSession\0" "halt\0" + "KillUser\0" "halt\0" + "LoadUnit\0" "reload\0" + "ListJobs\0" "status\0" + "ListSeats\0" "status\0" + "ListSessions\0" "status\0" + "ListUnits\0" "status\0" + "ListUnitFiles\0" "status\0" + "ListUsers\0" "status\0" + "LockSession\0" "halt\0" + "PowerOff\0" "halt\0" + "Reboot\0" "reboot\0" + "Reload\0" "reload\0" + "Reexecute\0" "reload\0" + "ResetFailed\0" "reload\0" + "Subscribe\0" "status\0" + "SwithcRoot\0" "reboot\0" + "SetEnvironment\0" "status\0" + "SetUserLinger\0" "halt\0" + "TerminateSeat\0" "halt\0" + "TerminateSession\0" "halt\0" + "TerminateUser\0" "halt\0" + "Unsubscribe\0" "status\0" + "UnsetEnvironment\0" "status\0" + "UnsetAndSetEnvironment\0" "status\0"; /* If the admin toggles the selinux enforcment mode this callback @@ -212,49 +210,6 @@ finish: return r; } -static int get_cmdline(pid_t pid, char **cmdline) { - char buf[PATH_MAX]; - FILE *f; - int count; - int n; - - snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid); - f = fopen(buf, "re"); - if (!f) { - return -errno; - } - count = fread(buf, 1, sizeof(buf), f); - fclose(f); - if (! count) { - return -errno; - } - for (n = 0; n < count - 1; n++) - { - if (buf[n] == '\0') - buf[n] = ' '; - } - (*cmdline) = strdup(buf); - if (! (*cmdline)) { - return -errno; - } - return 0; -} - -static int get_pid_id(pid_t pid, const char *file, uid_t *id) { - char buf[PATH_MAX]; - int r = 0; - FILE *f; - snprintf(buf, sizeof(buf), "/proc/%lu/%s", (unsigned long) pid, file); - f = fopen(buf, "re"); - if (!f) - return -errno; - fscanf(f, "%d", id); - if (ferror(f)) - r = -errno; - fclose(f); - return r; -} - /* This mimics dbus_bus_get_unix_user() */ static int bus_get_audit_data( DBusConnection *connection, @@ -263,74 +218,29 @@ static int bus_get_audit_data( DBusError *error) { pid_t pid; - DBusMessage *m = NULL, *reply = NULL; - int r = -1; - - m = dbus_message_new_method_call( - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "GetConnectionUnixProcessID"); - if (!m) { - r = -errno; - dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL); - goto finish; - } - - r = dbus_message_append_args( - m, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - if (!r) { - r = -errno; - dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL); - goto finish; - } - - reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error); - if (!reply) { - r = -errno; - goto finish; - } - - r = dbus_set_error_from_message(error, reply); - if (!r) { - r = -errno; - goto finish; - } + int r; - r = dbus_message_get_args( - reply, error, - DBUS_TYPE_UINT32, &pid, - DBUS_TYPE_INVALID); - if (!r) { - r = -errno; - goto finish; - } + pid = bus_get_unix_process_id(connection, name, error); + if (pid <= 0) + return -EINVAL; - r = get_pid_id(pid, "loginuid", &(audit->loginuid)); - if (r) - goto finish; + r = audit_loginuid_from_pid(pid, &audit->loginuid); + if (r < 0) + return r; - r = get_pid_id(pid, "uid", &(audit->uid)); - if (r) - goto finish; + r = get_process_uid(pid, &audit->uid); + if (r < 0) + return r; - r = get_pid_id(pid, "gid", &(audit->gid)); - if (r) - goto finish; + r = get_process_gid(pid, &audit->gid); + if (r < 0) + return r; - r = get_cmdline(pid, &(audit->cmdline)); - if (r) - goto finish; + r = get_process_cmdline(pid, LINE_MAX, true, &audit->cmdline); + if (r < 0) + return r; - r = 0; -finish: - if (m) - dbus_message_unref(m); - if (reply) - dbus_message_unref(reply); - return r; + return 0; } /* @@ -366,6 +276,7 @@ static int log_callback(int type, const char *fmt, ...) vsnprintf(buf, sizeof(buf), fmt, ap); audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0); + va_end(ap); return 0; } #endif @@ -435,49 +346,38 @@ static int get_audit_data( DBusError *error) { const char *sender; - int r = -1; + int r; sender = dbus_message_get_sender(message); - if (sender) { - r = bus_get_audit_data( - connection, - sender, - audit, - error); - if (r) - goto finish; - } else { + if (sender) + return bus_get_audit_data(connection, sender, audit, error); + else { int fd; struct ucred ucred; socklen_t len; - r = dbus_connection_get_unix_fd(connection, &fd); - if (!r) { - r = -EINVAL; - goto finish; - } + + if (!dbus_connection_get_unix_fd(connection, &fd)) + return -EINVAL; r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len); if (r < 0) { - r = -errno; log_error("Failed to determine peer credentials: %m"); - goto finish; + return -errno; } + audit->uid = ucred.uid; audit->gid = ucred.gid; - r = get_pid_id(ucred.pid, "loginuid", &(audit->loginuid)); - if (r) - goto finish; - - r = get_cmdline(ucred.pid, &(audit->cmdline)); - if (r) - goto finish; - } + r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid); + if (r < 0) + return r; - r = 0; + r = get_process_cmdline(ucred.pid, LINE_MAX, true, &audit->cmdline); + if (r < 0) + return r; -finish: - return r; + return 0; + } } /* @@ -521,32 +421,25 @@ static int get_calling_context( This function returns the SELinux permission to check and whether or not the check requires a unit file. */ -static void selinux_perm_lookup(const char *method, const char **perm, int *require_unit) -{ - int i; - *require_unit = -1; - - for (i = 0; unit_methods[i][0]; i++) { - if (streq(method, unit_methods[i][0])) { - *perm = unit_methods[i][1]; - *require_unit = 1; - break; +static void selinux_perm_lookup(const char *method, const char **perm, bool *require_unit) { + const char *m, *p; + + NULSTR_FOREACH_PAIR(m, p, unit_methods) + if (streq(method, m)) { + *perm = p; + *require_unit = true; + return; } - } - if (*require_unit < 0) { - for (i = 0; system_methods[i][0]; i++) { - if (streq(method, system_methods[i][0])) { - *perm = system_methods[i][1]; - *require_unit = 0; - break; - } + NULSTR_FOREACH_PAIR(m, p, system_methods) + if (streq(method, m)) { + *perm = p; + *require_unit = false; + return; } - } - if (*require_unit < 0) { - *require_unit = 0; - *perm = "undefined"; - } + + *require_unit = false; + *perm = "undefined"; } /* @@ -561,7 +454,9 @@ static int selinux_access_check(DBusConnection *connection, DBusMessage *message int r = 0; const char *tclass = NULL; struct auditstruct audit; - audit.uid = audit.loginuid = audit.gid = -1; + + audit.uid = audit.loginuid = (uid_t) -1; + audit.gid = (gid_t) -1; audit.cmdline = NULL; audit.path = path; @@ -589,9 +484,9 @@ static int selinux_access_check(DBusConnection *connection, DBusMessage *message (void) get_audit_data(connection, message, &audit, error); - errno=0; + errno= 0; r = selinux_check_access(scon, fcon, tclass, perm, &audit); - if ( r < 0) { + if (r < 0) { r = -errno; log_error("SELinux Denied \"%s\"", audit.cmdline); @@ -621,22 +516,24 @@ void selinux_access_finish(void) { int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error) { const char *perm; - int require_unit; - const char *member = dbus_message_get_member(message); + bool require_unit; + const char *member; int r; r = selinux_init(m, error); - if (r) + if (r < 0) return r; if (! selinux_enabled) return 0; + member = dbus_message_get_member(message); + selinux_perm_lookup(member, &perm, &require_unit); log_debug("SELinux dbus-unit Look %s up perm %s require_unit %d", member, perm, require_unit); r = selinux_access_check(connection, message, m, error, perm, path); - if ((r < 0) && (!selinux_enforcing)) { + if (r < 0 && !selinux_enforcing) { dbus_error_init(error); r = 0; } @@ -647,12 +544,12 @@ int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, int selinux_manager_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, DBusError *error) { int r = -1; const char *member; - int require_unit; + bool require_unit; const char *perm; char *path = NULL; r = selinux_init(m, error); - if (r) + if (r < 0) return r; if (! selinux_enabled) @@ -667,24 +564,22 @@ int selinux_manager_access_check(DBusConnection *connection, DBusMessage *messag const char *name; Unit *u; - r = dbus_message_get_args( + if (!dbus_message_get_args( message, error, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - if (!r) + DBUS_TYPE_INVALID)) { + r = -EINVAL; goto finish; + } - u = manager_get_unit(m, name); - if ( !u ) { - if ((r = manager_load_unit(m, name, NULL, error, &u)) < 0) { - r = -errno; - dbus_set_error(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name); - goto finish; - } + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) { + dbus_set_error(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name); + goto finish; } - path = (u->fragment_path ? u->fragment_path: u->source_path); + path = u->source_path ? u->source_path : u->fragment_path; } r = selinux_access_check(connection, message, m, error, perm, path); @@ -706,5 +601,6 @@ int selinux_manager_access_check(DBusConnection *connection, DBusMessage *messag return 0; } -void selinux_access_finish(void) {} +void selinux_access_finish(void) { +} #endif