Skip to content

Conversation

@0xDVC
Copy link

@0xDVC 0xDVC commented Oct 30, 2025

Remove incomplete CLI validation that only checked --pod flag and missed --pod-id-file (used by quadlet). Move validation to libpod/container_validate.go to catch all cases where --userns is set with --pod.

The new validation checks if container's ID mappings differ from the pod's
infra container and returns a clearer error message:
'cannot set user namespace mappings that differ from pod'

Fixes: #26848

Checklist

Ensure you have completed the following checklist for your pull request to be reviewed:

  • Certify you wrote the patch or otherwise have the right to pass it on as an open-source patch by signing all
    commits. (git commit -s). (If needed, use git commit -s --amend). The author email must match
    the sign-off email address. See CONTRIBUTING.md
    for more information.
  • Referenced issues using Fixes: #00000 in commit message (if applicable)
  • Tests have been added/updated (or no tests are needed)
  • Documentation has been updated (or no documentation changes are needed)
  • All commits pass make validatepr (format/lint checks)
  • Release note entered in the section below (or None if no user-facing changes)

Does this PR introduce a user-facing change?

Improved validation and error message when setting user namespace for containers in pods. Now properly catches all cases including quadlet configurations.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 30, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 0xDVC
Once this PR has been reviewed and has the lgtm label, please assign nalind for approval. For more information see the Code Review Process.

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@0xDVC 0xDVC force-pushed the fix-26848-userns-pod-validation branch from 6059c1f to 5a7b73a Compare October 30, 2025 23:50
@packit-as-a-service
Copy link

[NON-BLOCKING] Packit jobs failed. @containers/packit-build please check. Everyone else, feel free to ignore.

2 similar comments
@packit-as-a-service
Copy link

[NON-BLOCKING] Packit jobs failed. @containers/packit-build please check. Everyone else, feel free to ignore.

@packit-as-a-service
Copy link

[NON-BLOCKING] Packit jobs failed. @containers/packit-build please check. Everyone else, feel free to ignore.

