diff --git a/man/org.freedesktop.machine1.xml b/man/org.freedesktop.machine1.xml
index ea3a706215..c52aed0dbc 100644
--- a/man/org.freedesktop.machine1.xml
+++ b/man/org.freedesktop.machine1.xml
@@ -525,6 +525,8 @@ node /org/freedesktop/machine1/machine/rawhide {
readonly s SSHPrivateKeyPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s State = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly u UID = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
@@ -620,6 +622,8 @@ node /org/freedesktop/machine1/machine/rawhide {
+
+
@@ -683,6 +687,8 @@ node /org/freedesktop/machine1/machine/rawhide {
Subgroup contains the sub-control-group path this machine's processes reside
in, relative to the specified unit's control group.
+
+ UID contains the numeric UNIX UID of the user who registered the machine.
@@ -726,7 +732,8 @@ $ gdbus introspect --system \
CopyToWithFlags() were added in version 252.
GetSSHInfo(), VSockCID, SSHAddress,
and SSHPrivateKeyPath were added in version 256.
- LeaderPIDFDId and Subgroup were added in version 258.
+ LeaderPIDFDId, Subgroup, and UID were
+ added in version 258.
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 8935b59465..321ddbfdcc 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -60,10 +60,12 @@ int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bu
NULL
};
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
message,
"org.freedesktop.machine1.manage-machines",
details,
+ m->uid,
+ /* flags= */ 0,
&m->manager->polkit_registry,
error);
if (r < 0)
@@ -90,10 +92,12 @@ int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus
NULL
};
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
message,
"org.freedesktop.machine1.manage-machines",
details,
+ m->uid,
+ /* flags= */ 0,
&m->manager->polkit_registry,
error);
if (r < 0)
@@ -138,10 +142,12 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
NULL
};
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
message,
"org.freedesktop.machine1.manage-machines",
details,
+ m->uid,
+ /* flags= */ 0,
&m->manager->polkit_registry,
error);
if (r < 0)
@@ -258,10 +264,12 @@ int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_
NULL
};
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
message,
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
details,
+ m->uid,
+ /* flags= */ 0,
&m->manager->polkit_registry,
error);
if (r < 0)
@@ -299,10 +307,12 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
NULL
};
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
message,
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
details,
+ m->uid,
+ /* flags= */ 0,
&m->manager->polkit_registry,
error);
if (r < 0)
@@ -383,10 +393,12 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
NULL
};
- r = bus_verify_polkit_async(
+ r = bus_verify_polkit_async_full(
message,
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
details,
+ m->uid,
+ /* flags= */ 0,
&m->manager->polkit_registry,
error);
if (r < 0)
@@ -446,6 +458,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
NULL
};
+ /* NB: For now not opened up to owner of machine without auth */
r = bus_verify_polkit_async(
message,
"org.freedesktop.machine1.manage-machines",
@@ -531,6 +544,7 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
NULL
};
+ /* NB: For now not opened up to owner of machine without auth */
r = bus_verify_polkit_async(
message,
"org.freedesktop.machine1.manage-machines",
@@ -574,6 +588,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
NULL
};
+ /* NB: For now not opened up to owner of machine without auth */
r = bus_verify_polkit_async(
message,
"org.freedesktop.machine1.manage-machines",
@@ -727,6 +742,7 @@ static const sd_bus_vtable machine_vtable[] = {
SD_BUS_PROPERTY("SSHAddress", "s", NULL, offsetof(Machine, ssh_address), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SSHPrivateKeyPath", "s", NULL, offsetof(Machine, ssh_private_key_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Machine, uid), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("Terminate",
NULL,
diff --git a/src/machine/machine-varlink.c b/src/machine/machine-varlink.c
index b5754e2c49..8c437efc17 100644
--- a/src/machine/machine-varlink.c
+++ b/src/machine/machine-varlink.c
@@ -168,6 +168,10 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
return r;
}
+ r = sd_varlink_get_peer_uid(link, &machine->uid);
+ if (r < 0)
+ return r;
+
r = machine_link(manager, machine);
if (r == -EEXIST)
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_EXISTS, NULL);
@@ -278,12 +282,14 @@ int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters,
Manager *manager = ASSERT_PTR(machine->manager);
int r;
- r = varlink_verify_polkit_async(
+ r = varlink_verify_polkit_async_full(
link,
manager->bus,
"org.freedesktop.machine1.manage-machines",
(const char**) STRV_MAKE("name", machine->name,
"verb", "unregister"),
+ machine->uid,
+ /* flags= */ 0,
&manager->polkit_registry);
if (r <= 0)
return r;
@@ -300,12 +306,14 @@ int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters,
Manager *manager = ASSERT_PTR(machine->manager);
int r;
- r = varlink_verify_polkit_async(
+ r = varlink_verify_polkit_async_full(
link,
manager->bus,
"org.freedesktop.machine1.manage-machines",
(const char**) STRV_MAKE("name", machine->name,
"verb", "terminate"),
+ machine->uid,
+ /* flags= */ 0,
&manager->polkit_registry);
if (r <= 0)
return r;
@@ -368,12 +376,14 @@ int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
return sd_varlink_error_invalid_parameter_name(link, "whom");
}
- r = varlink_verify_polkit_async(
+ r = varlink_verify_polkit_async_full(
link,
manager->bus,
"org.freedesktop.machine1.manage-machines",
(const char**) STRV_MAKE("name", machine->name,
"verb", "kill"),
+ machine->uid,
+ /* flags= */ 0,
&manager->polkit_registry);
if (r <= 0)
return r;
@@ -510,11 +520,13 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
return r;
polkit_details = machine_open_polkit_details(p.mode, machine->name, user, path, command_line);
- r = varlink_verify_polkit_async(
+ r = varlink_verify_polkit_async_full(
link,
manager->bus,
machine_open_polkit_action(p.mode, machine->class),
(const char**) polkit_details,
+ machine->uid,
+ /* flags= */ 0,
&manager->polkit_registry);
if (r <= 0)
return r;
@@ -788,6 +800,7 @@ int vl_method_bind_mount(sd_varlink *link, sd_json_variant *parameters, sd_varli
if (machine->class != MACHINE_CONTAINER)
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
+ /* NB: For now not opened up to owner of machine without auth */
r = varlink_verify_polkit_async(
link,
manager->bus,
@@ -899,6 +912,7 @@ int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_va
if (machine->class != MACHINE_CONTAINER)
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
+ /* NB: For now not opened up to owner of machine without auth */
r = varlink_verify_polkit_async(
link,
manager->bus,
@@ -928,6 +942,7 @@ int vl_method_open_root_directory_internal(sd_varlink *link, sd_json_variant *pa
Manager *manager = ASSERT_PTR(machine->manager);
int r;
+ /* NB: For now not opened up to owner of machine without auth */
r = varlink_verify_polkit_async(
link,
manager->bus,
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 7ce512dd62..91c1450184 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -183,8 +183,10 @@ int machine_save(Machine *m) {
fprintf(f,
"# This is private data. Do not parse.\n"
- "NAME=%s\n",
- m->name);
+ "NAME=%s\n"
+ "UID=" UID_FMT "\n",
+ m->name,
+ m->uid);
/* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */
env_file_fputs_assignment(f, "SCOPE=", m->unit);
@@ -261,7 +263,7 @@ static void machine_unlink(Machine *m) {
int machine_load(Machine *m) {
_cleanup_free_ char *name = NULL, *realtime = NULL, *monotonic = NULL, *id = NULL, *leader = NULL, *leader_pidfdid = NULL,
- *class = NULL, *netif = NULL, *vsock_cid = NULL;
+ *class = NULL, *netif = NULL, *vsock_cid = NULL, *uid = NULL;
int r;
assert(m);
@@ -285,7 +287,8 @@ int machine_load(Machine *m) {
"NETIF", &netif,
"VSOCK_CID", &vsock_cid,
"SSH_ADDRESS", &m->ssh_address,
- "SSH_PRIVATE_KEY_PATH", &m->ssh_private_key_path);
+ "SSH_PRIVATE_KEY_PATH", &m->ssh_private_key_path,
+ "UID", &uid);
if (r == -ENOENT)
return 0;
if (r < 0)
@@ -369,6 +372,10 @@ int machine_load(Machine *m) {
log_warning_errno(r, "Failed to parse AF_VSOCK CID, ignoring: %s", vsock_cid);
}
+ r = parse_uid(uid, &m->uid);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse owning UID, ignoring: %s", uid);
+
return r;
}
@@ -426,14 +433,28 @@ static int machine_start_scope(
if (r < 0)
return r;
- r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
- "Delegate", "b", 1,
- "CollectMode", "s", "inactive-or-failed",
- "AddRef", "b", 1,
- "TasksMax", "t", UINT64_C(16384));
+ r = sd_bus_message_append(
+ m, "(sv)(sv)(sv)(sv)",
+ "Delegate", "b", 1,
+ "CollectMode", "s", "inactive-or-failed",
+ "AddRef", "b", 1,
+ "TasksMax", "t", UINT64_C(16384));
if (r < 0)
return r;
+ if (machine->uid != 0) {
+ _cleanup_free_ char *u = NULL;
+
+ if (asprintf(&u, UID_FMT, machine->uid) < 0)
+ return -ENOMEM;
+
+ r = sd_bus_message_append(
+ m, "(sv)",
+ "User", "s", u);
+ if (r < 0)
+ return r;
+ }
+
if (more_properties) {
r = sd_bus_message_copy(m, more_properties, true);
if (r < 0)
diff --git a/src/machine/machine.h b/src/machine/machine.h
index 8762263a8b..dddc0c8000 100644
--- a/src/machine/machine.h
+++ b/src/machine/machine.h
@@ -38,6 +38,8 @@ typedef struct Machine {
char *name;
sd_id128_t id;
+ uid_t uid;
+
MachineClass class;
char *state_file;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 7731fae708..d31ef407f4 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -514,6 +514,7 @@ typedef struct MachineStatusInfo {
struct dual_timestamp timestamp;
int *netif;
size_t n_netif;
+ uid_t uid;
} MachineStatusInfo;
static void machine_status_info_clear(MachineStatusInfo *info) {
@@ -567,6 +568,9 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
} else if (i->class)
printf("\t Class: %s\n", i->class);
+ if (i->uid != 0)
+ printf("\t UID: " UID_FMT "\n", i->uid);
+
if (i->root_directory)
printf("\t Root: %s\n", i->root_directory);
@@ -662,6 +666,7 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo
{ "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) },
{ "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
{ "NetworkInterfaces", "ai", map_netif, 0 },
+ { "UID", "u", NULL, offsetof(MachineStatusInfo, uid) },
{}
};
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 8aa00ba3ed..30f722a449 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -300,6 +300,16 @@ static int method_create_or_register_machine(
if (hashmap_get(manager->machines, name))
return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
+ if (r < 0)
+ return r;
+
+ uid_t uid;
+ r = sd_bus_creds_get_euid(creds, &uid);
+ if (r < 0)
+ return r;
+
const char *details[] = {
"name", name,
"class", machine_class_to_string(c),
@@ -324,6 +334,7 @@ static int method_create_or_register_machine(
m->leader = TAKE_PIDREF(pidref);
m->class = c;
m->id = id;
+ m->uid = uid;
if (!isempty(service)) {
m->service = strdup(service);
diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c
index 8551d703e7..7dac3cb0d2 100644
--- a/src/machine/machined-varlink.c
+++ b/src/machine/machined-varlink.c
@@ -485,7 +485,8 @@ static int list_machine_one_and_maybe_read_metadata(sd_varlink *link, Machine *m
JSON_BUILD_PAIR_STRING_NON_EMPTY("sshPrivateKeyPath", m->ssh_private_key_path),
JSON_BUILD_PAIR_VARIANT_NON_NULL("addresses", addr_array),
JSON_BUILD_PAIR_STRV_ENV_PAIR_NON_EMPTY("OSRelease", os_release),
- JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("UIDShift", shift, UID_INVALID));
+ JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("UIDShift", shift, UID_INVALID),
+ SD_JSON_BUILD_PAIR_UNSIGNED("UID", m->uid));
if (r < 0)
return r;
diff --git a/src/shared/varlink-io.systemd.Machine.c b/src/shared/varlink-io.systemd.Machine.c
index 1bb7c00fa1..ad7dff228f 100644
--- a/src/shared/varlink-io.systemd.Machine.c
+++ b/src/shared/varlink-io.systemd.Machine.c
@@ -98,7 +98,9 @@ static SD_VARLINK_DEFINE_METHOD_FULL(
SD_VARLINK_FIELD_COMMENT("Return the base UID/GID of the machine"),
SD_VARLINK_DEFINE_OUTPUT(UIDShift, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Subcgroup path of the machine, relative to the unit's cgroup path"),
- SD_VARLINK_DEFINE_OUTPUT(Subgroup, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
+ SD_VARLINK_DEFINE_OUTPUT(Subgroup, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Numeric UNIX UID of the user who registered the machine"),
+ SD_VARLINK_DEFINE_OUTPUT(UID, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ENUM_TYPE(
MachineOpenMode,