Podman: Volumes always owned by root

Created on 11 Apr 2019  ยท  39Comments  ยท  Source: containers/podman

Is this a BUG REPORT or FEATURE REQUEST? (leave only one on its own line)

/kind bug

Description

Volumes are always owned by root instead of inheriting owner and group from the host.

Steps to reproduce the issue:

  1. Run podman run --rm -v "$HOME:$HOME" alpine ls -l "$HOME/.."
total 4
drwx------   35 root     root          4096 Apr 11 07:55 fnkr
  1. Run podman run --rm -v "$HOME:$HOME" --user "$(id -u):$(id -g)" alpine ls -l "$(dirname $HOME)"
total 4
drwx------   35 root     root          4096 Apr 11 07:55 fnkr

Describe the results you received:

The mount is owned by root.

Describe the results you expected:

The mount should be owned by the current user in both cases. (At least this is what Docker does.)

โžœ docker run --rm -v "$HOME:$HOME" alpine ls -l "$HOME/.."
total 4
drwx------   35 1001     1001          4096 Apr 11 08:01 fnkr
โžœ docker run --rm -v "$HOME:$HOME" --user "$(id -u):$(id -g)" alpine ls -l "$(dirname $HOME)"
total 4
drwx------   35 1001     1001          4096 Apr 11 08:01 fnkr

Additional information you deem important (e.g. issue happens only occasionally):

100% reproducible. Probably related to https://github.com/containers/libpod/pull/2643 and https://github.com/containers/libpod/issues/2634.

Output of podman version:

โžœ podman version                                                                             
Version:            1.2.0
RemoteAPI Version:  1
Go Version:         go1.11.5
OS/Arch:            linux/amd64

Output of podman info --debug:

debug:
  compiler: gc
  git commit: ""
  go version: go1.11.5
  podman version: 1.2.0
host:
  BuildahVersion: 1.7.2
  Conmon:
    package: podman-1.2.0-2.git3bd528e.fc29.x86_64
    path: /usr/libexec/podman/conmon
    version: 'conmon version 1.12.0-dev, commit: d88bb0e63cb70f9787a8e410716924f380af361f'
  Distribution:
    distribution: fedora
    version: "29"
  MemFree: 10356088832
  MemTotal: 25145073664
  OCIRuntime:
    package: runc-1.0.0-68.dev.git6635b4f.fc29.x86_64
    path: /usr/bin/runc
    version: |-
      runc version 1.0.0-rc6+dev
      commit: ef9132178ccc3d2775d4fb51f1e431f30cac1398-dirty
      spec: 1.0.1-dev
  SwapFree: 0
  SwapTotal: 0
  arch: amd64
  cpus: 8
  hostname: ping
  kernel: 5.0.6-200.fc29.x86_64
  os: linux
  rootless: true
  uptime: 1h 54m 36.7s (Approximately 0.04 days)
insecure registries:
  registries: []
registries:
  registries:
  - docker.io
  - registry.fedoraproject.org
  - quay.io
  - registry.access.redhat.com
  - registry.centos.org
store:
  ConfigFile: /home/fnkr/.config/containers/storage.conf
  ContainerStore:
    number: 1
  GraphDriverName: overlay
  GraphOptions:
  - overlay.mount_program=/usr/bin/fuse-overlayfs
  GraphRoot: /home/fnkr/.local/share/containers/storage
  GraphStatus:
    Backing Filesystem: extfs
    Native Overlay Diff: "false"
    Supports d_type: "true"
    Using metacopy: "false"
  ImageStore:
    number: 26
  RunRoot: /run/user/1001
  VolumePath: /home/fnkr/.local/share/containers/storage/volumes

Additional environment details (AWS, VirtualBox, physical, etc.):

I'm using Fedora Workstation 29.

kinbug

Most helpful comment

I like it, I would love to make this easier for non expert users.
Seems like users are running non rootl containers, where they expect their UID==UID in the container and others expect their UID == 0 inside the container. The desktop team has built toolbox which is a wrapper around podman but does the UID==UID mapping.

All 39 comments

Podman by default in rootless mode makes the UID of the user running the command ROOT inside of the container. That means that when you look at the UID of the running process it will be 0, even though the process is really running as your UID. Also any files with your UID as owner or group will be seen as UID==0 while in the container. Any file actually owned by a UID==0 will be seen as -1.

So this is not a bug.
What are you hoping to do in the container?

