Skip to content
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

Volumes always owned by root #2898

Closed
fnkr opened this issue Apr 11, 2019 · 41 comments
Closed

Volumes always owned by root #2898

fnkr opened this issue Apr 11, 2019 · 41 comments
Labels
kind/bug Categorizes issue or PR as related to a bug. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments.

Comments

@fnkr
Copy link

fnkr commented Apr 11, 2019

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 #2643 and #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.

@openshift-ci-robot openshift-ci-robot added the kind/bug Categorizes issue or PR as related to a bug. label Apr 11, 2019
@rhatdan
Copy link
Member

rhatdan commented Apr 11, 2019

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?

@rhatdan rhatdan closed this as completed Apr 11, 2019
@fnkr
Copy link
Author

fnkr commented Apr 12, 2019

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"

@rhatdan
Copy link
Member

rhatdan commented Apr 12, 2019

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.

@fnkr
Copy link
Author

fnkr commented Apr 12, 2019

➜ 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

@rhatdan
Copy link
Member

rhatdan commented Apr 12, 2019

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.

@mheon
Copy link
Member

mheon commented Apr 12, 2019

podman run --match-uid maybe?

@rhatdan
Copy link
Member

rhatdan commented Apr 12, 2019

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

@giuseppe
Copy link
Member

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

@mheon
Copy link
Member

mheon commented Apr 12, 2019

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

@rhatdan
Copy link
Member

rhatdan commented Apr 12, 2019

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

@rhatdan
Copy link
Member

rhatdan commented Apr 12, 2019

@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.

@giuseppe
Copy link
Member

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

@fnkr
Copy link
Author

fnkr commented Apr 16, 2019

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

@rhatdan
Copy link
Member

rhatdan commented Apr 16, 2019

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

@fnkr
Copy link
Author

fnkr commented Apr 16, 2019

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

@rhatdan
Copy link
Member

rhatdan commented Apr 17, 2019

@fnk

@rhatdan rhatdan reopened this Apr 17, 2019
@rhatdan
Copy link
Member

rhatdan commented Apr 17, 2019

@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

@giuseppe
Copy link
Member

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

@rhatdan
Copy link
Member

rhatdan commented Apr 17, 2019

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

@giuseppe
Copy link
Member

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

@rhatdan
Copy link
Member

rhatdan commented Apr 17, 2019

Very confusing for the user.

@giuseppe
Copy link
Member

@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

@stevenwhately
Copy link

stevenwhately commented Apr 21, 2019

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

@mojavelinux
Copy link

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.

@mheon
Copy link
Member

mheon commented Apr 27, 2019 via email

@mojavelinux
Copy link

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?

@rhatdan
Copy link
Member

rhatdan commented Apr 28, 2019

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

@mojavelinux
Copy link

mojavelinux commented Apr 28, 2019

@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).

@rhatdan
Copy link
Member

rhatdan commented Apr 29, 2019

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.

@mheon
Copy link
Member

mheon commented Apr 29, 2019

@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

@mheon
Copy link
Member

mheon commented Apr 29, 2019

@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.

@mojavelinux
Copy link

@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.

@mheon
Copy link
Member

mheon commented Apr 29, 2019

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.

@mheon
Copy link
Member

mheon commented Apr 29, 2019

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

@baude
Copy link
Member

baude commented May 29, 2019

where are we on this one?

@mheon
Copy link
Member

mheon commented May 29, 2019

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

@mheon
Copy link
Member

mheon commented May 29, 2019

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

@mheon
Copy link
Member

mheon commented May 29, 2019

I'm going to close as we've added documentation and #3196 added a way to retain UIDs

@rkitover
Copy link

rkitover commented Jul 1, 2020

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

@Trass3r
Copy link

Trass3r commented Sep 2, 2021

Thanks this fixed my problems with typical VSCode dev containers.

    "remoteUser": "vscode",
    "runArgs": [
        "--userns=keep-id"
    ],

@ambrop72
Copy link

ambrop72 commented Oct 5, 2021

I think that I've found a simple solution for this. The idea is to NOT map root in the container to the running user on the host, but to map it to one of those large automatically assigned UIDs. In particular, map UIDs 0-999 in the container to automatically assigned UIDs, but map UID 1000 in the container to the host user's UID. Like this:

--uidmap 1000:0:1 --uidmap 0:1:1000

So if you now create a user with UID 1000 in the container (the first normal created user will get that UID), it will have full access to bind mounted folders owner by the host user.

@github-actions github-actions bot added the locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. label Sep 21, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/bug Categorizes issue or PR as related to a bug. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments.
Projects
None yet
Development

No branches or pull requests