-
Notifications
You must be signed in to change notification settings - Fork 103
Miscellaneous fixes for running Podman as a confined user #383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Reviewer's GuideThis PR adds and refines SELinux policy rules in container.fc and container.te to enable unprivileged, SELinux-confined users to run Podman containers by granting necessary file contexts, namespace permissions, cgroup and netlink access, and mount rights. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @gucci-on-fleek - I've reviewed your changes and they look great!
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: gucci-on-fleek, sourcery-ai[bot] The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @gucci-on-fleek, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request addresses several SELinux policy gaps that prevent Podman and related tools from functioning seamlessly for confined users, particularly in a Fedora IoT environment. The changes introduce specific rules to enable key functionalities such as running the Prometheus Podman exporter, executing bootc status
via sudo
, building container images with rpm-ostree
/bootc
, and ensuring proper systemd integration for socket-activated containers, all while operating under SELinux confinement. The aim is to provide a more robust and user-friendly experience for confined Podman users.
Highlights
- SELinux Policy for Prometheus Exporter: Added a file context rule in
container.fc
to correctly label/usr/bin/prometheus-podman-exporter
withcontainer_runtime_exec_t
, allowing it to execute with appropriate SELinux permissions. - Enhanced
bootc
andrpm-ostree
Support: Introduced new SELinux rules incontainer.te
to enablebootc status
when run viasudo
by confined users, and to permitrpm-ostree
/bootc
image building operations within containers by granting necessary filesystem and process transition permissions. - Improved Systemd Integration for Confined Users: Implemented policies in
container.te
to facilitate systemd socket activation for containers run by confined users, including permissions for TCP/UDP socket operations and allowing systemd to send signals (e.g.,SIGKILL
) to container processes for proper shutdown. - Podman Build Functionality for Confined Users: Added specific rules in
container.te
to allow confined users to performpodman build
operations, addressing permissions related to mounting on read-only container directories and utilizing thesetuid
capability. - Suppressing Harmless SELinux Denials: Included
dontaudit
rules incontainer.te
to prevent logging of known harmless SELinux AVC denials related tonnp_transition
andchown
attempts on FIFO files, reducing noise in audit logs.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
Without this label, running "prometheus-podman-exporter" as an SELinux-confined user results in a race condition: - If "prometheus-podman-exporter" starts before any containers, running any Podman commands (even just "podman system info") gives you a perplexing error: audit[26268]: AVC avc: denied { create } for pid=26268 comm="exe" name="whiteout" scontext=user_u:user_r:user_t:s0-s0:c0.c1023 tcontext=user_u:object_r:container_ro_file_t:s0 tclass=chr_file permissive=0 prometheus-podman-exporter[26268]: 2025/06/04 22:41:47 configure storage: kernel does not support overlay fs: unable to create kernel-style whiteout: permission denied podman[26287]: Error: configure storage: kernel does not support overlay fs: unable to create kernel-style whiteout: permission denied - If any containers start before "prometheus-podman-exporter", then everything is fine, except the "podman_container_mem_usage_bytes" metric is oddly missing. But as long as 1 container starts before "prometheus-podman-exporter", you're still able to run new containers, even after "prometheus-podman-exporter" has started. Signed-off-by: Max Chernoff <[email protected]>
Signed-off-by: Max Chernoff <[email protected]>
Signed-off-by: Max Chernoff <[email protected]>
Signed-off-by: Max Chernoff <[email protected]>
Signed-off-by: Max Chernoff <[email protected]>
Signed-off-by: Max Chernoff <[email protected]>
Signed-off-by: Max Chernoff <[email protected]>
83d9444
to
a1914b9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces several SELinux rule changes to enhance the usability of Podman for confined users. The changes address specific scenarios like bootc status
, building images within containers, systemd socket activation, and general podman build
operations.
While many additions seem justified by the provided comments, there are a few areas of concern, particularly regarding the principle of least privilege and the correct use of SELinux types for objects. The most significant concern is the granting of the setuid
capability to userdomain
.
My review focuses on ensuring these new rules are secure, correctly implemented, and maintainable.
|
||
# Needed for "podman build" to work as a confined user | ||
allow userdomain container_ro_file_t:dir mounton; | ||
allow userdomain self:capability setuid; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Granting the setuid
capability to userdomain
(allow userdomain self:capability setuid;
) is a significant security concern and generally should be avoided. userdomain
encompasses regular, potentially unprivileged user sessions (e.g., user_t
, staff_t
). CAP_SETUID
allows a process to change its UID, which can lead to privilege escalation if misused.
Rootless Podman typically relies on user namespaces and setuid-root helpers like newuidmap
/newgidmap
(which have their own specific SELinux handling, e.g., setuid_exec_t
) for UID/GID mapping, not on the user's shell or Podman client process having CAP_SETUID
directly.
This permission needs extremely strong justification.
- Is there a specific helper executed by
podman build
that requires this, and could it be confined to a more specific domain? - Can the operation be achieved using user namespaces without requiring
userdomain
to have this capability?
Unless there's an unavoidable, well-understood, and narrowly-scoped reason for this, this line should be removed to maintain the security posture of confined user domains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
allow userdomain self:capability setuid
only allows processes with the setuid-bit set (newuidmap
/newgidmap
in this case) to actually call setuid
; it does not allow any new processes to run as setuid. Still, I agree that this rule isn't very good, but I couldn't find another solution that works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you running rootful or rootless?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rootless, as user_u
:
$ id
uid=1006(builder) gid=1006(builder) groups=1006(builder) context=user_u:user_r:user_t:s0-s0:c0.c1023
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok so these are newuidmap and newgidmap causing the AVC, lets wrap it in a boolean.
allow userdomain container_runtime_t:tcp_socket { bind create getopt listen setopt }; | ||
allow userdomain container_runtime_t:udp_socket { bind create getopt listen setopt }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The target type container_runtime_t
in these rules (allow userdomain container_runtime_t:tcp_socket { ... };
and allow userdomain container_runtime_t:udp_socket { ... };
) appears to be a misapplication of SELinux object classes. container_runtime_t
is a process domain type, not a type for socket objects.
SELinux rules for object access are generally allow <source_domain> <target_object_type>:<object_class> <permissions>;
.
If userdomain
(e.g., systemd running as the user) is creating and binding these sockets for socket activation, the rules should be more like:
allow userdomain self:tcp_socket { bind create getopt listen setopt };
(if using its own type temporarily)
OR
allow userdomain some_specific_socket_type:tcp_socket { bind create getopt listen setopt };
And then, container_runtime_t
(Podman) would need permissions to use/inherit these sockets (e.g., allow container_runtime_t some_specific_socket_type:tcp_socket { read write ... };
or allow container_runtime_t userdomain:fd use;
).
As written, these rules imply userdomain
is performing actions on sockets that are already associated with (e.g., created by) the container_runtime_t
process, which is contrary to the typical systemd socket activation flow where systemd creates the socket first. Please clarify the intended interaction and adjust the types accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very strange AVC? This looks like podman is running under a confined user domain? or the confined user transitioned to confined_user_t?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like podman is running under a confined user domain?
Yes, I'm running some rootless Podman containers via systemd Quadlets as user_u
.
This is a very strange AVC?
The AI comments above are mostly nonsense, but I think that what's happening (but I might be wrong) is that for socket-activated units, systemd creates the socket using the context of the target binary:
[...] Other parts of the resulting SELinux context originate from either the target binary that is effectively triggered by socket unit [...]
https://www.freedesktop.org/software/systemd/man/latest/systemd.socket.html#SELinuxContextFromNet=
which in this case, is /usr/bin/podman
. But for that to work, systemd needs to be allowed to create the socket with that context. I couldn't find any way to tell systemd what context to use when it creates sockets, so this was the only way that I could figure out to make it work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok lets wrap some of these in boolean.
|
||
# When shutting down, systemd will stop the container before the socket unit, so | ||
# ignore any AVC denials from systemd trying to accept the socket | ||
dontaudit userdomain container_runtime_t:tcp_socket accept; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the comment on lines 1653-1654, using container_runtime_t
(a process domain type) as the target type for a tcp_socket
class in a dontaudit
rule is incorrect. The rule dontaudit userdomain container_runtime_t:tcp_socket accept;
means you are silencing denials where userdomain
attempts to accept
on a TCP socket object that is somehow typed/associated with the container_runtime_t
process domain.
This likely masks an underlying type enforcement issue or a misunderstanding of how the socket is typed and managed. The socket object itself should have a proper socket type. Please review the types involved in this interaction.
allow sysadm_t install_t:process transition; | ||
type_transition sysadm_t install_exec_t:process install_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The transition to install_t
for bootc status
(via sudo
, hence sysadm_t
) might be overly permissive if bootc status
is a read-only operation. The install_t
domain typically has permissions for software installation and modification.
If bootc status
can function with a more restricted domain, that would be preferable under the Principle of Least Privilege. However, if the bootc
toolset inherently requires install_t
for its operations, this might be unavoidable. Consider verifying if a more constrained type could suffice for the 'status' subcommand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yuck, but I am fine with allowing this.
allow container_t devpts_t:filesystem mount; | ||
allow container_t proc_t:filesystem mount; | ||
allow container_t tmpfs_t:filesystem remount; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Granting container_t
(the general domain for processes inside containers) direct filesystem mount
permission on devpts_t
and proc_t
, and filesystem remount
on tmpfs_t
is quite broad. While necessary for image building tools that set up new namespaces, these rules apply to any process running as container_t
.
Consider if these permissions can be narrowed:
- Could they be gated by a tunable boolean (e.g.,
tunable_policy(container_allow_filesystem_mount, false)
) so they are opt-in for systems that require this functionality? - Are there more specific contexts or conditions (e.g., specific capabilities granted to the container) under which these should be allowed?
While user namespaces in rootless containers mitigate some host-level risks, these broad permissions for container_t
should be carefully evaluated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These look fine to me. the first one should definitely be allowed. We should allow watch access for all container file types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should allow watch access for all container file types.
Watch access already seems to be allowed for container_file_t
, but I can change the rule to use container_file_type
(which is just container_ro_file_t
and container_file_t
) instead if you prefer.
Ephemeral COPR build failed. @containers/packit-build please check. |
1 similar comment
Ephemeral COPR build failed. @containers/packit-build please check. |
@@ -48,6 +48,7 @@ | |||
/usr/s?bin/crio.* -- gen_context(system_u:object_r:container_runtime_exec_t,s0) | |||
/usr/local/s?bin/crio.* -- gen_context(system_u:object_r:container_runtime_exec_t,s0) | |||
/usr/s?bin/ocid.* -- gen_context(system_u:object_r:container_runtime_exec_t,s0) | |||
/usr/bin/prometheus-podman-exporter -- gen_context(system_u:object_r:container_runtime_exec_t,s0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Container_runtime_t is a very permissive (unconfined) domain, does this tool basically run podman?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this tool basically run podman?
/usr/bin/prometheus-podman-exporter
is this tool, which is essentially a network-facing wrapper around podman ps
and podman stats
.
Container_runtime_t is a very permissive (unconfined) domain
I can test labelling it with a different domain, do you have any suggestions? This one was giving me bizarre errors (see the commit message for “Label prometheus-podman-exporter as container_runtime_exec_t”), so I have no idea which domains to try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What avc's are generated by leaving it bin_t?
I've been running Podman containers from SELinux-confined users on my Fedora IoT server for a few months now, but I've needed a few custom rules for it to work properly. This patch contains those rules.
There are quite a few (very small) changes here, so please let me know if you have any questions or want me to make any changes.
Full disclosure: I've been using a CIL version of these rules for a couple months now, and I've confirmed that the policy still builds (
make all
) and installs (semodule --install
) correctly, but I haven't directly tested using the.pp
module from this patch on my server.Summary by Sourcery
Add SELinux policy updates to enable confined users to run Podman containers without custom rules
Bug Fixes: