Thread (51 messages) 51 messages, 8 authors, 2020-03-02

Re: [PATCH v3 00/25] user_namespace: introduce fsid mappings

From: James Bottomley <James.Bottomley@HansenPartnership.com>
Date: 2020-02-18 23:51:09
Also in: linux-fsdevel, linux-security-module, lkml

On Tue, 2020-02-18 at 15:33 +0100, Christian Brauner wrote:
In the usual case of running an unprivileged container we will have
setup an id mapping, e.g. 0 100000 100000. The on-disk mapping will
correspond to this id mapping, i.e. all files which we want to appear
as 0:0 inside the user namespace will be chowned to 100000:100000 on
the host. This works, because whenever the kernel needs to do a
filesystem access it will lookup the corresponding uid and gid in the
idmapping tables of the container. Now think about the case where we
want to have an id mapping of 0 100000 100000 but an on-disk mapping
of 0 300000 100000 which is needed to e.g. share a single on-disk
mapping with multiple containers that all have different id mappings.
This will be problematic. Whenever a filesystem access is requested,
the kernel will now try to lookup a mapping for 300000 in the id
mapping tables of the user namespace but since there is none the
files will appear to be owned by the overflow id, i.e. usually
65534:65534 or nobody:nogroup.

With fsid mappings we can solve this by writing an id mapping of 0
100000 100000 and an fsid mapping of 0 300000 100000. On filesystem
access the kernel will now lookup the mapping for 300000 in the fsid
mapping tables of the user namespace. And since such a mapping
exists, the corresponding files will have correct ownership.
So I did compile this up in order to run the shiftfs tests over it to
see how it coped with the various corner cases.  However, what I find
is it simply fails the fsid reverse mapping in the setup.  Trying to
use a simple uid of 0 100000 1000 and a fsid of 100000 0 1000 fails the
entry setuid(0) call because of this code:

long __sys_setuid(uid_t uid)
{
	struct user_namespace *ns =
current_user_ns();
	const struct cred *old;
	struct cred *new;
	int
retval;
	kuid_t kuid;
	kuid_t kfsuid;

	kuid = make_kuid(ns, uid);
	if
(!uid_valid(kuid))
		return -EINVAL;

	kfsuid = make_kfsuid(ns, uid);
	if
(!uid_valid(kfsuid))
		return -EINVAL;

which means you can't have a fsid mapping that doesn't have the same
domain as the uid mapping, meaning a reverse mapping isn't possible
because the range and domain have to be inverse and disjoint.

James
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help