Add new SELinux permissions `modify` and `listdynusers` to the class `service`. - modfiy checks altering operations, like `systemctl log-level debug` or `systemctl add-wants foo bar`. - listdynusers checks obtaining dynamic users, which is very common on systems using nss-systemd. Add a new permission to avoid undermining the `status` permission. Perform SELinux access checks for the following D-Bus exposed methods: D-Bus interface | c function name | SELinux permission verb GetAfter / GetBefore | bus_job_method_get_waiting_jobs | status LogTarget | property_set_log_target | modify LogLevel | property_set_log_level | modify RuntimeWatchdocUSec | property_set_runtime_watchdog | modify ServiceWatchdogs | bus_property_set_bool_wrapper | modify GetUnit | method_get_unit | status GetUnitByPID | method_get_unit_by_pid | status GetUnitByControlGroup | method_get_unit_by_control_group | status LoadUnit | method_load_unit | status ListUnitsByNames | method_list_units_by_names | status LookupDynamicUserByName | method_lookup_dynamic_user_by_name | listdynusers LookupDynamicUserByUID | method_lookup_dynamic_user_by_uid | listdynusers GetDynamicUsers | method_get_dynamic_users | listdynusers AddDependencyUnitFiles | method_add_dependency_unit_files | modify GetUnitFileLinks | method_get_unit_file_links | status Unref | bus_unit_method_unref | modify --- src/core/dbus-job.c | 4 ++ src/core/dbus-manager.c | 89 ++++++++++++++++++++++++++++++++++++----- src/core/dbus-unit.c | 4 ++ 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index a7d342257b..7b0b093757 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -71,6 +71,10 @@ int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_ Job *j = userdata; int r, i, n; + r = mac_selinux_unit_access_check(j->unit, message, "status", error); + if (r < 0) + return r; + if (strstr(sd_bus_message_get_member(message), "After")) n = job_get_after(j, &list); else diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index c751e84253..d2db6e4a61 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -121,6 +121,10 @@ static int property_set_log_target( assert(bus); assert(value); + r = mac_selinux_access_check(value, "modify", error); + if (r < 0) + return r; + r = sd_bus_message_read(value, "s", &t); if (r < 0) return r; @@ -178,6 +182,10 @@ static int property_set_log_level( assert(bus); assert(value); + r = mac_selinux_access_check(value, "modify", error); + if (r < 0) + return r; + r = sd_bus_message_read(value, "s", &t); if (r < 0) return r; @@ -282,6 +290,10 @@ static int property_set_runtime_watchdog( assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + r = mac_selinux_access_check(value, "modify", error); + if (r < 0) + return r; + r = sd_bus_message_read(value, "t", t); if (r < 0) return r; @@ -289,6 +301,24 @@ static int property_set_runtime_watchdog( return watchdog_set_timeout(t); } +static int bus_property_set_bool_wrapper( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + int r; + + r = mac_selinux_access_check(value, "modify", error); + if (r < 0) + return r; + + return bus_property_set_bool(bus, path, interface, property, value, userdata, error); +} + static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) { Unit *u; int r; @@ -375,6 +405,10 @@ static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error if (r < 0) return r; + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + return reply_unit_path(u, message, error); } @@ -413,6 +447,10 @@ static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bu if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid); + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + return reply_unit_path(u, message, error); } @@ -488,6 +526,10 @@ static int method_get_unit_by_control_group(sd_bus_message *message, void *userd if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup); + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + return reply_unit_path(u, message, error); } @@ -510,6 +552,10 @@ static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_erro if (r < 0) return r; + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + return reply_unit_path(u, message, error); } @@ -529,6 +575,7 @@ static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobTyp if (r < 0) return r; + /* bus_unit_method_start_generic() includes a mac_selinux check */ return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error); } @@ -703,6 +750,10 @@ static int method_list_units_by_names(sd_bus_message *message, void *userdata, s assert(message); assert(m); + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + r = sd_bus_message_read_strv(message, &units); if (r < 0) return r; @@ -1263,11 +1314,11 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error * assert(message); assert(m); - r = verify_run_space("Refusing to reload", error); + r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; - r = mac_selinux_access_check(message, "reload", error); + r = verify_run_space("Refusing to reload", error); if (r < 0) return r; @@ -1299,11 +1350,11 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro assert(message); assert(m); - r = verify_run_space("Refusing to reexecute", error); + r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; - r = mac_selinux_access_check(message, "reload", error); + r = verify_run_space("Refusing to reexecute", error); if (r < 0) return r; @@ -1428,6 +1479,10 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er assert(message); assert(m); + r = mac_selinux_access_check(message, "reboot", error); + if (r < 0) + return r; + if (statvfs("/run/systemd", &svfs) < 0) return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m"); @@ -1441,10 +1496,6 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN)); } - r = mac_selinux_access_check(message, "reboot", error); - if (r < 0) - return r; - if (!MANAGER_IS_SYSTEM(m)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager."); @@ -1636,6 +1687,10 @@ static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *use assert(message); assert(m); + r = mac_selinux_access_check(message, "listdynusers", error); + if (r < 0) + return r; + r = sd_bus_message_read_basic(message, 's', &name); if (r < 0) return r; @@ -1663,6 +1718,10 @@ static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *user assert(message); assert(m); + r = mac_selinux_access_check(message, "listdynusers", error); + if (r < 0) + return r; + assert_cc(sizeof(uid) == sizeof(uint32_t)); r = sd_bus_message_read_basic(message, 'u', &uid); if (r < 0) @@ -1692,6 +1751,10 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_ assert(message); assert(m); + r = mac_selinux_access_check(message, "listdynusers", error); + if (r < 0) + return r; + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); if (!MANAGER_IS_SYSTEM(m)) @@ -2264,6 +2327,10 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd assert(message); assert(m); + r = mac_selinux_access_check(message, "modify", error); + if (r < 0) + return r; + r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; @@ -2300,6 +2367,10 @@ static int method_get_unit_file_links(sd_bus_message *message, void *userdata, s char **p; int runtime, r; + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + r = sd_bus_message_read(message, "sb", &name, &runtime); if (r < 0) return r; @@ -2422,7 +2493,7 @@ const sd_bus_vtable bus_manager_vtable[] = { /* The following item is an obsolete alias */ SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), SD_BUS_VTABLE_HIDDEN), SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0), - SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0), + SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool_wrapper, offsetof(Manager, service_watchdogs), 0), SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0), SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0), SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 9477c47140..f86efaac3a 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -645,6 +645,10 @@ int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error assert(message); assert(u); + r = mac_selinux_unit_access_check(u, message, "modify", error); + if (r < 0) + return r; + r = bus_unit_track_remove_sender(u, message); if (r == -EUNATCH) return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet."); -- 2.24.1