-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
userns: do not use an intermediate mount namespace #2730
userns: do not use an intermediate mount namespace #2730
Conversation
But this means a non priv user can get to the images correct? This has the potential to allow information leak and opening up of more 777 directories for users to write into. |
The directories under Let's get #2716 first, then I will rebase on top of that and verify there is nothing accessible by an unprivileged user |
☔ The latest upstream changes (presumably #2716) made this pull request unmergeable. Please resolve the merge conflicts. |
d892dba
to
5e7caf7
Compare
I've verified there is nothing accessible to unprivileged users. All the directories that are owned by the final root in the container have mode 0700. Said so, we need to be more careful when we add more content in the storage directory. In any case, even if I like the way this could simplify the implementation and need to worry of different code paths, I don't want to be the guy who caused CVEs in the storage :-) here there is a third option, that depends on a patch in conmon: #2730 |
If we can work through the security issues, I am definitely in favor of this one - the simplification of one of the most complex parts of libpod is a wonderful side effect of the fix. |
agreed. Having an intermediate mount namespace will always be somehow fragile, and difficult to debug |
Is there a way we could at least add a test to prove that a world writable directory in containers/storage was not reachable via non root users. su NONROOT find $STORAGEPATH -perm -o+w |
good idea. We could add a test like:
where would be the best place to add it? More stuff we have in the storage, the better it would be |
I think adding this to libpod at least in the system tests. @edsantiago WDYT? |
fbc4a26
to
1bc2d9e
Compare
@rhatdan good idea; on my todo list for Monday, thanks. |
I've added a patch to test an unprivileged user cannot access files in the storage. We might need to add the check to more tests. @edsantiago could you review it? |
@nalind PTAL |
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.
I love that you're extending the BATS tests, thank you! Some gotchas inline; and also a broader question: why add this as a function in helpers.bash
? That would be appropriate if this were a general-purpose function useful for multiple subtests. This is a single independent one-time test, so I would recommend making it a new standalone .bats
test instead. Look at 000-TEMPLATE
, copy it to NNN-pick-a-name.bats
, and put the code inside a @test
context.
test/system/helpers.bash
Outdated
# Check that an unprivileged user cannot read or write to the storage | ||
function check_no_unprivileged_access() { | ||
GRAPH_ROOT=$(run_podman info --format json | jq .store.GraphRoot) | ||
RUN_ROOT=$(run_podman info --format json | jq .store.RunRoot) |
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.
Unfortunately, in the BATS world, run_podman | xxx
doesn't work. It has to be done as two steps, run_podman
then operating on $output
. And in these cases, I would probably write it as:
run_podman info --format '{{.storage.Graphroot}}' ! then the same for RunRoot
GRAPH_ROOT="$output"
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.
thanks! I've fixed it in the new version
test/system/helpers.bash
Outdated
function check_no_unprivileged_access() { | ||
GRAPH_ROOT=$(run_podman info --format json | jq .store.GraphRoot) | ||
RUN_ROOT=$(run_podman info --format json | jq .store.RunRoot) | ||
find $GRAPH_ROOT $RUN_ROOT -perm -o+w | while read i; do |
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.
Did you mean to include -type f
? Or ! -type l
? There are an awful lot of symlinks that don't really seem to be useful to test.
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.
no I meant that. I'd prefer to test as many files/directories as possible, if it turns to be too expensive we can tune it
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 I mean is: can you try running that find
command manually, with -ls
instead of -print
? I think you'll find that there are a lot of symlinks, because all symlinks are mode 777, but that's meaningless. There is no point whatsoever to testing those.
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.
a lot of them in my current storage are coming from busybox
, we could probably try to skip these as we are really testing the same thing multiple times. I'd still like though to test symlinks and that we don't have access to rm them
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.
Let me try another way: can you explain what it is you think you are testing by paying attention to symlinks? I think there's a major misunderstanding going on here. Let's say the find
produces output like this:
/x -> /y
What is the purpose of running any tests on /x
? It is the same as running on /y
, and:
- if
/y
is a writable file or directory, thefind
command will emit it as part of its output - if
/y
is not a writable file or directory, there's no point in testing it
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.
in the last version I've pushed, I am also checking for rm
.
In the example you've given /x -> /y
the unprivileged user could still be able to rm /x
but not having privileges for doing it on /y
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.
Permissions on /y
are irrelevant for rm
; only the parent directory permissions matter.
I'm working on a little bit of a rewrite; I'll push it when I'm comfortable with it. It might be in a few hours.
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.
and symlink ownership. But given anyway that we are hardcoding the user, it probably doesn't make sense to test symlinks this way and we can safely skip them
test/system/helpers.bash
Outdated
GRAPH_ROOT=$(run_podman info --format json | jq .store.GraphRoot) | ||
RUN_ROOT=$(run_podman info --format json | jq .store.RunRoot) | ||
find $GRAPH_ROOT $RUN_ROOT -perm -o+w | while read i; do | ||
if chroot --userspec 1000:1000 / bash -c 'chmod +w $(dirname $i); chmod +w $i; cat $i || echo hello > $i || echo hello > $i/test' 2> /dev/null; then |
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.
Careful with plain $i
! Any space in the filename or any parent directory will cause all of these to fail. The convention is to double-quote every reference: "$i"
. (It's even better to use find ... -print0 | xargs -0
, but that would be harder to read in this case.
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.
thanks, fixed now
1bc2d9e
to
99f0495
Compare
test/system/030-run.bats
Outdated
@test "podman run - basic tests --uidmapping" { | ||
run_podman --uidmapping 0:10000:10000 run $IMAGE true | ||
|
||
run_podman --uidmapping 0:10000:10000 -v foo:/foo run $IMAGE true |
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.
Neither of these work. Hint: you can test via PODMAN=/path/to/podman bats test/system/030-run.bats
There are other problems; I'm working on some modifications to the framework, will submit them as a PR on your PR.
99f0495
to
85e3f99
Compare
85e3f99
to
596ffa0
Compare
var fd *os.File | ||
fd, err = os.Open(fmt.Sprintf("/proc/%d/task/%d/ns/mnt", os.Getpid(), unix.Gettid())) | ||
// makeAccessible changes the path permission and each parent directory to have --x--x--x | ||
func makeAccessible(path string, uid, gid int) error { |
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.
@vrothberg @rhatdan @nalind this logic should probably be moved to containers/storage as it is not really specific to libpod
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.
SGTM
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.
Do we want to do this now, or merge this PR first and move later?
a684267
to
60f1bd5
Compare
Are there other paths under /var/lib/containers/storage that we don't want a non privileged user to read? Volumes directory? |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: edsantiago, giuseppe The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@giuseppe Are we good to merge here? |
I'd like to get this in before 1.2 |
60f1bd5
to
f575047
Compare
LGTM |
I'll ping @nalind in scrum to ask for a quick review |
☔ The latest upstream changes (presumably #2789) made this pull request unmergeable. Please resolve the merge conflicts. |
f575047
to
462e2b3
Compare
☔ The latest upstream changes (presumably #2575) made this pull request unmergeable. Please resolve the merge conflicts. |
Signed-off-by: Giuseppe Scrivano <[email protected]>
We have an issue in the current implementation where the cleanup process is not able to umount the storage as it is running in a separate namespace. Simplify the implementation for user namespaces by not using an intermediate mount namespace. For doing it, we need to relax the permissions on the parent directories and allow browsing them. Containers that are running without a user namespace, will still maintain mode 0700 on their directory. Signed-off-by: Giuseppe Scrivano <[email protected]>
Signed-off-by: Ed Santiago <[email protected]> Signed-off-by: Giuseppe Scrivano <[email protected]>
462e2b3
to
1ae8a5b
Compare
/lgtm |
We have an issue in the current implementation where the cleanup
process is not able to umount the storage as it is running in a
separate namespace.
Simplify the implementation for user namespaces by not using an
intermediate mount namespace. For doing it, we need to relax the
permissions on the parent directories and allow browsing
them. Containers that are running without a user namespace, will still
maintain mode 0700 on their directory.
Alternative for: #2728
Signed-off-by: Giuseppe Scrivano [email protected]