public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
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.

  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