docker: gate --privileged behind DOCKER_PRIVILEGED toggle (default yes)#9733
Conversation
Adds DOCKER_PRIVILEGED env var (default "yes" for backward compatibility). Set DOCKER_PRIVILEGED=no to launch the build container without --privileged, instead complementing the existing --cap-add=SYS_ADMIN/MKNOD/SYS_PTRACE and loop-related --device-cgroup-rule entries with: --device=/dev/loop-control:/dev/loop-control --security-opt=seccomp=unconfined The original justifications for --privileged (USB FEL, raw block-device write via CARD_DEVICE) no longer apply: FEL was removed in ca6bf90, and CARD_DEVICE is now passed via --device=${CARD_DEVICE}. The losetup helper later in the same function still uses --privileged unconditionally; it is gated by /dev/loop0 missing on the host (rare on Linux) and is left out of scope. Tested: full image build with DOCKER_PRIVILEGED=no on edge/noble: - odroidm1 rockchip64 arm64 minimal Linux 7.0.2 49 min - helios4 mvebu armhf server Linux 6.18.25 134 min - helios64 rockchip64 arm64 server Linux 7.0.2 47 min debootstrap, loop, parted, mkfs, chroot, zstd compression all succeeded; no Operation-not-permitted / seccomp / loop_control errors; zero sudo calls on the host across all three runs. Assisted-by: Claude:claude-opus-4-7
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Docker container launch logic in the host functions is modified to conditionally control privileged mode via a Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
I am OK to merge, run tests in unprivileged mode on CI, then proceed with follow up. RKflashing came to my mind, but its not supported under Docker anyway: |
|
@igorpecovnik thanks. Which combinations would you like me to run locally with |
|
yes |
|
As I already wrote in the PR message, I have already put together several images like this. |
Oh, true. Now you can. https://github.com/armbian/os/actions/workflows/complete-artifact-matrix-standard-support.yml When executing, you can choose "Framework build branch" ... when adding new (branch must exists here, not on your fork), you need to run https://github.com/armbian/os/actions/workflows/recreate-matrix.yml so it gets there. |
|
There it is! |
|
Yes, correct and it seems working. Artifacts - when needed - https://fi.mirror.armbian.de/incoming/iav/ |
|
✅ This PR has been reviewed and approved — all set for merge! |
…u-arm Continues #9284 (arm64-compat-vdso extension + custom_kernel_make_params hook). That PR enabled COMPAT_VDSO in arm64 kernels and wired CROSS_COMPILE_COMPAT through the build; this PR uses the resulting 32-bit-capable kernels to skip qemu-arm emulation entirely during the image-build chroot work. Disable qemu-arm in /proc/sys/fs/binfmt_misc for the duration of the image-build so 32-bit ARM ELF falls through to kernel binfmt_elf and runs natively via CONFIG_COMPAT — typically ~12x faster than qemu-arm emulation on common ARM cores (Cortex-A53/A55/A72/A73/A76). A cleanup handler re-enables qemu-arm on build exit (success or failure). Empirical: helios4 BUILD_MINIMAL armhf rootfs cache-miss build on RK3568 (Cortex-A55) drops from 60:35 to 19:27 — 3.12x speedup; same build with rootfs cache-hit drops to 6:38 (~5x). Activation point is delayed to AFTER mmdebstrap (in create_new_rootfs_cache_via_debootstrap, right past the bash-presence check) and also at build_rootfs_and_image entry for the rootfs-cache hit path. Earlier activation breaks mmdebstrap because its cross-arch machinery requires a working qemu-arm in binfmt_misc and the chroot is not yet populated for native exec. Out-of-scope cases (target arch != armhf, host arch != aarch64, not running in container) return silently with no log noise. In-scope cases log the capability-check outcome at info level: native enabled, already-effective no-op, or 32-bit ARM execution unsupported (no COMPAT_VDSO in kernel, Apple Silicon, ARMv9-only cores) — falling back to qemu-arm-static emulation. Killswitch: NATIVE_ARMHF_ON_ARM64=no disables this path entirely, before any detection runs — useful on shared build farms or whenever opting out is desired (synonyms 'never' and 'disabled' are accepted by the parser). Sets ARMBIAN_NATIVE_ARMHF_VIA_BINFMT_ELF=yes when active so that deploy_qemu_binary_to_chroot / undeploy_qemu_binary_from_chroot skip copying qemu-arm-static into the chroot during image-stage (the kernel handles the ELF directly). Behaviour depends on DOCKER_PRIVILEGED (#9733). With the default DOCKER_PRIVILEGED=yes, /proc/sys/fs/binfmt_misc is shared with the host's init user-ns; disabling qemu-arm affects the host's other concurrent processes for the duration of the build (acceptable for single-user builders, problematic for shared build farms — opt out with NATIVE_ARMHF_ON_ARM64=no). With DOCKER_PRIVILEGED=no, sysfs is read-only inside the container; the disable write fails, the function logs a warning, and the build continues via qemu-arm-static — no regression. Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Igor Velkov <325961+iav@users.noreply.github.com>
Summary
Introduces a
DOCKER_PRIVILEGEDenv var (defaultyes) gating thehardcoded
--privilegedflag on the build container. When set tono,the container launches with a narrow capability set instead.
This is intentionally a conservative first step: default behaviour
is unchanged. A follow-up PR can flip the default to
noafterbroader board coverage is confirmed.
Motivation
--privilegedhas been hardcoded inlib/functions/host/docker.sh:384since 2022 (commit
d24d3327a8). The original comment cited tworeasons:
Both reasons are stale today:
ca6bf9046b(2023-02-09).CARD_DEVICEis passed explicitly viaDOCKER_ARGS+=("--device=${CARD_DEVICE}")atdocker.sh:471.The surrounding code already has a near-complete narrow-capability
setup:
This PR adds the two missing pieces to make a non-privileged container
usable for armbian builds:
--device=/dev/loop-control:/dev/loop-control—losetup -fneeds/dev/loop-control, not exposed without--privileged.--security-opt=seccomp=unconfined— default seccomp profile mayblock
mount,pivot_root,unshareeven withCAP_SYS_ADMIN,which breaks debootstrap and chroot setup.
Tested
Host: aarch64 (Armbian 26.2.1 noble), kernel 7.0.1, Docker 29.4.1.
Builds (all with
ARTIFACT_IGNORE_CACHE=yes DOCKER_PRIVILEGED=no RELEASE=noble, full image build: debootstrap, loop, parted, mkfs,chroot, zstd, rsync):
All three:
🐳 successful, image written, noOperation not permitted/ seccomp / loop_control errors in the log.DOCKER_PRIVILEGED unset (default
yes) verified separately to keepcurrent behaviour.
Out of scope
docker.sh:619(docker run --rm --privileged --cap-add=MKNOD ...) is unchanged. It is gated by/dev/loop0missing on the host, which is rare on Linux. A follow-up could mirror
the toggle there.
@TODO rpardini: maybe it's dead already?on--cap-add=SYS_PTRACEis left as-is — orthogonal to this change.
Follow-up
After this lands and gets exercise on more boards, a one-line PR can
flip the default to
no.Summary by CodeRabbit