Skip to content

units: Use DynamicUser=yes + polkit by default - #147

Open
mvo5 wants to merge 1 commit into
systemd:mainfrom
mvo5:dynamic-user-by-default
Open

mvo5 wants to merge 1 commit into
systemd:mainfrom
mvo5:dynamic-user-by-default

Conversation

@mvo5

@mvo5 mvo5 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Instead of running as root we should really prefer to run unprivileged. This can be done by using the DynamicUser=yes in the unit and by having a polkit rule that allows the bridge to talk to the various varlink services.

This is hardening, effectively the bridge is still root because it can start processes as root via varlink. The other nice benefit of it is that by using polkit we can potentially limit the usage more fine-grained. We also plan to add more features to polkit and systemd to carry more information from the bridge so that we can take data from the bridge authentication into account when making the authorization decisions.

Fwiw, if we can get polkit-org/polkit#712 merged this becomes much more useful.

Instead of running as root we should really prefer to run
unprivileged. This can be done by using the DynamicUser=yes
in the unit and by having a polkit rule that allows the bridge
to talk to the various varlink services.

This is hardening, effectively the bridge is still root because
it can start processes as root via varlink. The other nice benefit
of it is that by using polkit we can potentially limit the usage
more fine-grained. We also plan to add more features to polkit
and systemd to carry more information from the bridge so that
we can take data from the bridge authentication into account when
making the authorization decisions.
@mvo5
mvo5 force-pushed the dynamic-user-by-default branch from d5103a2 to 864f659 Compare October 15, 2026 06:00
# Nothing in the bridge needs root: every privileged operation happens in the
# varlink service on the other side of the socket, which authorizes the caller
# via polkit.
DynamicUser=yes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work with regard to early boot ordering? The socket unit says "the bridge is reachable for remote management while systemd-firstboot.service may still be blocking". Will dbus be up at that point to do the authentication for bridge requests at that point? If not, we should point this out somewhere in the readme.

DynamicUser=yes
# systemd-journal for journal access, varlink-httpd for the secrets in
# /etc/varlink-httpd/, which the transient uid cannot own.
SupplementaryGroups=systemd-journal varlink-httpd

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another potential ordering problem: varlink-httpd group may only exist after systemd-sysusers.service has run, but the unit as DefaultDependencies=no and no After=systemd-sysusers.service, so early calls might fail if the group doesn't exist. Restart=on-failure probably recovers it eventually.

Comment thread README.md
hopefully can carry more information from the bridge to polkit for
decisions.

Important to know:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should point out here that some services are unreachable with this default configuration. systemd-bootctl, systemd-repart, systemd-pcrlock, systemd-udevd-varlink, systemd-report and sysupdate-notify sockets come with 0644 by default. And there are also the methods that check uid == 0. I think the other PR mentions it, but might be nice to have a clear list we keep up to date.

Comment thread justfile
Comment on lines +9 to +10
sysusersdir := prefix / "lib/sysusers.d"
tmpfilesdir := prefix / "lib/tmpfiles.d"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now install these but never run systemd-sysusers or systemd-tmpfiles --create. I'm not a user of "install" commands, so I don't know what exactly the expectations there are.

Comment thread justfile

# without this rule polkit denies the DynamicUser every privileged varlink call
install_polkit:
install -Dm644 data/10-varlink-httpd.rules {{destdir}}{{polkitrulesdir}}/10-varlink-httpd.rules

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10- might be a bit high priority for a default rule? Not to familiar with the conventions..

Comment on lines +14 to +16
if (subject.system_unit === "varlink-httpd.service") {
return polkit.Result.YES;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rule doesn't check no_new_privileges, also see comments on the rule, dbus access etc in the other PR.

Comment thread varlink-httpd.spec

# The bridge runs with DynamicUser=yes and many varlink call need
# to be authorized by polkit
Requires: polkit

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Requires: polkit
Requires: polkit >= 124

I'm no expert when it comes to rpm packaging, but I think you can do something like this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants