@@ -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}`.
@@ -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()}"
@@ -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)
@@ -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"
@@ -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 \
@@ -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}
}
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(-)