Container fails to restart after setting raw.idmap

I have a host user craig with a uid/gid of 1001.

I have container stretch-cc with a user cc having uid/gid of 1000.

I try setting the raw.idmap using either of these methods:

old method:

printf "uid $(id -u) 1000\ngid $(id -g) 1000" | lxc config set test raw.idmap -

new method:

echo "both 1001 1000" | lxc config set stretch-cc raw.idmap -

In both cases the container error on restart:

conf - conf.c:lxc_map_ids:2999 - newuidmap failed to write mapping "newuidmap: uid range [1000-1001) -> [1001-1002) not allowed": newuidmap 13712 0 231072 1000 1000 1001 1 1001 232073 64535

Configuration is:

$ lxc config show stretch-cc
architecture: x86_64
config:
  image.architecture: amd64
  image.description: Debian stretch amd64 (20190317_05:24)
  image.os: Debian
  image.release: stretch
  image.serial: "20190317_05:24"
  raw.idmap: |
    both 1001 1000
  volatile.base_image: 137c391ed7e0d39a3912a6ae45d545f60d8156dcf601a427030f40421cc81129
  volatile.eth0.hwaddr: 00:16:3e:9b:d5:68
  volatile.idmap.base: "0"
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":231072,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1001,"Nsid":1000,"Maprange":1},{"Isuid":true,"Isgid":false,"Hostid":232073,"Nsid":1001,"Maprange":64535},{"Isuid":false,"Isgid":true,"Hostid":231072,"Nsid":0,"Maprange":1000},{"Isuid":true,"Isgid":true,"Hostid":1001,"Nsid":1000,"Maprange":1},{"Isuid":false,"Isgid":true,"Hostid":232073,"Nsid":1001,"Maprange":64535}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":231072,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":231072,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.power: RUNNING
devices: {}
ephemeral: false
profiles:
- default
- stretch-cc-profile
stateful: false
description: ""
$ lxc profile show stretch-cc-profile 
config: {}
description: map user cc home dir to host /home/craig/lxc-dirs/stretch-cc
devices:
  home:
    path: /home/cc
    source: /home/craig/lxc-dirs/stretch-cc
    type: disk
name: stretch-cc-profile
used_by:
- /1.0/containers/stretch-cc

on host:

$ grep 1001 /etc/passwd
craig:x:1001:1001:Craig,0,1,2,3:/home/craig:/bin/bash
$ cat /etc/subuid
crub18:100000:65536
craig:165536:65536
lxd:231072:65536
root:231072:65536

subguid same

on container:

$ lxc exec stretch-cc -- grep 1000 /etc/passwd
cc:x:1000:1000::/home/cc:/bin/bash
$ lxc exec stretch-cc -- cat /etc/subuid
cc:100000:65536

subgid same

The LXD documentation says:

The raw keys allow direct interaction with the backend features that LXD itself uses, setting those may very well break LXD in non-obvious ways and should whenever possible be avoided.

This seems to be an instruction that raw.idmap should NOT be used.
But it contradicts the LXD documentation
on id mapping.

You’re on a system which uses /etc/subuid and /etc/subgid.

The root user under which LXD is running must be allowed access to any uid/gid that you intend to use.
In this case, root doesn’t have access to your user’s uid and gid, causing that error.

Thank you very much for your assistance.
However I don’t have enough a priori knowledge context to transform your explanation into a working solution. I can’t see anything obvious I missed in the manual.

From the manual:

If some but not all of `/etc/subuid` , `/etc/subgid` , `newuidmap` (path lookup) and `newgidmap` (path lookup) can be found on the system, LXD will fail the startup of any container until this is corrected as this shows a broken shadow setup.

All those 4 files exist and I believe they were installed or modified by lxd init - so I’m guessing their content is not a problem.

Do I need to additionally add lines like these?

uid 50-60 500-510
gid 100000-110000 10000-20000

I am really at a loss.


Edit: I tried giving the container user and host user the same name and uid/gid

craig:x:1001:1001::/home/craig:/bin/bash

is the same in both systems /etc/passwd

The other two obvious things I can think of is

  • the container users home directory is NOT a map of the host users home directory, it is a map of a host users subdirectory under its home directory (as visible in the profile listed above)
  • the container is unpriviliged

However nothing in the manual (that has stuck in my mind) indicates either of those factors would be a problem.

Hello
from the fine manual:

SUBUID(5)                                                                   File Formats and Conversions                                                                   SUBUID(5)

NAME
       subuid - the subordinate uid file

DESCRIPTION
       Each line in /etc/subuid contains a user name and a range of subordinate user ids that user is allowed to use.

So, on the host (you quoted a subuid file in the container - you have to remember that a container is a jail on steroids, if you could in a container map users to the host, it would be a slight security issue - so don’t bother setting uid mappings in a container), add a line such as
root:1001:1
in /etc/subuid and /etc/subgid
The mapping you have in your /etc/ give access to root on the automatic id range(generated by lxd) beginning at 231072, if you use custom mappings you have to add them yourself.

@gpatel-fr - Hi and thanks for your reply. It has kicked me down the road a bit more, and I am grateful for that.

My understanding - which may partially or completely incorrect - is as follows:

  1. The uids in /etc/subuid are supposed to be all interpreted as being in the host-namespace. There is also an unwritten default state in /etc/subuid (and -gid) of root:0:65536. Therefore adding root:100x:1 to /etc/subuid shouldn’t change the semantics of program behavior.
  2. From the subuid manpage: "This file specifies the user IDs that ordinary users can use, with the newuidmap command, to configure uid mapping in a user namespace. " The user in question here is lxd. It means when lxd talks to the host in host-namespace, it uses the block specified in /etc/subuid - that is lxd:231072:65536 in the above example case. lxd if free to use any translation of that block it pleases inside its own namespace (e.g. in the container). /etc/subuid, however, is strictly in host-namespace.
  3. Considering the above 1 and 2, the principle behind the specs of writing root:100x:1 isn’t at all clear. If lxd is using lxd-namespace inside /etc/subuid, then what happens when another application decides it also wants to use it’s own local namespace in /etc/subuid? It could collide with lxd. I’m sure it’s not the case that root:100x:1 is a euphemism for lxc:100x:1.

Giving @stgraber 's 2017 blog a closer look, I realize I missed that his host user was not a typical uid=100x user, but rather had a uid in the lxc subuid range, to quote:

lxd:201105:1
root:201105:1

So it could be a special purpose user created with something like:

GID=200512
UID=201105
##sudo groupadd -g ${GID} cc || exit 155                                                      
sudo useradd -u ${UID} -g ${GID} -s /bin/bash cc || exit 160  

in a setup with one such host-user per container, and all such host-user sharing a single host-group login. It would have been interesting and possibly useful for @stgraber to have explained about that setup and it’s pros and cons.

Now I think I will retreat from this path of having the container mount a host-user dir (except for read only), and go back to a more birds eye view of optimizing ergonomics while preserving security.