Hi @rhatdan, thanks for your response. Is there any way to use --user together with volumes? In my use case the name, group, UID, GID and home dir of the user are relevant and I need to access certain files from host and container processes. This is a simplified example of what I'm doing (works with Docker):

--user=$UID --volume="$HOME/build/passwd:/etc/passwd:ro" --volume="$HOME/build:$HOME/build" --workdir="$HOME/build"

If you eliminate the --user=$UID it should work for you, but you will think you are running as root inside of the container. Another option is to use the User Namespace differently.

I am going to guess that your UID == 1000, Current
And you have a line like this in the /etc/subuid file.
fnkr:100000:65536
If you ran podman with the following commands
$ podman run --uidmap 0:100000:1000 --uidmap 1000:1000:1 --uidmap 1001:101000:64536 ...
Then you will get the environment you envision.
You will have to play with the UID Ranges above to get this correct.

@giuseppe I wonder if we should make this an option for podman,
podman --uidmap user, which would do the above automatically.

โžœ podman run --uidmap 0:100000:1000 --uidmap 1000:1000:1 --uidmap 1001:101000:64536 alpne ls 
Error: error creating libpod runtime: there might not be enough IDs available in the namespace (requested 100000:100000 for /home/fnkr/.local/share/containers/storage/overlay/l): chown /home/fnkr/.local/share/containers/storage/overlay/l: invalid argument

I changed the command slightly to get it working, but now files from the volume are owned by nobody:

โžœ podman run --rm -v="$PWD:$PWD" -w="$PWD" --uidmap=0:10000:$((UID)) --uidmap=$UID:$UID:1 --uidmap=$((UID+1)):$((UID+10001)):$((55536-UID)) alpine ls -l -n
total 0
-rw-r--r--    1 65534    65534            0 Apr 12 17:47 test

โžœ ls -l -n       
total 0
-rw-r--r--. 1 1001 1001 0 Apr 12 17:47 test

I like it, I would love to make this easier for non expert users.
Seems like users are running non rootl containers, where they expect their UID==UID in the container and others expect their UID == 0 inside the container. The desktop team has built toolbox which is a wrapper around podman but does the UID==UID mapping.

podman run --match-uid maybe?

I would want something to indicate this is usernamespace --userns-map-uid

we could do that, it should be pretty easy. We need to provide a preconfigured mapping for the namespace. We also need --user to be configured though

We could default to the logged-in user's UID

@giuseppe Why would we need --user? I still am fine with them being root when the container starts and then remapping to their user.

@mheon I don't think we should change the default. If we had a flag that changed the default then you could toggle the flag via an environment variable.

We need user for the effective setresuid in the oci runtime, that needs to happen after the second mapping is in place.

Hi,

I couldn't figure out how to fix this yet. If I use --uidmap the UID/GID of volumes is always 65534.

โžœ podman run --rm -v="$PWD:$PWD" -w="$PWD" --uidmap=0:10000:$((UID)) --uidmap=$UID:$UID:1 --uidmap=$((UID+1)):$((UID+10001)):$((55536-UID)) alpine ls -l -n
total 0
-rw-r--r--    1 65534    65534            0 Apr 12 17:47 test

โžœ ls -l -n       
total 0
-rw-r--r--. 1 1001 1001 0 Apr 12 17:47 test

Is uid 1001 mapped into your container? If not it will show up as 65534

Yes, it is ($UID is 1001). This is how the command is expanded:

โžœ podman run --rm -v="$PWD:$PWD" -w "$PWD" --uidmap=0:10000:1001 --uidmap=1001:1001:1 --uidmap=1002:11002:54535 alpine ls -l -n

Here is another example that doesn't work either:

โžœ podman run --rm -v="$PWD:$PWD" -w "$PWD" --uidmap=0:10000:10 --uidmap=1000:1000:1000 alpine ls -l -n

@fnk

@giuseppe I am seeing this also. Any ideas?
podman run --rm -v="$PWD:$PWD" --privileged -w "$PWD" --uidmap=0:10000:3267 --uidmap=3267:3267:1 alpine ls -l -n

Is showing me the files in my homedir as:
-rw-rw-r-- 1 65534 65534 13426 Apr 17 12:30 run.bats
-rw-rw-r-- 1 65534 65534 1212 Apr 15 20:15 secrets.bats
-rw-rw-r-- 1 65534 65534 2597 Apr 15 20:15 selinux.bats
drwxrwxr-x 2 65534 65534 4096 Sep 17 2018 serve

$ ls -l -n umount.bats 
-rw-rw-r--. 1 3267 3267 1780 Apr 15 16:15 umount.bats
$ podman run --rm -v="$PWD:$PWD" --privileged -w "$PWD" --uidmap=0:10000:3267 --uidmap=3267:3267:1 --uidmap=3268:13268:100 alpine ls -l -n umount.bats
-rw-rw-r--    1 65534    65534         1780 Apr 15 20:15 umount.bats
$ podman run --rm -v="$PWD:$PWD" --privileged -w "$PWD" --uidmap=0:10000:3267 --uidmap=3267:3267:1 --uidmap=3268:13268:100 alpine cat /proc/self/uid_map
         0      10000       3267
      3267       3267          1
      3268      13268        100

root from the first namespace (which is your user) is not mapped inside the new namespace, you need to do --uidmap=3267:0:1

So the issue here is that my command is executing in the second namespace.

we need to use something like fedora-toolbox: https://github.com/debarshiray/toolbox/blob/master/toolbox#L732-L734

Very confusing for the user.

@rhatdan agreed. We need to do this automatically:

user_id_real=$(id -u)
max_uid_count=65536
max_minus_uid=$((max_uid_count - user_id_real))
uid_plus_one=$((user_id_real + 1))
podman run --rm -v="$PWD:$PWD" --privileged -w "$PWD" --uidmap "$user_id_real":0:1  --uidmap 0:1:"$user_id_real" --uidmap "$uid_plus_one":"$uid_plus_one":"$max_minus_uid"  alpine ls -l -n

To allow for users above 65536 you will need something like:

user_id_real=$(id -u)
max_uid_count=65536
max_minus_uid=$((max_uid_count - user_id_real))
uid_plus_one=$((user_id_real + 1))
if $user_id_real < 65536 ; then
  podman run --rm -v="$PWD:$PWD" --privileged -w "$PWD" --uidmap "$user_id_real":0:1 --uidmap 0:1:"$user_id_real" --uidmap "$uid_plus_one":"$uid_plus_one":"$max_minus_uid"  alpine ls -l -n
else
  podman run --rm -v="$PWD:$PWD" --privileged -w "$PWD" --uidmap "$user_id_real":0:1 --uidmap 0:1:65536 alpine ls -l -n
fi

Since I keep getting yelled at for recommending --privileged, I'm trying to work out how I can mount a volume unprivileged such that the root user in the container writes files to that volume as the user who started the container. (In other words, when the container stops, the files that were written are owned by the user who started the container).

Here's what I've tried:

podman run --rm -it -v "/tmp:/tmp" alpine touch /tmp/test.txt

Here's what I get:

touch: text.txt: Permission denied

But, magically, it works if I add --privileged:

podman run --rm -it --privileged -v "/tmp:/tmp" alpine touch /tmp/test.txt

Am I violating security best practices by adding --privileged? Or is it safe because this is podman? I'm confused. If it is safe, it would be nice if the documentation would say so.

Are you running Podman rootless, or with root?

The problem is likely SELinux, given that the user in question should have
permissions to write in /tmp otherwise. Privileged relaxes the container's
SELinux constraints, so it makes sense that it resolves the issue.

If you're running Podman rootless, using privileged increases the
container's ability to interact with the system (more of the host is
mounted into the container, SELinux and Seccomp restrictions are relaxed,
etc), but it still has no privileges the user that launched the container
did not.

If you only need to make files and don't want the other effects of
privileged, security-opt label=disable might work better. You can also use
:z on the volume mounts to label them for container use, but I'd only
recommend that for folders you made explicitly to share with the container
(relabelling /tmp for example would probably break your system)

On Sat, Apr 27, 2019, 05:12 Dan Allen notifications@github.com wrote:

Since I keep getting yelled at for recommending --privileged, I'm trying
to work out how I can mount a volume unprivileged such that the root user
in the container writes files to that volume as the user who started the
container. (In other words, when the container stops, the files that were
written are owned by the user who started the container).

Here's what I've tried:

podman run --rm -it -v "/tmp:/tmp" alpine touch /tmp/test.txt

Here's what I get:

touch: text.txt: Permission denied

But, magically, it works if I add --privileged:

podman run --rm -it --privileged -v "/tmp:/tmp" alpine touch /tmp/test.txt

