core: Verify systemd1 DBus method callers via polkit
DBus methods that retrieve information can be called by anyone. DBus methods that modify state of units are verified via polkit action: org.freedesktop.systemd1.manage-units DBus methods that modify state of unit files are verified via polkit action: org.freedesktop.systemd1.manage-unit-files DBus methods that reload the entire daemon state are verified via polkit action: org.freedesktop.systemd1.reload-daemon DBus methods that modify job state are callable from the clients that started the job. root (ie: CAP_SYS_ADMIN) can continue to perform all calls, property access etc. There are several DBus methods that can only be called by root. Open up the dbus1 policy for the above methods. (Heavily modified by Lennart, making use of the new bus_verify_polkit_async() version that doesn't force us to always pass the original callback around. Also, interactive auhentication must be opt-in, not unconditional, hence I turned this off.)
This commit is contained in:
parent
f38857914a
commit
283868e1dc
|
@ -29,6 +29,23 @@
|
|||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
|
||||
|
||||
static int verify_sys_admin_or_owner_sync(sd_bus_message *message, Job *j, sd_bus_error *error) {
|
||||
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
|
||||
int r;
|
||||
|
||||
if (sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message)))
|
||||
return 0; /* One of the job owners is calling us */
|
||||
|
||||
r = sd_bus_query_sender_privilege(message, CAP_SYS_ADMIN);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access denied to perform action");
|
||||
|
||||
/* Root has called us */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int property_get_unit(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
|
@ -60,6 +77,10 @@ int bus_job_method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata,
|
|||
assert(message);
|
||||
assert(j);
|
||||
|
||||
r = verify_sys_admin_or_owner_sync(message, j, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = selinux_unit_access_check(j->unit, message, "stop", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -71,7 +92,7 @@ int bus_job_method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata,
|
|||
|
||||
const sd_bus_vtable bus_job_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, 0),
|
||||
SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
|
|
@ -353,6 +353,8 @@ static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata,
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -385,6 +387,8 @@ static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *us
|
|||
|
||||
assert_cc(sizeof(pid_t) == sizeof(uint32_t));
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = sd_bus_message_read(message, "u", &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -427,6 +431,8 @@ static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -455,6 +461,12 @@ static int method_start_unit_generic(sd_bus *bus, sd_bus_message *message, Manag
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -504,6 +516,12 @@ static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &old_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -525,6 +543,13 @@ static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Like bus_verify_manage_unit_async(), but uses CAP_SYS_KILL */
|
||||
r = bus_verify_manage_unit_async_for_kill(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -546,6 +571,12 @@ static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -567,6 +598,12 @@ static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -590,6 +627,12 @@ static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, voi
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "ss", &name, &smode);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -649,6 +692,8 @@ static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata,
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = sd_bus_message_read(message, "u", &id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -735,6 +780,8 @@ static int list_units_filtered(sd_bus *bus, sd_bus_message *message, void *userd
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -821,6 +868,8 @@ static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -871,6 +920,8 @@ static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -904,6 +955,8 @@ static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userda
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -930,6 +983,8 @@ static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1019,6 +1074,12 @@ static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, s
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_reload_daemon_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = selinux_access_check(message, "reload", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1047,6 +1108,12 @@ static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_reload_daemon_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = selinux_access_check(message, "reload", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1322,6 +1389,8 @@ static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *us
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1373,6 +1442,8 @@ static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1400,6 +1471,8 @@ static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Anyone can call this method */
|
||||
|
||||
r = selinux_access_check(message, "status", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1501,6 +1574,12 @@ static int method_enable_unit_files_generic(
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read_strv(message, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1573,6 +1652,12 @@ static int method_preset_unit_files_with_mode(sd_bus *bus, sd_bus_message *messa
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read_strv(message, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1629,6 +1714,12 @@ static int method_disable_unit_files_generic(
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = selinux_access_check(message, verb, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1670,6 +1761,12 @@ static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = selinux_access_check(message, "enable", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1700,6 +1797,12 @@ static int method_preset_all_unit_files(sd_bus *bus, sd_bus_message *message, vo
|
|||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = selinux_access_check(message, "enable", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1767,20 +1870,20 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
|||
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
|
||||
SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
|
||||
SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
|
||||
SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
|
||||
SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
|
||||
SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
|
||||
SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
|
||||
SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
|
||||
SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
||||
SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
|
||||
SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, 0),
|
||||
SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
|
||||
SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
|
||||
SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
|
||||
SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
|
||||
SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
@ -1791,8 +1894,8 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
|||
SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
|
||||
SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
|
||||
SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
|
||||
SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
|
||||
SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
|
||||
SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
|
||||
SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
|
||||
|
@ -1804,17 +1907,17 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
|||
SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
|
||||
SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
|
||||
SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
|
||||
SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
|
||||
SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
|
||||
SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
|
||||
SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, 0),
|
||||
SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
|
||||
SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
|
||||
SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
|
||||
SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, 0),
|
||||
SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
||||
SD_BUS_SIGNAL("UnitNew", "so", 0),
|
||||
SD_BUS_SIGNAL("UnitRemoved", "so", 0),
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "dbus-cgroup.h"
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-scope.h"
|
||||
#include "dbus.h"
|
||||
#include "bus-util.h"
|
||||
#include "bus-internal.h"
|
||||
#include "bus-errors.h"
|
||||
|
@ -37,6 +38,12 @@ static int bus_scope_abandon(sd_bus *bus, sd_bus_message *message, void *userdat
|
|||
assert(message);
|
||||
assert(s);
|
||||
|
||||
r = bus_verify_manage_unit_async(UNIT(s)->manager, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = scope_abandon(s);
|
||||
if (sd_bus_error_is_set(error))
|
||||
return r;
|
||||
|
|
|
@ -421,6 +421,12 @@ int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, s
|
|||
assert(message);
|
||||
assert(u);
|
||||
|
||||
r = bus_verify_manage_unit_async_for_kill(u->manager, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "si", &swho, &signo);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -455,6 +461,12 @@ int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *use
|
|||
assert(message);
|
||||
assert(u);
|
||||
|
||||
r = bus_verify_manage_unit_async(u->manager, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = selinux_unit_access_check(u, message, "reload", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -472,6 +484,12 @@ int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *u
|
|||
assert(message);
|
||||
assert(u);
|
||||
|
||||
r = bus_verify_manage_unit_async(u->manager, message, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
r = sd_bus_message_read(message, "b", &runtime);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
|
|
@ -1092,6 +1092,8 @@ void bus_done(Manager *m) {
|
|||
m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
|
||||
|
||||
m->private_listen_fd = safe_close(m->private_listen_fd);
|
||||
|
||||
bus_verify_polkit_async_registry_free(m->polkit_registry);
|
||||
}
|
||||
|
||||
int bus_fdset_add_all(Manager *m, FDSet *fds) {
|
||||
|
@ -1215,3 +1217,20 @@ int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
|
|||
|
||||
return r;
|
||||
}
|
||||
|
||||
int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
|
||||
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
|
||||
}
|
||||
|
||||
/* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
|
||||
int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
|
||||
return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
|
||||
}
|
||||
|
||||
int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
|
||||
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, &m->polkit_registry, error);
|
||||
}
|
||||
|
||||
int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
|
||||
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, &m->polkit_registry, error);
|
||||
}
|
||||
|
|
|
@ -35,3 +35,8 @@ int bus_track_deserialize_item(char ***l, const char *line);
|
|||
int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l);
|
||||
|
||||
int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
|
||||
|
||||
int bus_verify_manage_unit_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
|
||||
int bus_verify_manage_unit_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error);
|
||||
int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
|
||||
int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
|
||||
|
|
|
@ -276,6 +276,9 @@ struct Manager {
|
|||
|
||||
/* Reference to the kdbus bus control fd */
|
||||
int kdbus_fd;
|
||||
|
||||
/* Used for processing polkit authorization responses */
|
||||
Hashmap *polkit_registry;
|
||||
};
|
||||
|
||||
int manager_new(SystemdRunningAs running_as, bool test_run, Manager **m);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
<policy context="default">
|
||||
<deny send_destination="org.freedesktop.systemd1"/>
|
||||
|
||||
<!-- Completely open to anyone -->
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||
|
||||
|
@ -94,6 +96,112 @@
|
|||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="GetDefaultTarget"/>
|
||||
|
||||
<!-- Managed via polkit or other criteria -->
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="StartUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="StartUnitReplace"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="StopUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="ReloadUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="RestartUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="TryRestartUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="ReloadOrRestartUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="ReloadOrTryRestartUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="KillUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="ResetFailedUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="SetUnitProperties"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="StartTransientUnit"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="CancelJob"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="Reload"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="Reexecute"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="EnableUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="DisableUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="ReenableUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="LinkUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="PresetUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="PresetUnitFilesWithMode"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="MaskUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="UnmaskUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="SetDefaultTarget"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Manager"
|
||||
send_member="PresetAllUnitFiles"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.systemd1"
|
||||
send_interface="org.freedesktop.systemd1.Job"
|
||||
send_member="Cancel"/>
|
||||
|
||||
<allow receive_sender="org.freedesktop.systemd1"/>
|
||||
</policy>
|
||||
|
||||
|
|
|
@ -38,4 +38,34 @@
|
|||
<annotate key="org.freedesktop.policykit.exec.path">@bindir@/systemd-stdio-bridge</annotate>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.systemd1.manage-units">
|
||||
<_description>Manage system services or units</_description>
|
||||
<_message>Authentication is required to manage system services or units.</_message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.systemd1.manage-unit-files">
|
||||
<_description>Manage system service or unit files</_description>
|
||||
<_message>Authentication is required to manage system service or unit files.</_message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.systemd1.reload-daemon">
|
||||
<_description>Reload the systemd state</_description>
|
||||
<_message>Authentication is required to reload the systemd state.</_message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
|
|
Loading…
Reference in a new issue