From: "'Felix Moessbauer' via isar-users" <isar-users@googlegroups.com>
To: isar-users@googlegroups.com
Cc: quirin.gylstorff@siemens.com,
Felix Moessbauer <felix.moessbauer@siemens.com>
Subject: [RFC 08/12] wic: rework image deploy logic to deploy under correct user
Date: Wed, 18 Feb 2026 12:58:23 +0100 [thread overview]
Message-ID: <20260218115827.3947145-9-felix.moessbauer@siemens.com> (raw)
In-Reply-To: <20260218115827.3947145-1-felix.moessbauer@siemens.com>
We previously deployed the image file as root and then chowned the
deployed files to the calling user. Hereby the chown command itself
requires to be run under root, which is not possible on rootless.
As a preparation for rootless, we rework the deploy logic to deploy the
files under the calling user. For that, we deploy to a temporary
directory within workdir that is writeable from inside the chroot and
then copy out under the calling user.
Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
---
RECIPE-API-CHANGELOG.md | 12 +++++
.../image-tools-extension.bbclass | 11 +++++
meta/classes-recipe/image.bbclass | 10 +++-
meta/classes-recipe/imagetypes.bbclass | 47 +++++++++++--------
meta/classes-recipe/imagetypes_wic.bbclass | 10 ++--
meta/classes-recipe/squashfs.bbclass | 2 +-
6 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/RECIPE-API-CHANGELOG.md b/RECIPE-API-CHANGELOG.md
index bc40a403..f80630a0 100644
--- a/RECIPE-API-CHANGELOG.md
+++ b/RECIPE-API-CHANGELOG.md
@@ -978,3 +978,15 @@ specifies the rootfs path.
Using these helpers instead of direct `sudo` invocations centralizes platform-specific
privileged execution logic in `base.bbclass`. Direct use of `sudo` is discouraged
in downstream layers.
+
+### Changes to image types
+
+The way different image types are handled has changed to be be compatible with
+rootless builds. For that, the deployment of images happens in two steps:
+
+1. generate the image in the `${IMAGE_STAGE_CHROOT}`
+2. the `imager_run` or `${SUDO_CHROOT}` command takes care of deploying the image
+ into the `${DEPLOY_DIR_IMAGE}`
+
+Conversion commands need to follow this strategy as well, but can read the image
+(prior to conversion) from `${IMAGE_FILE_CHROOT}`.
diff --git a/meta/classes-recipe/image-tools-extension.bbclass b/meta/classes-recipe/image-tools-extension.bbclass
index e88557f6..2eac3619 100644
--- a/meta/classes-recipe/image-tools-extension.bbclass
+++ b/meta/classes-recipe/image-tools-extension.bbclass
@@ -17,6 +17,17 @@ SCHROOT_MOUNTS = "${WORKDIR}:${PP_WORK} ${IMAGE_ROOTFS}:${PP_ROOTFS} ${DEPLOY_DI
SCHROOT_MOUNTS += "${REPO_ISAR_DIR}/${DISTRO}:/isar-apt"
imager_run() {
+ IMAGE_STAGE_DIR=$(dirname $IMAGE_STAGE_HOST)
+ create_chroot_parent_dir $IMAGE_STAGE_DIR
+ imager_run_${ISAR_CHROOT_MODE} "$@"
+
+ # copy locally deployed files with correct permissions to deploy dir
+ find $IMAGE_STAGE_DIR -type f -exec cp {} ${DEPLOY_DIR_IMAGE} \;
+ # on error keep the files for investigation
+ run_privileged rm -rf $IMAGE_STAGE_DIR
+}
+
+imager_run_schroot() {
local_install="${@(d.getVar("INSTALL_%s" % d.getVar("BB_CURRENTTASK")) or '').strip()}"
local_bom="${@(d.getVar("BOM_%s" % d.getVar("BB_CURRENTTASK")) or '').strip()}"
diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass
index ca449ec5..e0e19adf 100644
--- a/meta/classes-recipe/image.bbclass
+++ b/meta/classes-recipe/image.bbclass
@@ -180,8 +180,14 @@ IMGCLASSES += "${IMAGE_CLASSES}"
inherit ${IMGCLASSES}
# convenience variables to be used by CMDs
+# Note, that the variables are only valid within the type specific task itself
+# but not in transitively called shell functions
IMAGE_FILE_HOST = "${DEPLOY_DIR_IMAGE}/${IMAGE_FULLNAME}.${type}"
+# view (only for reading) the image in the deploy dir (useful for conversion commands)
IMAGE_FILE_CHROOT = "${PP_DEPLOY}/${IMAGE_FULLNAME}.${type}"
+# staging location for copy-out (should only be written to from chroot)
+IMAGE_STAGE_HOST = "${WORKDIR}/deploy-image-${type}/${IMAGE_FULLNAME}.${type}"
+IMAGE_STAGE_CHROOT = "${PP_WORK}/deploy-image-${type}/${IMAGE_FULLNAME}.${type}"
SUDO_CHROOT = "imager_run -d ${PP_ROOTFS} -u root --"
# hook up IMAGE_CMD_*
@@ -262,8 +268,8 @@ python() {
image_cmd = localdata.getVar('IMAGE_CMD:' + bt_clean)
if image_cmd:
localdata.setVar('type', bt)
+ cmds.append(localdata.expand('\tIMAGE_STAGE_HOST="${IMAGE_STAGE_HOST}"'))
cmds.append(localdata.expand(image_cmd))
- cmds.append(localdata.expand('\tsudo chown $(id -u):$(id -g) ${IMAGE_FILE_HOST}'))
else:
bb.fatal("No IMAGE_CMD for %s" % bt)
vardeps.add('IMAGE_CMD:' + bt_clean)
@@ -292,8 +298,8 @@ python() {
localdata.setVar('type', t)
cmd = '\t' + localdata.getVar('CONVERSION_CMD:' + c)
if cmd not in cmds:
+ cmds.append(localdata.expand('\tIMAGE_STAGE_HOST="${IMAGE_STAGE_HOST}"'))
cmds.append(cmd)
- cmds.append(localdata.expand('\tsudo chown $(id -u):$(id -g) ${IMAGE_FILE_HOST}.%s' % c))
vardeps.add('CONVERSION_CMD:' + c)
for dep in (localdata.getVar('CONVERSION_DEPS:' + c) or '').split():
conversion_install.add(dep)
diff --git a/meta/classes-recipe/imagetypes.bbclass b/meta/classes-recipe/imagetypes.bbclass
index f802c11c..78b89393 100644
--- a/meta/classes-recipe/imagetypes.bbclass
+++ b/meta/classes-recipe/imagetypes.bbclass
@@ -9,7 +9,7 @@ TAR_TRANSFORM = "--transform='s|rootfs|.|'"
TAR_OPTIONS:append = " ${TAR_TRANSFORM}"
IMAGE_CMD:tar() {
${SUDO_CHROOT} tar ${TAR_OPTIONS} -cvSf \
- ${IMAGE_FILE_CHROOT} --one-file-system -C ${PP} rootfs
+ ${IMAGE_STAGE_CHROOT} --one-file-system -C ${PP} rootfs
}
# image type: ext4
@@ -38,10 +38,11 @@ do_image_ext4[prefuncs] = "set_mke2fs_args"
IMAGE_CMD:ext4() {
export E2FSPROGS_FAKE_TIME="${SOURCE_DATE_EPOCH}"
- truncate -s ${ROOTFS_SIZE}K '${IMAGE_FILE_HOST}'
-
- ${SUDO_CHROOT} /sbin/mke2fs ${MKE2FS_ARGS} \
- -F -d '${PP_ROOTFS}' '${IMAGE_FILE_CHROOT}'
+ ${SUDO_CHROOT} /bin/bash -s <<'EOF'
+ set -e
+ truncate -s ${ROOTFS_SIZE}K '${IMAGE_STAGE_CHROOT}'
+ /sbin/mke2fs ${MKE2FS_ARGS} -F -d '${PP_ROOTFS}' '${IMAGE_STAGE_CHROOT}'
+EOF
}
# image type: cpio
@@ -49,10 +50,12 @@ IMAGER_INSTALL:cpio += "cpio"
CPIO_IMAGE_FORMAT ?= "newc"
IMAGE_CMD:cpio() {
- ${SUDO_CHROOT} \
- sh -c "cd ${PP_ROOTFS}; /usr/bin/find . | \
- /usr/bin/cpio -H ${CPIO_IMAGE_FORMAT} -o > \
- ${IMAGE_FILE_CHROOT}"
+ imager_run -p -d ${PP_WORK} -u root <<'EOIMAGER'
+ set -e
+ cd '${PP_ROOTFS}'; /usr/bin/find . | \
+ /usr/bin/cpio -H ${CPIO_IMAGE_FORMAT} -o > \
+ '${IMAGE_STAGE_CHROOT}'
+EOIMAGER
}
# image type: fit
@@ -72,8 +75,9 @@ IMAGE_CMD:fit() {
die "FIT_IMAGE_SOURCE does not contain fitimage source file"
fi
- ${SUDO_CHROOT} /usr/bin/mkimage ${MKIMAGE_ARGS} \
- -f '${PP_WORK}/${FIT_IMAGE_SOURCE}' '${IMAGE_FILE_CHROOT}'
+ ${SUDO_CHROOT} /usr/bin/mkimage \
+ ${MKIMAGE_ARGS} -f '${PP_WORK}/${FIT_IMAGE_SOURCE}' \
+ '${IMAGE_STAGE_CHROOT}'
}
IMAGE_CMD:fit[depends] = "${PN}:do_transform_template"
@@ -90,8 +94,9 @@ THIS_ISAR_CROSS_COMPILE := "${ISAR_CROSS_COMPILE}"
ISAR_CROSS_COMPILE:armhf = "${@bb.utils.contains('IMAGE_BASETYPES', 'ubifs', '1', '${THIS_ISAR_CROSS_COMPILE}', d)}"
IMAGE_CMD:ubifs() {
- ${SUDO_CHROOT} /usr/sbin/mkfs.ubifs ${MKUBIFS_ARGS} \
- -r '${PP_ROOTFS}' '${IMAGE_FILE_CHROOT}'
+ ${SUDO_CHROOT} /usr/sbin/mkfs.ubifs \
+ ${MKUBIFS_ARGS} -r '${PP_ROOTFS}' \
+ '${IMAGE_FILE_CHROOT}'
}
# image type: ubi
@@ -108,22 +113,26 @@ IMAGE_CMD:ubi() {
die "UBINIZE_CFG does not contain ubinize config file."
fi
- ${SUDO_CHROOT} /usr/sbin/ubinize ${UBINIZE_ARGS} \
- -o '${IMAGE_FILE_CHROOT}' '${PP_WORK}/${UBINIZE_CFG}'
+ ${SUDO_CHROOT} /usr/sbin/ubinize \
+ ${UBINIZE_ARGS} -o '${IMAGE_STAGE_CHROOT}' \
+ '${PP_WORK}/${UBINIZE_CFG}'
}
IMAGE_CMD:ubi[depends] = "${PN}:do_transform_template"
# image conversions
IMAGE_CONVERSIONS = "gz xz zst zck"
-CONVERSION_CMD:gz = "${SUDO_CHROOT} sh -c 'gzip -f -9 -n -c --rsyncable ${IMAGE_FILE_CHROOT} > ${IMAGE_FILE_CHROOT}.gz'"
+# image conversions
+IMAGE_CONVERSIONS = "gz xz zst zck"
+
+CONVERSION_CMD:gz = "${SUDO_CHROOT} sh -c 'gzip -f -9 -n -c --rsyncable ${IMAGE_FILE_CHROOT} > ${IMAGE_STAGE_CHROOT}.gz'"
CONVERSION_DEPS:gz = "gzip"
-CONVERSION_CMD:xz = "${SUDO_CHROOT} sh -c 'xz -c ${XZ_DEFAULTS} ${IMAGE_FILE_CHROOT} > ${IMAGE_FILE_CHROOT}.xz'"
+CONVERSION_CMD:xz = "${SUDO_CHROOT} sh -c 'xz -c ${XZ_DEFAULTS} ${IMAGE_FILE_CHROOT} > ${IMAGE_STAGE_CHROOT}.xz'"
CONVERSION_DEPS:xz = "xz-utils"
-CONVERSION_CMD:zst = "${SUDO_CHROOT} sh -c 'zstd -c --sparse ${ZSTD_DEFAULTS} ${IMAGE_FILE_CHROOT} > ${IMAGE_FILE_CHROOT}.zst'"
+CONVERSION_CMD:zst = "${SUDO_CHROOT} sh -c 'zstd -c --sparse ${ZSTD_DEFAULTS} ${IMAGE_FILE_CHROOT} > ${IMAGE_STAGE_CHROOT}.zst'"
CONVERSION_DEPS:zst = "zstd"
-CONVERSION_CMD:zck = "${SUDO_CHROOT} sh -c 'cd $(dirname ${IMAGE_FILE_CHROOT}); zck ${ZCK_DEFAULTS} ${IMAGE_FILE_CHROOT}'"
+CONVERSION_CMD:zck = "${SUDO_CHROOT} sh -c 'cd $(dirname ${IMAGE_FILE_CHROOT}); zck ${ZCK_DEFAULTS} ${IMAGE_STAGE_CHROOT}'"
CONVERSION_DEPS:zck = "zchunk"
diff --git a/meta/classes-recipe/imagetypes_wic.bbclass b/meta/classes-recipe/imagetypes_wic.bbclass
index 63974a3e..ebf3ce8e 100644
--- a/meta/classes-recipe/imagetypes_wic.bbclass
+++ b/meta/classes-recipe/imagetypes_wic.bbclass
@@ -145,6 +145,9 @@ check_for_wic_warnings() {
do_image_wic[file-checksums] += "${WKS_FILE_CHECKSUM}"
IMAGE_CMD:wic() {
+ # variable is type specific, hence capture here and
+ # forward to functions via export
+ export IMAGE_STAGE_CHROOT="${IMAGE_STAGE_CHROOT}"
generate_wic_image
check_for_wic_warnings
}
@@ -181,20 +184,19 @@ generate_wic_image() {
-e "${IMAGE_BASENAME}" ${WIC_CREATE_EXTRA_ARGS}
WIC_DIRECT=$(ls -t -1 /tmp/${IMAGE_FULLNAME}.wic/*.direct | head -1)
- mv -f ${WIC_DIRECT} ${PP_DEPLOY}/${IMAGE_FULLNAME}.wic
- mv -f ${WIC_DIRECT}.bmap ${PP_DEPLOY}/${IMAGE_FULLNAME}.wic.bmap
+ mv -f ${WIC_DIRECT} $IMAGE_STAGE_CHROOT
+ mv -f ${WIC_DIRECT}.bmap $IMAGE_STAGE_CHROOT.bmap
# deploy partition files if requested (ending with .p<x>)
if [ "${WIC_DEPLOY_PARTITIONS}" -eq "1" ]; then
# locate *.direct.p<x> partition files
find "/tmp/${IMAGE_FULLNAME}.wic/" -type f -regextype sed -regex ".*\.direct.*\.p[0-9]\{1,\}" | while read f; do
suffix=$(basename $f | sed 's/.*\.direct\(.*\)/\1/')
- mv -f ${f} ${PP_DEPLOY}/${IMAGE_FULLNAME}.wic${suffix}
+ mv -f ${f} $IMAGE_STAGE_CHROOT${suffix}
done
fi
EOIMAGER
run_privileged chown -R $(stat -c "%U" ${LAYERDIR_core}) ${LAYERDIR_core} ${LAYERDIR_isar} ${SCRIPTSDIR} || true
- run_privileged chown -R $(id -u):$(id -g) "${DEPLOY_DIR_IMAGE}/${IMAGE_FULLNAME}.wic"*
rm -rf ${IMAGE_ROOTFS}/../pseudo
cat ${DEPLOY_DIR_IMAGE}/${IMAGE_FULLNAME}.manifest \
diff --git a/meta/classes-recipe/squashfs.bbclass b/meta/classes-recipe/squashfs.bbclass
index 9cd7ed3d..8330ffb5 100644
--- a/meta/classes-recipe/squashfs.bbclass
+++ b/meta/classes-recipe/squashfs.bbclass
@@ -42,6 +42,6 @@ IMAGE_CMD:squashfs[depends] = "${PN}:do_transform_template"
IMAGE_CMD:squashfs[vardepsexclude] += "SQUASHFS_CREATION_LIMITS"
IMAGE_CMD:squashfs() {
${SUDO_CHROOT} /bin/mksquashfs \
- '${SQUASHFS_CONTENT}' '${IMAGE_FILE_CHROOT}' \
+ '${SQUASHFS_CONTENT}' '${IMAGE_STAGE_CHROOT}' \
-noappend ${SQUASHFS_CREATION_LIMITS} ${SQUASHFS_CREATION_ARGS}
}
--
2.51.0
--
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/20260218115827.3947145-9-felix.moessbauer%40siemens.com.
next prev parent reply other threads:[~2026-02-18 11:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-18 11:58 [RFC 00/12] add support to build isar unprivileged 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 01/12] refactor bootstrap: store rootfs tar with user permissions 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 02/12] deb-dl-dir: export without root privileges 'Felix Moessbauer' via isar-users
2026-02-18 14:01 ` 'Jan Kiszka' via isar-users
2026-02-18 11:58 ` [RFC 03/12] download debs without locking 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 04/12] introduce wrappers for privileged execution 'Felix Moessbauer' via isar-users
2026-02-18 14:11 ` 'Jan Kiszka' via isar-users
2026-02-18 11:58 ` [RFC 05/12] bootstrap: move cleanup trap to function 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 06/12] rootfs: rework sstate caching of rootfs artifact 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 07/12] rootfs_generate_initramfs: rework deployment to avoid chowning 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` 'Felix Moessbauer' via isar-users [this message]
2026-02-18 11:58 ` [RFC 09/12] use bitbake function to generate mounting scripts 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 10/12] apt-fetcher: prepare for chroot specific fetching 'Felix Moessbauer' via isar-users
2026-02-18 11:58 ` [RFC 11/12] add support for fully rootless builds 'Felix Moessbauer' via isar-users
2026-02-18 16:09 ` 'Jan Kiszka' via isar-users
2026-02-18 16:50 ` 'Jan Kiszka' via isar-users
2026-02-18 11:58 ` [RFC 12/12] apt-fetcher: implement support for unshare backend 'Felix Moessbauer' via isar-users
2026-02-18 18:20 ` [RFC 00/12] add support to build isar unprivileged 'Jan Kiszka' via isar-users
2026-02-18 18:31 ` 'Jan Kiszka' via isar-users
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260218115827.3947145-9-felix.moessbauer@siemens.com \
--to=isar-users@googlegroups.com \
--cc=felix.moessbauer@siemens.com \
--cc=quirin.gylstorff@siemens.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox