image-tools icon indicating copy to clipboard operation
image-tools copied to clipboard

oci-unpack to handle UID/GID mappings

Open glestaris opened this issue 8 years ago • 4 comments

As discussed lately in https://github.com/opencontainers/image-tools/pull/3, oci-unpack could also be handling UID/GID translation to prepare the unpacked image (rootfs) for a container that uses a user namespace with UID/GID mappings. There are, so far, the following use cases:

  1. Multiple mappings: the UID/GIDs defined in the tar-ball need to be translated accordingly.
  2. Single mapped user (host user X): all the files and directories of the rootfs are owned by X.
  3. Mapped users are less than the users defined in the tar-ball (by @cyphar)

I would propose extiending the oci-unpack interface by adding:

*--uid-mapping <Namespace UID>:<Host UID>:<Size> (similar to the /proc/$PID/uid_map structure). It can be provided multiple times.

  • --gid-mapping which handles the GID mappings similarly.
  • --fallback-uid <Namespace UID> When provided, if a tar entry UID is not mapped the unpacked file will be owned by <Namespace UID>. If the flag is not provided and a unmapped UID is encountered, oci-unpack should fail.

Grootfs is implementing the --uid-mapping and --gid-mapping flags but I would prefer this translation logic to live in oci-unpack.

glestaris avatar Oct 03 '16 22:10 glestaris

On Mon, Oct 03, 2016 at 03:05:50PM -0700, George Lestaris wrote:

*--uid-mapping <Host UID>:<Namespace UID>:<Size> (similar to the /proc/$PID/uid_map structure). It can be provided multiple times.

  • --gid-mapping which handles the GID mappings similarly.
  • --fallback-uid <Namespace UID> When provided, if a tar entry UID is not mapped the unpacked file will be owned by <Namespace UID>. If the flag is not provided and a unmapped UID is encountered, oci-unpack should fail.

I don't think you need the first two, and --fallback-uid can always be the current user. oci-unpack would need to learn an option to switch between:

  1. Always chown, die on errors (this is #3's --same-owner).
  2. Always chown, warn on errors (maybe --try-same-owner?).
  3. Never chown (this is #3's default for non-root users, and would match --no-same-owner).

Then you can achieve your desired semantics by unpacking in a user namespace that has your intended UID/GID mappings.

wking avatar Oct 03 '16 22:10 wking

I agree that we can avoid something like --fallback-user. However, I think having oci-unpack dealing with translation is important. Imagine the following workflow:

oci-download --ref 3.2.5 oci://registry.opencontainers.org/redis ./redis-image
oci-unpack --ref 3.2.5 --uid-mapping 1000:0:1000 ./redis-image ./redis-bundle
cd ./redis-bundle
oci-runtime-tool generate --uidmappings 1000:0:1000 --args redis-server
runc create my-redis

If we have to create the user namespace before unpacking the rootfs we would either have to use unshare or call oci-unpack through runc (which would probably mean calling runc twice).

glestaris avatar Oct 04 '16 08:10 glestaris

On Tue, Oct 04, 2016 at 01:30:55AM -0700, George Lestaris wrote:

oci-download --ref 3.2.5 oci://registry.opencontainers.org/redis ./redis-image
oci-unpack --ref 3.2.5 --uid-mapping 1000:0:1000 ./redis-image ./redis-bundle
cd ./redis-bundle
oci-runtime-tool generate --uidmappings 1000:0:1000 --args redis-server
runc create my-redis

If we have to create the user namespace before unpacking the rootfs we would either have to use unshare or call oci-unpack through runc (which would probably mean calling runc twice).

I don't mind calling unshare or runC for this. And the OCI spec is a bit tedious, but here's the ccon version:

ccon -s '

{ "version": "0.1.0", "namespaces": { "user": { "setgroups": true, "uidMappings": [ {"containerID": 0, "hostID": 2000, "size": 10} ], "gidMappings": [ {"containerID": 0, "hostID": 3000, "size": 10} ] } }, "process": { "user": { "uid": 0, "gid": 0 }, "args": ["sh", "-c", "touch /tmp/a && chown 1:1 /tmp/a"] } }'

ls -l /tmp/a

-rw-r--r-- 1 2001 3001 0 Oct 4 10:11 /tmp/a

That's more typing than a two command line options, but you could wrap it up in a script if you don't want to retype it. And it makes it clear that without the ability to create such user-namespace mappings to execute the container, there's not much point in such a mapped unpacking.

wking avatar Oct 04 '16 17:10 wking

To be honest, all I really want for umoci is if I can use an []idtools.IDMap (or whatever the runtime-spec equivalent is) to specify what translation I would like during unpacking. That's all I'm looking for here, because currently you need to run umoci as root (which is simply a non-starter for building things within OBS or KIWI).

The discussion in #3 about whether it can ever be "correct" to output such a rootfs is missing the point IMO. What matters is that I can set the correct owners inside the diff layers (whether or not I had to cheat to do it is a separate issue -- and outside the concern of the extraction API).

cyphar avatar Nov 05 '16 15:11 cyphar