@0xDVC 0xDVC force-pushed the fix-26848-userns-pod-validation branch 9 times, most recently from 88b5145 to d5700bc Compare October 31, 2025 12:29
// Linux requires containers sharing network or IPC namespaces (like in a pod) to use the same
// user namespace. Trying to use different ones will fail at the kernel level.
// Most of this is already checked in pkg/specgen/generate/namespaces.go before pod containers drop their ID mappings.
func (c *Container) validateUserNSInPod() error {
Copy link
Member

Choose a reason for hiding this comment

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

this is not my area of expertise, but what am I missing here? All conditions including the default return nil?

Copy link
Author

Choose a reason for hiding this comment

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

good catch, totally missed removing that. Earlier in development, I was focusing on libpod/container_validate.go as suggested when I started work. I realized that by the time that call runs, the ID mappings had already been dropped (in namespaces.go lines 265-269), so I would have missed catching the error. namespaces.go is where the actual validation is happening.

removing it now.

@0xDVC 0xDVC force-pushed the fix-26848-userns-pod-validation branch 4 times, most recently from 181f6ca to 502a145 Compare October 31, 2025 15:04
@TomSweeneyRedHat
Copy link
Member

Tests are unhappy, I'm not sure what's what with them. I'm going to try a rerun of the failed ones.

@0xDVC
Copy link
Author

0xDVC commented Oct 31, 2025

Tests are unhappy, I'm not sure what's what with them. I'm going to try a rerun of the failed ones.

Literally😂. For most, quite a learning experience. The rest? Got me at a choke hold.

@0xDVC 0xDVC force-pushed the fix-26848-userns-pod-validation branch 2 times, most recently from 1af8d52 to aba6c69 Compare November 1, 2025 08:53
Comment on lines 26 to 29
// Linux requires containers sharing network or IPC namespaces (like in a pod)
// to use the same user namespace. Trying to use different ones will fail at the kernel level.
func userNSConflictsWithPod(pod *libpod.Pod, mode specgen.NamespaceMode) error {
if pod != nil && pod.HasInfraContainer() && (pod.SharesIPC() || pod.SharesNet()) {
Copy link
Member

Choose a reason for hiding this comment

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

why are the network and ipc namespaces special cased here? I don't think the comment is right, it doesn't fail it is just not resulting in a proper setup as the namespace ownerships isn't right wich can cause permission problems later.

I see no reason to special case namespace types here, this should be blocked for all namespaces.
cc @mheon @giuseppe

Copy link
Member

Choose a reason for hiding this comment

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

It should work fine with crun, there is some code to handle joining namespaces not owned by the target user namespace. So it is mostly a decision whether we want to allow it or not (I think we should).

Copy link
Member

Choose a reason for hiding this comment

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

@giuseppe Are you saying we should allow mixing userns in containers that are part of the same pod?
AFAICT we added this limitation from the beginning #10589 just not properly enforced.

While I agree it can start doesn't it totally break the capabilities as the ownership is wrong, i.e. similar to described here https://blog.podman.io/2023/12/interaction-between-user-namespaces-and-capabilities/
Additionally files in /proc/sys will have the wrong ownership:

$ podman pod create --pod-id-file /tmp/pod1 --userns keep-id 
55dff018031a5f8282983a7657e815633756b2adc47049cd6055631429f20d9f
$ podman run --pod-id-file /tmp/pod1 --rm quay.io/libpod/testimage:20241011 ls -l /proc/sys/net/
total 0
dr-xr-xr-x    1 root     root             0 Nov  4 11:22 core
dr-xr-xr-x    1 root     root             0 Nov  4 11:22 ipv4
dr-xr-xr-x    1 root     root             0 Nov  4 11:22 ipv6
dr-xr-xr-x    1 root     root             0 Nov  4 11:22 mptcp
dr-xr-xr-x    1 root     root             0 Nov  4 11:22 netfilter
dr-xr-xr-x    1 root     root             0 Nov  4 11:22 unix
$ podman run --pod-id-file /tmp/pod1 --rm --userns host  quay.io/libpod/testimage:20241011 ls -l /proc/sys/net/
total 0
dr-xr-xr-x    1 bin      bin              0 Nov  4 11:22 core
dr-xr-xr-x    1 bin      bin              0 Nov  4 11:22 ipv4
dr-xr-xr-x    1 bin      bin              0 Nov  4 11:22 ipv6
dr-xr-xr-x    1 bin      bin              0 Nov  4 11:22 mptcp
dr-xr-xr-x    1 bin      bin              0 Nov  4 11:22 netfilter
dr-xr-xr-x    1 bin      bin              0 Nov  4 11:22 unix

So this seems like a major problem as most users won't be aware of this.

Copy link
Member

Choose a reason for hiding this comment

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

when we first added the feature, it was not possible to mix namespaces (it requires the new mount API in the kernel), so that was the root reason for not allowing it.

Sure you get something weird, like files ownership, but that might be useful in some cases for power users? IIRC Kubernetes doesn't allow it, and they are discussing whether allow netns=host with user namespaces.

Comment on lines 267 to 282
case specgen.Private:
if err := userNSConflictsWithPod(pod, s.UserNS.NSMode); err != nil {
return nil, err
}
case specgen.Auto:
if err := userNSConflictsWithPod(pod, s.UserNS.NSMode); err != nil {
return nil, err
}
case specgen.NoMap:
if err := userNSConflictsWithPod(pod, s.UserNS.NSMode); err != nil {
return nil, err
}
case specgen.Path:
if err := userNSConflictsWithPod(pod, s.UserNS.NSMode); err != nil {
return nil, err
}
Copy link
Member

Choose a reason for hiding this comment

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

That is a bit inelegant and does not scale well. IT could be made much simpler by moving this out of the switch case.

since you already check the userns mode != FromPod in userNSConflictsWithPod() all you need to do is call userNSConflictsWithPod(pod,s.UserNS.NSMode) once before or after this switch case block.

Comment on lines 686 to 687
cleanup := podmanTest.Podman([]string{"pod", "rm", "-f", "testing123"})
cleanup.WaitWithDefaultTimeout()
Copy link
Member

Choose a reason for hiding this comment

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

this is missing a Expect(session).Should(Exit(0)) to make sure the command worked.

New test code however should just use PodmanExitCleanly which combines this all into a one liner

podmanTest.PodmanExitCleanly("pod", "rm", "-f", "testing123")

Comment on lines 694 to 695
cleanup = podmanTest.Podman([]string{"pod", "rm", "-f", "testing1234"})
cleanup.WaitWithDefaultTimeout()
Copy link
Member

Choose a reason for hiding this comment

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

you don't need to do final cleanup in e2e tests so this can be omitted

done

# --userns and --pod have a different error message format
run_podman pod create --name userns-pod-test
Copy link
Member

Choose a reason for hiding this comment

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

don't hard code names in system tests, this test runs in parallel with other so names can conflict

use podname=p-$(safename) and then use this var as name to create/remove

Copy link
Author

Choose a reason for hiding this comment

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

resolved

if pod != nil && pod.HasInfraContainer() && (pod.SharesIPC() || pod.SharesNet()) {
// FromPod mode is allowed - container inherits from pod
if mode != specgen.FromPod {
return fmt.Errorf("cannot set user namespace mappings that differ from pod: %w", define.ErrInvalidArg)
Copy link
Member

Choose a reason for hiding this comment

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

looking at the error mappings might be confusing, cannot set user namespace mode when joining pod with infra container is more clear I think?

Copy link
Author

Choose a reason for hiding this comment

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

thanks for the feedback. will resolve all at its earliest

@0xDVC 0xDVC force-pushed the fix-26848-userns-pod-validation branch 3 times, most recently from 21962d1 to 36709ee Compare November 5, 2025 10:57
@0xDVC 0xDVC requested a review from Luap99 November 5, 2025 13:21
Copy link
Member

@Honny1 Honny1 left a comment

Choose a reason for hiding this comment

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

Code LGTM. I have only one non-blocking style nit.

0xDVC added 2 commits November 7, 2025 05:00
- remove old CLI validation that only checked --pod flag
- add validation in namespaces.go to catch all paths (cli, quadlet, api)
- block userns mixing for all pods with infra, not just ipc/net
- update error message to be clearer
- fix test cleanup to use PodmanExitCleanly()
- use dynamic pod names in system tests to avoid conflicts

fixes containers#26848

Signed-off-by: 0xdvc <neilohene@gmail.com>
@0xDVC 0xDVC force-pushed the fix-26848-userns-pod-validation branch from 2c5aaa2 to afc6464 Compare November 7, 2025 05:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Per Container User Namespaces in Pod Quadlets?

6 participants