From: Ivan Kruglov Date: Thu, 7 Nov 2024 09:39:41 +0000 (+0100) Subject: machine: introduce io.systemd.Machine.{MapFrom, MapTo} methods X-Git-Tag: v258-rc1~1835^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8351463f676a281437f1eb3f8b99d74adff3b817;p=thirdparty%2Fsystemd.git machine: introduce io.systemd.Machine.{MapFrom, MapTo} methods --- diff --git a/src/machine/machine-varlink.c b/src/machine/machine-varlink.c index 8ad3c874691..1d2814b26a3 100644 --- a/src/machine/machine-varlink.c +++ b/src/machine/machine-varlink.c @@ -570,3 +570,161 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met return sd_varlink_reply(link, v); } + +typedef struct MachineMapParameters { + const char *name; + PidRef pidref; + uid_t uid; + gid_t gid; +} MachineMapParameters; + +static void machine_map_paramaters_done(MachineMapParameters *p) { + assert(p); + pidref_done(&p->pidref); +} + +int vl_method_map_from(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + static const sd_json_dispatch_field dispatch_table[] = { + VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(MachineOpenParameters), + { "uid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uid_gid, offsetof(MachineMapParameters, uid), 0 }, + { "gid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uid_gid, offsetof(MachineMapParameters, gid), 0 }, + {} + }; + + Manager *manager = ASSERT_PTR(userdata); + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + _cleanup_(machine_map_paramaters_done) MachineMapParameters p = { + .pidref = PIDREF_NULL, + .uid = UID_INVALID, + .gid = GID_INVALID, + }; + uid_t converted_uid = UID_INVALID; + gid_t converted_gid = GID_INVALID; + Machine *machine; + int r; + + assert(link); + assert(parameters); + + r = sd_varlink_dispatch(link, parameters, dispatch_table, &p); + if (r != 0) + return r; + + if (p.uid != UID_INVALID && !uid_is_valid(p.uid)) + return sd_varlink_error_invalid_parameter_name(link, "uid"); + + if (p.gid != GID_INVALID && !gid_is_valid(p.gid)) + return sd_varlink_error_invalid_parameter_name(link, "gid"); + + r = lookup_machine_by_name_or_pidref(link, manager, p.name, &p.pidref, &machine); + if (r == -ESRCH) + return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL); + if (r < 0) + return r; + + if (machine->class != MACHINE_CONTAINER) + return sd_varlink_error(link, "io.systemd.Machine.NotSupported", NULL); + + if (p.uid != UID_INVALID) { + r = machine_translate_uid(machine, p.uid, &converted_uid); + if (r == -ESRCH) + return sd_varlink_error(link, "io.systemd.Machine.NoSuchUser", NULL); + if (r < 0) + return log_debug_errno(r, "Failed to map uid=%u for machine '%s': %m", p.uid, machine->name); + } + + if (p.gid != UID_INVALID) { + r = machine_translate_gid(machine, p.gid, &converted_gid); + if (r == -ESRCH) + return sd_varlink_error(link, "io.systemd.Machine.NoSuchGroup", NULL); + if (r < 0) + return log_debug_errno(r, "Failed to map gid=%u for machine '%s': %m", p.gid, machine->name); + } + + r = sd_json_buildo(&v, + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("uid", converted_uid, UID_INVALID), + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("gid", converted_gid, GID_INVALID)); + if (r < 0) + return r; + + return sd_varlink_reply(link, v); +} + +int vl_method_map_to(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + static const sd_json_dispatch_field dispatch_table[] = { + { "uid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uid_gid, offsetof(MachineMapParameters, uid), 0 }, + { "gid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uid_gid, offsetof(MachineMapParameters, gid), 0 }, + {} + }; + + Manager *manager = ASSERT_PTR(userdata); + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + _cleanup_(machine_map_paramaters_done) MachineMapParameters p = { + .pidref = PIDREF_NULL, + .uid = UID_INVALID, + .gid = GID_INVALID, + }; + Machine *machine_by_uid = NULL, *machine_by_gid = NULL; + uid_t converted_uid = UID_INVALID; + gid_t converted_gid = GID_INVALID; + const char *machine_name = NULL; + int r; + + assert(link); + assert(parameters); + + r = sd_varlink_dispatch(link, parameters, dispatch_table, &p); + if (r != 0) + return r; + + if (p.uid != UID_INVALID) { + if (!uid_is_valid(p.uid)) + return sd_varlink_error_invalid_parameter_name(link, "uid"); + if (p.uid < 0x10000) + return sd_varlink_error(link, "io.systemd.Machine.UserInHostRange", NULL); + } + + if (p.gid != GID_INVALID) { + if (!gid_is_valid(p.gid)) + return sd_varlink_error_invalid_parameter_name(link, "gid"); + if (p.gid < 0x10000) + return sd_varlink_error(link, "io.systemd.Machine.GroupInHostRange", NULL); + } + + if (p.uid != UID_INVALID) { + r = manager_find_machine_for_uid(manager, p.uid, &machine_by_uid, &converted_uid); + if (r < 0) + return log_debug_errno(r, "Failed to find machine for uid=%u: %m", p.uid); + if (!r) + return sd_varlink_error(link, "io.systemd.Machine.NoSuchUser", NULL); + } + + if (p.gid != GID_INVALID) { + r = manager_find_machine_for_gid(manager, p.gid, &machine_by_gid, &converted_gid); + if (r < 0) + return log_debug_errno(r, "Failed to find machine for gid=%u: %m", p.gid); + if (!r) + return sd_varlink_error(link, "io.systemd.Machine.NoSuchGroup", NULL); + } + + if (machine_by_uid && machine_by_gid && machine_by_uid != machine_by_gid) { + log_debug_errno(SYNTHETIC_ERRNO(ESRCH), "Mapping of UID %u and GID %u resulted in two different machines", p.uid, p.gid); + return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL); + } + + if (machine_by_uid) + machine_name = machine_by_uid->name; + else if (machine_by_gid) + machine_name = machine_by_gid->name; + else + return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL); + + r = sd_json_buildo(&v, + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("uid", converted_uid, UID_INVALID), + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("gid", converted_gid, GID_INVALID), + JSON_BUILD_PAIR_STRING_NON_EMPTY("machineName", machine_name)); + if (r < 0) + return r; + + return sd_varlink_reply(link, v); +} diff --git a/src/machine/machine-varlink.h b/src/machine/machine-varlink.h index 380f011dbea..984a8d8f3ed 100644 --- a/src/machine/machine-varlink.h +++ b/src/machine/machine-varlink.h @@ -25,3 +25,5 @@ int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters, int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_map_from(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_map_to(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c index 3385aa8a178..e0e27c44964 100644 --- a/src/machine/machined-varlink.c +++ b/src/machine/machined-varlink.c @@ -771,6 +771,8 @@ static int manager_varlink_init_machine(Manager *m) { "io.systemd.Machine.Terminate", vl_method_terminate, "io.systemd.Machine.Kill", vl_method_kill, "io.systemd.Machine.Open", vl_method_open, + "io.systemd.Machine.MapFrom", vl_method_map_from, + "io.systemd.Machine.MapTo", vl_method_map_to, "io.systemd.MachineImage.List", vl_method_list_images, "io.systemd.MachineImage.Update", vl_method_update_image, "io.systemd.MachineImage.Clone", vl_method_clone_image, diff --git a/src/shared/varlink-io.systemd.Machine.c b/src/shared/varlink-io.systemd.Machine.c index 83a20f4f0eb..696d4020022 100644 --- a/src/shared/varlink-io.systemd.Machine.c +++ b/src/shared/varlink-io.systemd.Machine.c @@ -122,6 +122,31 @@ static SD_VARLINK_DEFINE_METHOD( SD_VARLINK_FIELD_COMMENT("Path to the allocated pseudo TTY"), SD_VARLINK_DEFINE_OUTPUT(ptyPath, SD_VARLINK_STRING, 0)); +static SD_VARLINK_DEFINE_METHOD( + MapFrom, + VARLINK_DEFINE_MACHINE_LOOKUP_AND_POLKIT_INPUT_FIELDS, + SD_VARLINK_FIELD_COMMENT("UID in the machine to map to host UID"), + SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("GID in the machine to map to host GID"), + SD_VARLINK_DEFINE_INPUT(gid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Mapped UID"), + SD_VARLINK_DEFINE_OUTPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Mapped GID"), + SD_VARLINK_DEFINE_OUTPUT(gid, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_METHOD( + MapTo, + SD_VARLINK_FIELD_COMMENT("Host UID to map to machine UID"), + SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Host GID to map to machine GID"), + SD_VARLINK_DEFINE_INPUT(gid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Mapped UID"), + SD_VARLINK_DEFINE_OUTPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Mapped GID"), + SD_VARLINK_DEFINE_OUTPUT(gid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Machine's name which owns mapped UID/GID"), + SD_VARLINK_DEFINE_OUTPUT(machineName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE)); + static SD_VARLINK_DEFINE_ERROR(NoSuchMachine); static SD_VARLINK_DEFINE_ERROR(MachineExists); static SD_VARLINK_DEFINE_ERROR(NoPrivateNetworking); @@ -130,6 +155,10 @@ static SD_VARLINK_DEFINE_ERROR(NoUIDShift); static SD_VARLINK_DEFINE_ERROR(NotAvailable); static SD_VARLINK_DEFINE_ERROR(NotSupported); static SD_VARLINK_DEFINE_ERROR(NoIPC); +static SD_VARLINK_DEFINE_ERROR(NoSuchUser); +static SD_VARLINK_DEFINE_ERROR(NoSuchGroup); +static SD_VARLINK_DEFINE_ERROR(UserInHostRange); +static SD_VARLINK_DEFINE_ERROR(GroupInHostRange); SD_VARLINK_DEFINE_INTERFACE( io_systemd_Machine, @@ -154,6 +183,10 @@ SD_VARLINK_DEFINE_INTERFACE( &vl_type_MachineOpenMode, SD_VARLINK_SYMBOL_COMMENT("Allocates a pseudo TTY in the container in various modes"), &vl_method_Open, + SD_VARLINK_SYMBOL_COMMENT("Maps given machine's UID/GID to host's UID/GID"), + &vl_method_MapFrom, + SD_VARLINK_SYMBOL_COMMENT("Maps given host's UID/GID to a machine and corresponding UID/GID"), + &vl_method_MapTo, SD_VARLINK_SYMBOL_COMMENT("No matching machine currently running"), &vl_error_NoSuchMachine, &vl_error_MachineExists, @@ -168,4 +201,12 @@ SD_VARLINK_DEFINE_INTERFACE( SD_VARLINK_SYMBOL_COMMENT("Requested operation is not supported"), &vl_error_NotSupported, SD_VARLINK_SYMBOL_COMMENT("There is no IPC service (such as system bus or varlink) in the container"), - &vl_error_NoIPC); + &vl_error_NoIPC, + SD_VARLINK_SYMBOL_COMMENT("No such user"), + &vl_error_NoSuchUser, + SD_VARLINK_SYMBOL_COMMENT("No such group"), + &vl_error_NoSuchGroup, + SD_VARLINK_SYMBOL_COMMENT("User belongs to host UID range"), + &vl_error_UserInHostRange, + SD_VARLINK_SYMBOL_COMMENT("Group belongs to host GID range"), + &vl_error_GroupInHostRange);