Rootless builds, again
v3 cover Rootless builds, again
After fixing (hopefully) all remaining issues in Isar, kas, and our gitlab-cloud-ci, we should now be ready to merge this.
Changes to v2:
- update to kas 5.5
- bump Isar once more, plus not-yet-merged patch
- run rootless builds against rootless runner
Jan
Jan Kiszka (2):
Update Isar revision
ci: Select rootless runner
Quirin Gylstorff (3):
update to kas 5.5
switch to isar-rootless
update README.md for rootless build
.gitlab-ci.yml | 10 +- .reproducible-check-ci.yml | 5 +- Kconfig | 2 +- README.md | 7 +- ...map-nobody-nogroup-as-dedicated-bloc.patch | 68 ++++ kas-cip.yml | 8 +- kas-container | 329 ++++++++++-------- 7 files changed, 269 insertions(+), 160 deletions(-) create mode 100644 isar-patches/0001-rootless-always-map-nobody-nogroup-as-dedicated-bloc.patch
Signature · 1 line
2.47.3
PATCH v3 1/5 update to kas 5.5
From: Quirin Gylstorff <[email protected]>
--- .gitlab-ci.yml | 2 +- Kconfig | 2 +- kas-cip.yml | 2 +- kas-container | 329 +++++++++++++++++++++++++++---------------------- 4 files changed, 187 insertions(+), 148 deletions(-)
.gitlab-ci.yml +1 -1
@@ -34,7 +34,7 @@ stages: - cve-check default: - image: ghcr.io/siemens/kas/kas-isar:5.2 + image: ghcr.io/siemens/kas/kas-isar:5.5 before_script: - export http_proxy=$HTTP_PROXY - export https_proxy=$HTTPS_PROXY
Kconfig +1 -1
@@ -17,7 +17,7 @@ config KAS_INCLUDE_MAIN config KAS_BUILD_SYSTEM string - default "isar" + default "isar-privileged" config ARCH_AMD64 bool
kas-cip.yml +1 -1
@@ -15,7 +15,7 @@ header: distro: cip-core-trixie target: cip-core-image -build_system: isar +build_system: isar-privileged repos: cip-core:
kas-container +184 -145
543 lines not on this page · raw message
Signature · 1 line
2.47.3
PATCH v3 2/5 Update Isar revision
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
One not-yet-merged patch is needed to make Isar compatible with gitlab-cloud-ci in rootless mode.
--- ...map-nobody-nogroup-as-dedicated-bloc.patch | 68 +++++++++++++++++++ kas-cip.yml | 6 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 isar-patches/0001-rootless-always-map-nobody-nogroup-as-dedicated-bloc.patch
isar-patches/0001-rootless-always-map-nobody-nogroup-as-dedicated-bloc.patch new file +68 -0
@@ -0,0 +1,68 @@ +From ea8f6d883a494430ff7db4ee95a875edee23c020 Mon Sep 17 00:00:00 2001 +From: Felix Moessbauer <[email protected]> +Date: Thu, 20 Aug 2026 17:10:29 +0200 +Subject: [PATCH] rootless: always map nobody/nogroup as dedicated block + +The nobody/nogroup ids were mapped as part of the linear id range, +with an extra single-id mapping added only if the range was too small +to contain them. The extra mapping was guarded by "uid_cnt < nobody_id", +but the linear range ends at uid_cnt-2, so it covers nobody only for +uid_cnt >= 65536. For a count of 65534 or 65535 neither the linear range +nor the guard mapped nobody. + +Relying on the linear range to cover nobody is unsafe in general. If that +range covers the outer id that --map-root-user maps to, unshare punches a +hole out of the mapping, and per unshare(1) this "may result in the +highest user ID of the mapping not being mapped". That highest id is +exactly nobody. This happens whenever the subid range overlaps the id of +the calling user, e.g. with + + builder:0:65536 + +where the mapped block 1..65534 contains the builder's own uid. The +resulting namespace then silently lacks a nobody mapping, while a range +like 100000:65536 is unaffected and hides the problem. + +Map nobody/nogroup as a separate block at the top of the range and cap +the linear range at nobody_id-1. The separate block does not overlap +--map-root-user, so it survives, and a hole now at most costs id 65533. + +Fixes: 4fedb1ae ("add support for fully rootless builds") +Signed-off-by: Felix Moessbauer <[email protected]> +--- + meta/classes-global/base.bbclass | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/meta/classes-global/base.bbclass b/meta/classes-global/base.bbclass +index d96ebef4..8f81ab70 100644 +--- a/meta/classes-global/base.bbclass ++++ b/meta/classes-global/base.bbclass +@@ -470,15 +470,19 @@ def run_privileged_cmd(d): + nobody_subid = uid_base + uid_cnt - 1 + gid_base, gid_cnt = get_subid_range('/etc/subgid', d) + nogroup_subid = gid_base + gid_cnt - 1 ++ # nobody/nogroup need a dedicated block at the top of the range. As part ++ # of the linear range they are lost whenever that range covers the outer ++ # id of --map-root-user, because unshare then punches out a hole and ++ # drops the highest id of the range. ++ uid_linear_cnt = min(uid_cnt - 2, nobody_id - 1) ++ gid_linear_cnt = min(gid_cnt - 2, nobody_id - 1) + cmd = 'unshare --mount --pid --uts --ipc --user' \ + ' --kill-child' \ + ' --setuid 0 --setgid 0 --fork' \ +- f' --map-users 1:{uid_base+1}:{uid_cnt-2}' \ +- f' --map-groups 1:{gid_base+1}:{gid_cnt-2}' +- if uid_cnt < nobody_id: +- cmd += f' --map-users {nobody_id}:{nobody_subid}:1' +- if gid_cnt < nobody_id: +- cmd += f' --map-groups {nobody_id}:{nogroup_subid}:1' ++ f' --map-users 1:{uid_base+1}:{uid_linear_cnt}' \ ++ f' --map-groups 1:{gid_base+1}:{gid_linear_cnt}' \ ++ f' --map-users {nobody_id}:{nobody_subid}:1' \ ++ f' --map-groups {nobody_id}:{nogroup_subid}:1' + cmd += " --map-root-user" + else: + cmd = 'sudo -E' +-- +2.47.3 +
kas-cip.yml +5 -1
@@ -22,9 +22,13 @@ repos: isar: url: https://github.com/ilbers/isar.git - commit: 481db3b2e8949336576e50a78aaf5d101f52c8d2 + commit: 436bc96f3869b4a139357afbabb039caf4df7c5c layers: meta: + patches: + p1: + path: isar-patches/0001-rootless-always-map-nobody-nogroup-as-dedicated-bloc.patch + repo: cip-core bblayers_conf_header: standard: |
Signature · 1 line
2.47.3
PATCH v3 3/5 switch to isar-rootless
In reply to Jan KiszkaFrom: Quirin Gylstorff <[email protected]>
--- .reproducible-check-ci.yml | 3 +-- Kconfig | 2 +- kas-cip.yml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-)
.reproducible-check-ci.yml +1 -2
@@ -39,8 +39,7 @@ # Deploy .wic, .swu and wic partitions for build1 - deploy_rb_artifacts build1 # clean - - sudo rm -rf build/tmp - - sudo rm -rf build/sstate-cache + - kas purge --isar-rootless ${base_yaml} # Build 2nd time - !reference [.build_base, script] # Deploy .wic, .swu and wic partitions for build2
Kconfig +1 -1
@@ -17,7 +17,7 @@ config KAS_INCLUDE_MAIN config KAS_BUILD_SYSTEM string - default "isar-privileged" + default "isar-rootless" config ARCH_AMD64 bool
kas-cip.yml +1 -1
@@ -15,7 +15,7 @@ header: distro: cip-core-trixie target: cip-core-image -build_system: isar-privileged +build_system: isar-rootless repos: cip-core:
Signature · 1 line
2.47.3
PATCH v3 4/5 update README.md for rootless build
In reply to Jan KiszkaFrom: Quirin Gylstorff <[email protected]>
--- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
README.md +3 -4
@@ -10,10 +10,9 @@ from scratch. ## Building Target Images -Install docker or podman and make sure you have required permissions to start -privileged containers. For docker, you need to be part of respective docker -group (`sudo usermod -aG docker <USER>`). Privileged podman requires sudo -rights for the caller (`<USER> ALL=(root) SETENV: /usr/bin/podman` in sudoers). +Install docker or podman. For true unprivileged builds, podman is recommended. +See [kas documentation](https://kas.readthedocs.io/en/latest/userguide/kas-container.html) +for more details. Open up the image configuration menu and select the desired target and its options:
Signature · 1 line
2.47.3
PATCH v3 5/5 ci: Select rootless runner
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
We need to explicitly select a runner that is launching build containers in unprivileged mode. This is primarily due to the bug in kas 5.4 which breaks the parallel start of multiple kas-isar containers on the same host. At the same time, such tagging allows us to phase out the privileged runner at some point in way that would clearly block legacy jobs.
--- .gitlab-ci.yml | 8 ++++---- .reproducible-check-ci.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-)
.gitlab-ci.yml +4 -4
@@ -1,7 +1,7 @@ # # CIP Core, generic profile # -# Copyright (c) Siemens AG, 2019-2025 +# Copyright (c) Siemens AG, 2019-2026 # Copyright (c) Toshiba Corporation, 2020 # # Authors:
@@ -53,7 +53,7 @@ default: when: never - if: $CI_COMMIT_BRANCH != "master" tags: - - large + - large-rootless variables: base_yaml: "kas-cip.yml:kas/board/${target}.yml" script:
@@ -917,7 +917,7 @@ cve-checks: needs: [] image: registry.gitlab.com/cip-project/cip-core/debian-cve-checker:build-latest tags: - - large + - large-rootless script: - scripts/run-cve-checks.sh rules:
@@ -936,7 +936,7 @@ lavacli-container: stage: build image: quay.io/buildah/stable:v1.41.4 tags: - - large + - large-rootless before_script: - buildah login -u $CI_REGISTRY_USER --password $CI_REGISTRY_PASSWORD $CI_REGISTRY script:
.reproducible-check-ci.yml +1 -1
@@ -21,7 +21,7 @@ extension: security stage: build tags: - - large + - large-rootless rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $REPRODUCIBLE_BUILDS script:
Signature · 1 line
2.47.3