Am I violating security best practices by adding --privileged? Or is it
safe because this is podman? I'm confused. If it is safe, it would be nice
if the documentation would say so.

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/containers/libpod/issues/2898#issuecomment-487269663,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AB3AOCA7DD2U4YMDOUKMVZ3PSQKHFANCNFSM4HFEIAOA
.

If you're running Podman rootless, using privileged increases the container's ability to interact with the system (more of the host is mounted into the container, SELinux and Seccomp restrictions are relaxed, etc), but it still has no privileges the user that launched the container did not.

That is exactly what I needed to know. And it's also exactly the behavior I need to make volumes viable. (The use case is to invoke the container as though it is a local command to save the user from having to install a toolchain).

Is there anywhere in the documentation I can link to that makes this assertion?

You might want to look at the gnome toolbox package, which is designed for pretty much your use case. It wraps podman to act in a behaviour where it gives the users their own container, which they can become root and install what ever software they want, but does not effect the host OS.

I wrote a series of blogs on podman and user namespace out on opensource.com

https://opensource.com/users/rhatdan

@rhatdan I appreciate that suggestion, and I will certainly look into it for my own use.

However, when it comes to providing instructions for users who want to run a piece of software without having to install the whole toolchain, that's asking too much of them. They just want to know what command they have to type into the console to be able to run the application. It's a means to an end. And for that, the podman command alone is what they're after. And it's something that requires very little explanation (once we sort out the right arguments for them to use).

I am not arguing against the use of podman. Podman is the tool for a user to install a containerized application. That is why we are building it.
If a user wants to install RPMs on his host and is not allowed to run as root, then toolbox wrapping of podman becomes an interesting way to allow users to to do this use case.
Obviously podman can do this, since toolbox is just wrapping it, but toolbox makes different assumptions on how the user runs the container.

@mojavelinux We've mentioned that rootless uses no additional privileges in a few blog posts, but nothing in the README or manpages.

That sounds like a big omission on our part, so I'll look into getting something written up for the README first, and then maybe the manpages

@mojavelinux I took a first pass at adding a description in #3038 - would appreciate your checking to see if this would have adequately answered your question, or if we need to include more detail.

@mheon I very appreciate you following up to add information about this to the docs. However, the paragraph you added doesn't really enhance my knowledge or understanding in anyway. Specifically, I don't see any mention of --privileged and how it pertains to volume mounts. That's really the issue at hand here. I would expect something like:

Running rootless has the advantage that the container has no more access to the host system than the user who launched it. Yet, by default, it's even more restricted then that. To give the container the same permission the host system as the user who launched it, such as the ability to mount volumes read/write, you'll need to add the --privileged flag. Bear in mind that, with rootless podman, this does not grant the container privileged beyond what the user who launched it has. In other words, the behavior diffs from the same flag in Docker, which in contrast does violate that permission boundary.

Honestly, I think it was a poor decision to reuse the same flag as in Docker since clearly it has very different implications. But for consistency, I could see the benefits if it is properly documented.

A lot of the implications are still the same - we're still relaxing Seccomp, SELinux, and restrictions on mounts in /proc and /sys. The biggest difference is the starting point in terms of permissions and capabilities - we can grant you additional privileges with --privileged, but nothing more than what you started with in the first place.

(I should probably put that bit in the readme too)

where are we on this one?

3038 merged with documentation, so I think this might be fixed

Actually, I think @giuseppe solved our other issues with a --userns option

I'm going to close as we've added documentation and https://github.com/containers/libpod/pull/3196 added a way to retain UIDs

The --userns=keep-id thing did not work for me, while my volume had the right uid, the rest of the system was also owned by it instead of root. While the solution by @stevenwhately works perfectly for me, I will repeat it here in sh syntax for anyone stumbling across this:

user_id_real=$(id -u)
max_uid_count=65536
max_minus_uid=$((max_uid_count - user_id_real))
uid_plus_one=$((user_id_real + 1))
if [ $user_id_real -lt 65536 ]; then
    extra_args="--privileged --uidmap $user_id_real:0:1 --uidmap 0:1:$user_id_real --uidmap $uid_plus_one:$uid_plus_one:$max_minus_uid"
else
    extra_args="--privileged --uidmap $user_id_real:0:1 --uidmap 0:1:65536"
fi
Was this page helpful?
0 / 5 - 0 ratings