[OE-core] [PATCH] sanity: allow to compile from root in user namespaces

Nikolai Merinov n.merinov at inango-systems.com
Tue Dec 31 08:33:15 UTC 2019


New rootless container subsystems rely on the "user namespaces"
Linux feature. In order to create a container from a regular user the
user uid and subuids mapped to the uid space inside of container.

There are different default configurations used for different
container subsystems:

 1. Rootless Docker[1] maps the user ID to 0, the subuids to range
    starting from 1.
 2. Rootless RunC[2] from OCI by default maps the user ID to 0 and
    ignores the subuids.
 3. LXC[3] maps the subuids to range from 0. UID not participates
    in the mapping.

The LXC variant does not allow to work on same files simultaneusly
inside and outside of a container. Variant suggested by other
container susbsystems assumes that files owned by user should be
owned by root in a container environment.

In order to simplify Yocto compilation in such rootless containers I
want to allow to start the bitbake from root user in user namespace
and allow software compilation from root user in the described
configuration. Additionally I want to provide minimal dockerfile
suitable for the core-image-sato image compilation.

--
[1] https://docs.docker.com/engine/security/rootless/
[2] https://github.com/opencontainers/runc#rootless-containers
[3] https://linuxcontainers.org/lxc/getting-started/#creating-unprivileged-containers-as-a-user
---
 meta/classes/insane.bbclass                   |  4 ++--
 meta/classes/sanity.bbclass                   | 10 +++++++-
 meta/recipes-core/coreutils/coreutils_8.31.bb |  1 +
 scripts/docker/Dockerfile                     | 19 +++++++++++++++
 scripts/docker/oe-rootless-docker             | 24 +++++++++++++++++++
 5 files changed, 55 insertions(+), 3 deletions(-)
 create mode 100644 scripts/docker/Dockerfile
 create mode 100755 scripts/docker/oe-rootless-docker

diff --git a/meta/classes/insane.bbclass b/meta/classes/insane.bbclass
index 0564f9c2a4..3599ce3e6a 100644
--- a/meta/classes/insane.bbclass
+++ b/meta/classes/insane.bbclass
@@ -876,12 +876,12 @@ def package_qa_check_host_user(path, name, d, elf, messages):
             raise
     else:
         check_uid = int(d.getVar('HOST_USER_UID'))
-        if stat.st_uid == check_uid:
+        if check_uid != 0 and stat.st_uid == check_uid:
             package_qa_add_message(messages, "host-user-contaminated", "%s: %s is owned by uid %d, which is the same as the user running bitbake. This may be due to host contamination" % (pn, package_qa_clean_path(path, d, name), check_uid))
             return False
 
         check_gid = int(d.getVar('HOST_USER_GID'))
-        if stat.st_gid == check_gid:
+        if check_gid != 0 and stat.st_gid == check_gid:
             package_qa_add_message(messages, "host-user-contaminated", "%s: %s is owned by gid %d, which is the same as the user running bitbake. This may be due to host contamination" % (pn, package_qa_clean_path(path, d, name), check_gid))
             return False
     return True
diff --git a/meta/classes/sanity.bbclass b/meta/classes/sanity.bbclass
index 63ab6cf3df..a1eba62589 100644
--- a/meta/classes/sanity.bbclass
+++ b/meta/classes/sanity.bbclass
@@ -742,7 +742,15 @@ def check_sanity_everybuild(status, d):
     # it makes sense to always run them.
 
     if 0 == os.getuid():
-        raise_sanity_error("Do not use Bitbake as root.", d)
+        userns = False
+        with open("/proc/self/uid_map") as f:
+            for line in f:
+                fields = line.split()
+                if fields[0] == "0" and fields[1] != "0":
+                    userns = True
+                    break
+        if not userns:
+            raise_sanity_error("Do not use Bitbake as root.", d)
 
     # Check the Python version, we now have a minimum of Python 3.4
     import sys
diff --git a/meta/recipes-core/coreutils/coreutils_8.31.bb b/meta/recipes-core/coreutils/coreutils_8.31.bb
index 57b2c1bdba..2f8009331a 100644
--- a/meta/recipes-core/coreutils/coreutils_8.31.bb
+++ b/meta/recipes-core/coreutils/coreutils_8.31.bb
@@ -28,6 +28,7 @@ SRC_URI[sha256sum] = "ff7a9c918edce6b4f4b2725e3f9b37b0c4d193531cac49a48b56c4d0d3
 EXTRA_OECONF_class-native = "--without-gmp"
 EXTRA_OECONF_class-target = "--enable-install-program=arch,hostname --libexecdir=${libdir}"
 EXTRA_OECONF_class-nativesdk = "--enable-install-program=arch,hostname"
+EXTRA_OECONF_append = " FORCE_UNSAFE_CONFIGURE=1"
 
 # acl and xattr are not default features
 #
diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile
new file mode 100644
index 0000000000..4a143d6aa1
--- /dev/null
+++ b/scripts/docker/Dockerfile
@@ -0,0 +1,19 @@
+FROM ubuntu:18.04
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y update --fix-missing
+
+# Configure locale for Python3
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install locales ; \
+    DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales && \
+        locale-gen en_US.UTF-8 && \
+        update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
+
+ENV LANG=en_US.UTF-8
+ENV LC_ALL=en_US.UTF-8
+
+# Install Yocto native dependencies
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
+        wget git-core diffstat unzip texinfo gcc-multilib \
+        build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \
+        xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev \
+        pylint3 xterm gawk
diff --git a/scripts/docker/oe-rootless-docker b/scripts/docker/oe-rootless-docker
new file mode 100755
index 0000000000..1efcc82280
--- /dev/null
+++ b/scripts/docker/oe-rootless-docker
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+usage () {
+CMD=$(basename $0)
+cat <<EOF
+Usage: $CMD [docker-build|docker-run]
+  docker-build  Build Dockerfile locally
+  docker-run    Run rootless docker image suitable for image compilation
+EOF
+}
+
+if ! [ -n "${DOCKER_HOST}" -a "$(stat -c '%U' "${DOCKER_HOST#*://}" 2>/dev/null)" = "$(whoami)" ] ; then
+	echo "Install rootless docker according to the https://docs.docker.com/engine/security/rootless/"
+	exit 1
+fi
+
+if [ "$1" = "docker-build" ]; then
+	docker build -t poky-docker $(dirname $(readlink -f $0))
+elif [ "$1" = "docker-run" ]; then
+	docker run -ti -v ${HOME}:${HOME} -v ${PWD}:${PWD} --workdir ${PWD} -e HOME poky-docker
+else
+	usage
+	exit 0
+fi
-- 
2.17.1



More information about the Openembedded-core mailing list