- Is it alright to create a user for those respective UIDs/GIDs on the host in order to have a more meaningful output for ls and friends?
Yes it is alright. However you must ensure that such user has no right over anything in the host system:
- Disabled access or password,
- No usable login shell,
- No writeable home directory.
Be also sure to not create any duplicate in your user names.
Here is a sample script, taking the guest's /etc/passwd
and /etc/group
files to create the corresponding users in the host system. All names are prefixed with the container name, and all IDs are increased using the given value to match container's UIDs:
#! /bin/sh
# Path to guest's `/etc' directory.
guest_etc=/var/lib/lxc/mycontainer/rootfs/etc
# Guest's name, used as login prefix and inside GECOS field.
guest_name=mycontainer
# Increment to be applied to UIDs and GIDs (= range start).
uid_incr=100000
gid_incr=$uid_incr
guest_passwd=${guest_etc}/passwd
guest_group=${guest_etc}/group
exec <$guest_group
while IFS=":" read name pass gid null; do
gid_new=$( expr $gid + $gid_incr )
if ! getent group $gid_new >/dev/null; then
addgroup --system --gid $gid_new "${guest_name}_${name}"
fi
done
exec <$guest_passwd
while IFS=":" read login pass uid gid gecos null; do
uid_new=$( expr $uid + $uid_incr )
gid_new=$( expr $gid + $gid_incr )
if ! getent passwd $uid_new >/dev/null; then
adduser --system --home /nonexistent --no-create-home \
--shell /bin/nologin --uid $uid_new --gid $gid_new \
--gecos "\"$guest_name container user (${gecos})\"" \
"${guest_name}_${login}"
fi
done
The warnings regarding the inaccessible home directory are normal and expected: this is the actual purpose of /nonexistent
to not exist.
- is there a way to make those files/folder accessible to the host user
who "owns" the userns, i.e. john in our case? And if so, is the only
sensible method to create a group shared between those valid users
inside the subordinate range and and the userns "owner" and set the
permissions accordingly? Well, or ACLs, obviously.
This should really worth a separate question IMO.
Since the container's content is owned by different UIDs than the container owner UID, then it is not accessible to him. I can imagine an exception to this rule for subusers, but there is currently none I am aware of (I've created a related question a few time ago, but no answer yet).
The files /etc/subuid
and /etc/subgid
are currently only used by newuidmap
(1) to allow or deny the switch from one UID/GID to another of a given process. It does not give the range owner any other right.
Therefore, the solution to such issue should be designed on a case-per-case basis. Beware however with you ACL idea: let's say you put some ACLs on the container's files to allow your host's UID 1000 to read them, this means that the container's user with container's UID 1000 will also have the same level of privilege...
In other words: may root owned unprivileged containers be "less
unprivileged" than ones owned by standard accounts?
I don't think so. What matters is what's in /proc/$PID/uid_map
of processes in user namespace of the container, not what's in /etc/subuid
. Suppose you execute the following from the initial user namespace (that is, not from the container) for $PID
of a process running in the container:
$ cat /proc/$PID/uid_map
0 200000 1000
This means that UID range [0-1000)
of the process $PID will be mapped to UID range [200000-201000)
outside of its user namespace (of the container). UIDs outside of the [200000-201000)
range will be mapped to 65534 ($(cat /proc/sys/kernel/overflowuid)
) in the container. This can happen for instance if you don't create a new PID namespace. In that case, the process in the container would see processes outside, but their UID would be 65534.
So with proper UID mapping, even if the container is started by root, its processes will have unprivileged UIDs outside of it.
Subordinate UIDs in /etc/subuid
are not in any way linked to a single UID outside. The purpose of this file is to allow unprivileged users to start containers which use more than one UID (which is the case for most Linux operating systems). By default, you can only map your UID if you're unprivileged user. That is, if your UID is 1000 and $PID
refers to a process in the container, you can only do
echo "$N 1000 1" >/proc/$PID/uid_map
for any $N
as unprivileged user. Everything else is not permitted. If you could map longer range, i.e.
echo "$N 1000 50" >/proc/$PID/uid_map
you would gain access to UIDs [1000-1050)
outside of the container through the container. And of course, if you could change start of outer UID range, you'd have easy way to get root. So /etc/subuid
defines outer ranges which you are allowed to use. This file is used by newuidmap
which is setuid root.
$ cat /etc/subuid
woky:200000:50
$ echo '0 200000 50' >/proc/$PID/uid_map
-bash: echo: write error: Operation not permitted
$ newuidmap $PID 0 200000 50
$ # success
The details are much more complicated and I'm probably not the proper person to explain it but I guess it's better to have no answer. :-) You might want to check man pages user_namespaces(7)
and newuidmap(1)
, and my own research First process in a new Linux user namespace needs to call setuid()? . Unfortunately, I'm not entirely sure how LXC uses this file.
Best Answer
Yes, this can be configured in
/etc/login.defs
using theSUB_UID_MIN
,SUB_UID_MAX
andSUB_UID_COUNT
parameters and theirSUB_GID_*
counterparts.All these parameters are described in
login.defs
(5) man page, however the default values given in this documentation are not true on all platforms.According to the man page, a behavior similar to the one you describe should be used by default with ranges set as multiple of 10000. However this would cause issues with some system accounts and groups which are affected UID and GID above 65000 on certain platforms (Debian and derivatives for instance). Therefore the default range 65536 has been enforced with the side-effect you know.
So, to get more human readable ranges, you can explicitly set the values below in your
/etc/login.defs
file:By the way, the files
/etc/subuid
and/etc/subgid
can indeed be manually edited, but ensure that ranges do not overlap and be sure to not mess with any process, file or any other object ownership. In other words, while it is safe to do it before actually using the range, afterward it will require some special care.