diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-07-14 12:37:28 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-07-22 15:53:45 +0200 |
commit | 29206d4619843252c2e04f20dc03c246547600a2 (patch) | |
tree | a30c2f5b2e90f016c5ed46452ac27264f2afae1c /src/core/dbus-manager.c | |
parent | 66dccd8d85aac9f029c626aac8d2b7e58d239b47 (diff) |
core: add a concept of "dynamic" user ids, that are allocated as long as a service is running
This adds a new boolean setting DynamicUser= to service files. If set, a new
user will be allocated dynamically when the unit is started, and released when
it is stopped. The user ID is allocated from the range 61184..65519. The user
will not be added to /etc/passwd (but an NSS module to be added later should
make it show up in getent passwd).
For now, care should be taken that the service writes no files to disk, since
this might result in files owned by UIDs that might get assigned dynamically to
a different service later on. Later patches will tighten sandboxing in order to
ensure that this cannot happen, except for a few selected directories.
A simple way to test this is:
systemd-run -p DynamicUser=1 /bin/sleep 99999
Diffstat (limited to 'src/core/dbus-manager.c')
-rw-r--r-- | src/core/dbus-manager.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index d05968bd65..ef05a75a8b 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -43,6 +43,7 @@ #include "string-util.h" #include "strv.h" #include "syslog-util.h" +#include "user-util.h" #include "virt.h" #include "watchdog.h" @@ -1511,8 +1512,8 @@ static int method_unset_and_set_environment(sd_bus_message *message, void *userd } static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) { - uint8_t code; Manager *m = userdata; + uint8_t code; int r; assert(message); @@ -1534,6 +1535,61 @@ static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_ return sd_bus_reply_method_return(message, NULL); } +static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + uid_t uid; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read_basic(message, 's', &name); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + if (!valid_user_group_name(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name); + + r = dynamic_user_lookup_name(m, name, &uid); + if (r == -ESRCH) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user %s does not exist.", name); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "u", (uint32_t) uid); +} + +static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *name = NULL; + Manager *m = userdata; + uid_t uid; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(uid) == sizeof(uint32_t)); + r = sd_bus_message_read_basic(message, 'u', &uid); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User ID invalid: " UID_FMT, uid); + + r = dynamic_user_lookup_uid(m, uid, &name); + if (r == -ESRCH) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user ID " UID_FMT " does not exist.", uid); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", name); +} + static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; @@ -2199,6 +2255,8 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("UnitNew", "so", 0), SD_BUS_SIGNAL("UnitRemoved", "so", 0), |