[Pkg-shadow-devel] [test] newuidmap/newgidmap

Philippe Grégoire gregoirep at hotmail.com
Tue Jun 3 18:40:41 UTC 2014


TLDR; no easy solution. Either the /etc/subuid is in the kernel and we remove
the file. Or newuidmap reflects the kernel, and they must be kept in sync.

On 2014-06-03 16:58:18 (+0000), Serge Hallyn wrote:
> Quoting Philippe Grégoire (gregoirep at hotmail.com):
> > On 2014-06-03 15:38:05 (+0000), Serge Hallyn wrote:
> > > Quoting Philippe Grégoire (gregoirep at hotmail.com):
> > > 
> > > I personally still feel as you do, that root should be a special case who can
> > > do as he likes;  OTOH it's not an unreasonable argument that (a) root can do
> > > as he likes manually anyway, and (b) requiring this gives some default
> > > protective isolation of subuids for root.
> > 
> > Actually, I believe that, because root can do arbitrary mappings using /proc,
> > there is no _need_ for an exception.
> 
> So you're happy with the status quo?  (There is currently no exception, only
> ranges authorized by /etc/subuid are allowed)
> 
I think the behavior of newuidmap is appropriate... I see it as awkward, though.
As a side note, the kernel already allows "$d $userid 1" -- but it is probably
there to be consistent with what regular users would expect.

> > The main goal here is to prevent collisions and privilege escalations if users
> > were allowed to do arbitrary mappings. /etc/subuid allows just that by enabling
> > users to do mappings (with the help of a SETUID program) to ranges specified by
> > the administrator (or programmatically, in the case of adduser). While it is
> > true that root can have subids, it cannot be enforced, utltimately, by
> > newuidmap.
> 
> It can't be enforced.  However, noone except while playing around with it is
> going to manually set up uid mappings.  They'll use a toolset, let's, oh, say,
> lxc-usernsexec.  Not having this exception for root means that all such
> toolsets will need to have a separate code path for the root user writing
> to /proc/$$/uid_map, while the main code path uses newuidmap.  That's a
> recipe for untested paths and errors.
> 
I had to play with it because lxc is broken on Debian, and Ubuntu. Quickly, I
can create a container as a unprivileged user but running it produces:

  'Error creating container whatever'

which is, quite frankly, purely unsatisfying. What am I expected to do with that
error message? What am I suppose to investigate? Also, why would cgroups be
mandatory? etc. But that is another topic; and I am no longer interested in lxc
(version 1.x? -- please...).

-- BEGIN TOUGHT PROCESS --

Forget about lxc and newuidmap for a moment and follow me.

The kernel is the ultimate id mapper. Unprivileged users cannot run full
containers because it requires CAP_SETUID to map to ranges greater than 1 (if
the base is the user's id). Thus one needs a tool to allow unprivileged users
to define arbitrary mappings.

Comes newuidmap which has the set-uid-bit set. Now we must consider the issue
of privilege escalations (malicious) and id collisions -- where one container
creates a sensitive file with external id 100000 in a directory accessible by
others (off the top of my head, but _there is_ more dangerous).

Comes /etc/subuid, whose sole purpose is to complement newuidmap by allocating
unused ids to users. Now the administrator (or adduser) can allocate id ranges as
needed.

Together, there is now a way for unprivileged users to run full containers.


Now the problem comes when root (or a privileged user) uses newuidmap. We know
it, we hate it, it fails. The reason is that newuidmap does not check whether
the caller has the required (by the kernel) to map to arbitrary ids. On the
first look, it is problematic and one is tempted to make newuidmap make the
same check than the kernel. But why does Eric did not go that way? I presume:

  1) newuidmap was meant for unprivileged users.
  2) if one modifies the kernel, one must modify newuidmap accordingly.

The second reason is the main point, in my opinion, for not needing to modify
it. In fact, it would be simpler if everyone simply used the kernel.

I proposed an equivalent to /etc/subuid in /proc/sys/kernel/subuid and make the
kernel check that file (which has other consequences, anyways). Mappings could
be stored in /etc/sysctl.d and loaded into the kernel during boot.

-- END LONG TOUGHT PROCESS --

You are arguing about making the newuidmap the only tool needed for mapping
ids for the sake of toolsets, while newuidmap could also be avoided.

Complaining about a change of this kind:

  if (0 != newuidmap(...)) {
	write_to_uid_map(...);
  }

does not have much weight. I yet have to find/hear a solid argument against...

> > If one would want to enforce subids for root, one may want to investigate a
> > /proc/.../subuid interface. That could probably leave the whole restriction
> 
> I'm not sure what you mean here.

Disgression, but, refering to Eric's answers in the thread you linked to. If
newuidmap is considered the "be all and end all", it should enforce subids for
root. However, because setuid programs can define arbitrary mappings using the
/proc interface, it cannot be. If one _really_ wanted to enforce subids for root
containers, they would have to be enforced by the kernel, not a user-land tool.
I refer you to the brief explanation above, and invite you to think about it.

> > process in the kernel, remove the need for newuidmap and have the administrator
> > allocate subuids for himself before using them.
> > 
> > In any case, the thing here is about assumptions. newuidmap is not a front-end
> > but a dedicated tool.
> 
> A dedicated privileged tool for use by other tools, to localize the very careful
> handling needed to delegate this stuff safely.
> 
Delegation of CAP_SETUID, yes. Do you want to be /etc/subuid and newuidmap to be
the ultimate enforcer, instead of the kernel? If whatever toolset is running
with the appropriate privileges, there is no need for newuidmap; one is always
able to talk with the kernel.

> > To avoid confusion, the manual should be more factual and
> > recommend checking the mapping with the kernel for a definitive answer.
> 
> I think you're saying you want an update to newuidmap(1), but I don't understand
> what.  Can you give some proposed text?
> 

--- BEGIN MANUAL DRAFT --
NOTES

  newuidmap was designed for unprivileged users to run containers with a ids
  different than their own. Users should first try communicate directly with
  the kernel to check whether they have the appropriate privileges. If not,
  they shoud use newuidmap to determine whether the administrator has defined
  an exception for their request.
--- END MANUAL DRAFT --

The order (kernel then newuidmap, or vice-versa) has to be checked, and I assume
they are consistent.

Also, I yet have to see an official user_namespaces(7) (which newuidmap(1)
refers to) which would probably instruct how to use uid_map.

> > P. Grégoire
> 
> -serge



More information about the Pkg-shadow-devel mailing list