diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index c096a012d8..a9d15ca5f7 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -247,6 +247,25 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
assert(message);
+ if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
+ const char *details[] = {
+ "machine", m->name,
+ "verb", "get_os_release",
+ NULL
+ };
+
+ r = bus_verify_polkit_async(
+ message,
+ "org.freedesktop.machine1.inspect-machines",
+ details,
+ &m->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+ }
+
r = machine_get_os_release(m, &l);
if (r == -ENONET)
return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information.");
diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c
index 4ab68a77f9..acc2137f83 100644
--- a/src/machine/machined-varlink.c
+++ b/src/machine/machined-varlink.c
@@ -535,6 +535,17 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl
if (r != 0)
return r;
+ if (m->runtime_scope != RUNTIME_SCOPE_USER && should_acquire_metadata(p.acquire_metadata)) {
+ r = varlink_verify_polkit_async(
+ link,
+ m->system_bus,
+ "org.freedesktop.machine1.inspect-machines",
+ (const char**) STRV_MAKE("name", strna(p.name)),
+ &m->polkit_registry);
+ if (r <= 0)
+ return r;
+ }
+
r = sd_varlink_set_sentinel(link, VARLINK_ERROR_MACHINE_NO_SUCH_MACHINE);
if (r < 0)
return r;
@@ -682,6 +693,17 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
if (r != 0)
return r;
+ if (m->runtime_scope != RUNTIME_SCOPE_USER && should_acquire_metadata(p.acquire_metadata)) {
+ r = varlink_verify_polkit_async(
+ link,
+ m->system_bus,
+ "org.freedesktop.machine1.inspect-images",
+ (const char**) STRV_MAKE("name", strna(p.image_name)),
+ &m->polkit_registry);
+ if (r <= 0)
+ return r;
+ }
+
r = sd_varlink_set_sentinel(link, VARLINK_ERROR_MACHINE_IMAGE_NO_SUCH_IMAGE);
if (r < 0)
return r;
diff --git a/src/machine/org.freedesktop.machine1.policy b/src/machine/org.freedesktop.machine1.policy
index d5b8d83d2a..f8f498f8cf 100644
--- a/src/machine/org.freedesktop.machine1.policy
+++ b/src/machine/org.freedesktop.machine1.policy
@@ -88,7 +88,17 @@
auth_admin
auth_admin_keep
- org.freedesktop.login1.shell org.freedesktop.login1.login
+ org.freedesktop.login1.shell org.freedesktop.login1.login org.freedesktop.machine1.inspect-machines
+
+
+
+ Inspect local virtual machines and containers
+ Authentication is required to inspect local virtual machines and containers.
+
+ auth_admin
+ auth_admin
+ auth_admin_keep
+
@@ -120,6 +130,17 @@
auth_admin
auth_admin_keep
+ org.freedesktop.machine1.inspect-images
+
+
+
+ Inspect local virtual machine and container images
+ Authentication is required to inspect local virtual machine and container images.
+
+ auth_admin
+ auth_admin
+ auth_admin_keep
+
diff --git a/test/units/TEST-13-NSPAWN.unpriv.sh b/test/units/TEST-13-NSPAWN.unpriv.sh
index 75a9c1aac0..e0516449c7 100755
--- a/test/units/TEST-13-NSPAWN.unpriv.sh
+++ b/test/units/TEST-13-NSPAWN.unpriv.sh
@@ -23,6 +23,8 @@ at_exit() {
rm -rf /home/testuser/.local/state/machines/inodetest2 ||:
rm -rf /home/testuser/.local/state/machines/mangletest ||:
machinectl terminate zurps ||:
+ machinectl terminate exfiltrate ||:
+ systemctl --user --machine testuser@ stop exfiltrate.service ||:
rm -f /etc/polkit-1/rules.d/registermachinetest.rules
machinectl terminate nurps ||:
machinectl terminate kurps ||:
@@ -163,6 +165,28 @@ run0 -u testuser \
systemctl --user --machine testuser@ stop sleep.service
test ! -f /shouldnotwork
+echo FOO=bar >/tmp/foo
+chmod 600 /tmp/foo
+run0 -u testuser \
+ systemd-run --unit exfiltrate.service --service-type notify --property NotifyAccess=all --user \
+ unshare --map-root-user --user --mount \
+ bash -c 'mount --bind /tmp/foo /usr/lib/os-release; systemd-notify --ready; exec sleep infinity'
+exfiltrate_pid="$(systemctl --machine testuser@.host show --user -P MainPID exfiltrate.service)"
+run0 -u testuser \
+ varlinkctl \
+ call \
+ /run/systemd/machine/io.systemd.Machine \
+ io.systemd.Machine.Register \
+ "{\"name\":\"exfiltrate\", \"class\":\"container\", \"leader\": $exfiltrate_pid}"
+exfiltrate_output="$(run0 -u testuser \
+ varlinkctl \
+ call \
+ /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List \
+ "{\"name\":\"exfiltrate\",\"acquireMetadata\":\"graceful\"}" 2>&1)" || true
+(! echo "$exfiltrate_output" | grep '"name".*"exfiltrate"' >/dev/null)
+(! echo "$exfiltrate_output" | grep "FOO=bar" >/dev/null)
+systemctl --user --machine testuser@ stop exfiltrate.service
+
run0 -u testuser mkdir /var/tmp/image-tar
run0 -u testuser importctl --user export-tar zurps /var/tmp/image-tar/kurps.tar.gz -m
run0 -u testuser importctl --user import-tar /var/tmp/image-tar/kurps.tar.gz -m