Files
snapd/tests/lib/snaps
James Henstridge 4dfeea8fce interfaces: add a polkit-agent interface (#10598)
This is a first go at an interface to allow a snap to register as a Polkit agent. The primary use case is for the Ubuntu Core Desktop system we're building. The implicit slot is not available on classic systems, since there is no reasonable way to implement it given the variability in the PAM and NSS configurations found on those systems.

Here's a brief description of how a Polkit agent operates:

The agent registers with polkitd by calling the RegisterAgent D-Bus method. In general, it will register as an agent for all processes that belong to a particular logind session.
When a system daemon makes a CheckAuthorization call to polkitd for a subject that is covered by the agent, polkitd will make a BeginAuthentication call to the agent. This includes the requested action ID, a message to show the user, and a cookie string to identify the authentication request.
The agent runs the setuid polkit-agent-helper-1 executable as a sub-process. The helper begins the PAM authentication process, and delegates any prompts to the agent via messages on stdin/stdout.
On completion of the authentication process (either success or failure), the helper makes an AuthenticationAgentResponse2 method call to polkitd, using the cookie to identify the request. Polkitd trusts the response because the D-Bus connection credentials show that the helper is running as root.
Polkitd responds to the system daemon with this result, allowing it to decide how to respond to its client.
This poses a number of difficulties for a snap based system:

The snap needs to be able to execute a setuid binary.
The setuid binary is going to inherit some security config from its parent process, including:
mount name space: it will be running in the snap's sandbox, so the sandbox will need to provide all the PAM modules referenced by the system's configuration, and have access to all data files and services those modules use.
seccomp filters: the parent's seccomp filter will need to allow all access the setuid helper requires. One obvious case that has come up is access to the kernel audit subsystem.
The need to support the host system's PAM config mostly rules out getting this to work on Classic systems. On Core systems though, things will generally work if the snap uses the same base as the boot file system (or something sufficiently similar).

The interface makes use of AppArmor's ability to switch profiles on exec(). We switch to a sub-profile tailored to what polkit-agent-helper-1 needs. Namely:

Include nameservice and authentication abstractions to enable use of PAM. Also grant access to extrausers shadow files, which aren't currently included in authentication.
Allow audit_write and sys_nice capabilities, which are used by the installed PAM modules
Allow SIGTERM signals from the calling snap: this is sent when the user cancels authentication. The corresponding rule allowing the agent to send the signal is covered by the default snap AppArmor template.
Allow communication with polkitd over the D-Bus system bus to make the AuthenticationAgentResponse2 method call.
The interface is locked down with allow-installation: false on the plug side, since it allows running a privileged process in a mount namespace under the control of the snap. Through the use of layouts, it's possible that the snap could replace shared libraries loaded by the helper. Even though the helper is locked down through an AppArmor sub-profile, it seems reasonable to vet snaps that request this access.

I don't have a spread test for this, as we don't have any ubuntu-core-* systems with polkit integrated, and I'm not all together certain how I'd structure a test for this. We have been manually testing the interface on Core Desktop builds though.

* interfaces: add a polkit-agent interface

* interfaces: use a subprofile to run polkit-agent-helper-1 in polkit-agent interface

* interfaces: only look for polkit-agent-helper-1 in /usr/libexec

Prior to Ubuntu 22.04, the polkit executables were installed in
/usr/lib/policykit-1. As there is practically zero chance of polkit
being integrated into these older Ubuntu Core versions, there's no
benefit checking the old path.
2023-10-02 13:43:32 +02:00
..