From db0fcd0894caa71207ac0dd5922ee3edfdcdcaac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Thu, 17 Jul 2025 12:33:17 +0200 Subject: [PATCH] Apply proper udev locking Several commands during repart, resize and other actions require a proper lock to be set for udev such that other events knows about the locked state of a device and do not mess with it until the command for which the lock persists has completed. This commit applies proper udev locks to all commands that requires it. In addition incorrect code that was expected to prevent such race conditions got dropped from the implementation. This is related to bsc#1242987 --- .../90kiwi-repart/kiwi-repart-disk.sh | 26 ----------- .../99kiwi-lib/kiwi-filesystem-lib.sh | 14 +++--- dracut/modules.d/99kiwi-lib/kiwi-luks-lib.sh | 4 +- dracut/modules.d/99kiwi-lib/kiwi-lvm-lib.sh | 4 +- .../modules.d/99kiwi-lib/kiwi-mdraid-lib.sh | 6 ++- .../99kiwi-lib/kiwi-partitions-lib.sh | 46 +++++++++++-------- 6 files changed, 45 insertions(+), 55 deletions(-) diff --git a/dracut/modules.d/90kiwi-repart/kiwi-repart-disk.sh b/dracut/modules.d/90kiwi-repart/kiwi-repart-disk.sh index 318842aa..69b14d34 100755 --- a/dracut/modules.d/90kiwi-repart/kiwi-repart-disk.sh +++ b/dracut/modules.d/90kiwi-repart/kiwi-repart-disk.sh @@ -226,16 +226,6 @@ function check_repart_possible { return 0 } -function mask_fsck_root_service { - info "disable systemd-fsck-root.service" - systemctl mask systemd-fsck-root.service -} - -function unmask_fsck_root_service { - info "enabling systemd-fsck-root.service" - systemctl unmask systemd-fsck-root.service -} - #====================================== # Perform repart/resize operations #-------------------------------------- @@ -243,22 +233,6 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin setup_debug -# when repartitioning disks, the used tools can trigger re-reads of -# the partition table, in turn triggering systemd-fsck-root.service -# repeatedly via udev events, which finally can cause booting to fail with -# * start request repeated too quickly for systemd-fsck-root.service -# * Failed to start File System Check on /dev/disk/by-uuid... -# * Dependency failed for /sysroot. -# To avoid this, disable the root fsck (is finished at this point anyway -# *and* the filesystem is brand new ;) by masking it. -# "systemctl disable" does not work here, because it is event driven -# More details: https://github.com/SUSE/kiwi/issues/1034 - -# make sure we unmask the fsck service -trap unmask_fsck_root_service EXIT - -mask_fsck_root_service - # initialize for disk repartition initialize diff --git a/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh b/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh index a0b82f26..0d802010 100644 --- a/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh +++ b/dracut/modules.d/99kiwi-lib/kiwi-filesystem-lib.sh @@ -37,22 +37,23 @@ function resize_filesystem { local mpoint=/fs-resize local fstype fstype=$(probe_filesystem "${device}") + lock="udevadm lock --device ${device}" case ${fstype} in ext2|ext3|ext4) - resize_fs="resize2fs -f -p ${device}" + resize_fs="${lock} resize2fs -f -p ${device}" ;; btrfs) resize_fs="mkdir -p ${mpoint} && mount ${device} ${mpoint} &&" - resize_fs="${resize_fs} btrfs filesystem resize max ${mpoint}" + resize_fs="${resize_fs} ${lock} btrfs filesystem resize max ${mpoint}" resize_fs="${resize_fs};umount ${mpoint} && rmdir ${mpoint}" ;; xfs) resize_fs="mkdir -p ${mpoint} && mount ${device} ${mpoint} &&" - resize_fs="${resize_fs} xfs_growfs ${mpoint}" + resize_fs="${resize_fs} ${lock} xfs_growfs ${mpoint}" resize_fs="${resize_fs};umount ${mpoint} && rmdir ${mpoint}" ;; swap) - resize_fs="mkswap ${device} --label SWAP" + resize_fs="${lock} mkswap ${device} --label SWAP" ;; *) # don't know how to resize this filesystem @@ -76,6 +77,7 @@ function check_filesystem { local check_fs_return_ok local fstype fstype=$(probe_filesystem "${device}") + lock="udevadm lock --device ${device}" case ${fstype} in ext2|ext3|ext4) # The exit code by e2fsck is the sum of the following conditions: @@ -87,13 +89,13 @@ function check_filesystem { # 16 - Usage or syntax error # 32 - E2fsck canceled by user request # 128 - Shared library error - check_fs="e2fsck -p -f ${device}" + check_fs="${lock} e2fsck -p -f ${device}" check_fs_return_ok="test \$? -le 2" ;; btrfs) # btrfs check returns a zero exit status if it succeeds. # Non zero is returned in case of failure. - check_fs="btrfsck ${device}" + check_fs="${lock} btrfsck ${device}" check_fs_return_ok="test \$? -eq 0" ;; xfs) diff --git a/dracut/modules.d/99kiwi-lib/kiwi-luks-lib.sh b/dracut/modules.d/99kiwi-lib/kiwi-luks-lib.sh index 9eb99224..a7a4e0ee 100644 --- a/dracut/modules.d/99kiwi-lib/kiwi-luks-lib.sh +++ b/dracut/modules.d/99kiwi-lib/kiwi-luks-lib.sh @@ -74,7 +74,7 @@ function reencrypt_luks { setup_progress_fifo ${progress} ( # reencrypt, this will overwrite all key slots - cryptsetup reencrypt \ + udevadm lock --device "${device}" cryptsetup reencrypt \ --progress-frequency 1 \ --key-file "${passphrase_file}" \ --key-slot "${keyslot}" \ @@ -102,7 +102,7 @@ function activate_luks { # but this requires to manually call luksOpen since # with systemd-cryptsetup we saw it still asking for # a passphrase - cryptsetup \ + udevadm lock --device "${device}" cryptsetup \ --key-file /dev/zero \ --keyfile-size 32 \ luksOpen "${device}" luks diff --git a/dracut/modules.d/99kiwi-lib/kiwi-lvm-lib.sh b/dracut/modules.d/99kiwi-lib/kiwi-lvm-lib.sh index c20246cc..f4490325 100644 --- a/dracut/modules.d/99kiwi-lib/kiwi-lvm-lib.sh +++ b/dracut/modules.d/99kiwi-lib/kiwi-lvm-lib.sh @@ -61,7 +61,9 @@ function get_volume_path_for_volume { } function resize_pyhiscal_volumes { - pvresize "$(get_root_map)" + local device + device=$(get_root_map) + udevadm lock --device "${device}" pvresize "${device}" } function resize_lvm_volumes_and_filesystems { diff --git a/dracut/modules.d/99kiwi-lib/kiwi-mdraid-lib.sh b/dracut/modules.d/99kiwi-lib/kiwi-mdraid-lib.sh index 3ed2d315..bfdcf225 100644 --- a/dracut/modules.d/99kiwi-lib/kiwi-mdraid-lib.sh +++ b/dracut/modules.d/99kiwi-lib/kiwi-mdraid-lib.sh @@ -19,12 +19,14 @@ function deactivate_mdraid { function activate_mdraid { declare kiwi_RaidDev=${kiwi_RaidDev} - mdadm --assemble --scan "${kiwi_RaidDev}" + udevadm lock --device "${kiwi_RaidDev}" \ + mdadm --assemble --scan "${kiwi_RaidDev}" wait_for_storage_device "${kiwi_RaidDev}" set_root_map "${kiwi_RaidDev}" } function resize_mdraid { declare kiwi_RaidDev=${kiwi_RaidDev} - mdadm --grow --size=max "${kiwi_RaidDev}" + udevadm lock --device "${kiwi_RaidDev}" \ + mdadm --grow --size=max "${kiwi_RaidDev}" } diff --git a/dracut/modules.d/99kiwi-lib/kiwi-partitions-lib.sh b/dracut/modules.d/99kiwi-lib/kiwi-partitions-lib.sh index 6fc321af..6704ee25 100644 --- a/dracut/modules.d/99kiwi-lib/kiwi-partitions-lib.sh +++ b/dracut/modules.d/99kiwi-lib/kiwi-partitions-lib.sh @@ -23,9 +23,11 @@ function create_partitions { ;; esac if type partprobe &> /dev/null;then - partprobe "${disk_device}" + udevadm lock --device "${disk_device}" \ + partprobe "${disk_device}" else - partx -u "${disk_device}" + udevadm lock --device "${disk_device}" \ + partx -u "${disk_device}" fi } @@ -59,21 +61,23 @@ function create_msdos_partitions { start_sector_from[$partid]=$( _get_msdos_partition_start_sector "${disk_device}" "${partid}" ) - sfdisk --force --delete "${disk_device}" "${partid}" + udevadm lock --device "${disk_device}" \ + sfdisk --force --delete "${disk_device}" "${partid}" ;; "n") # create a partition... partid=${cmd_list[$index + 2]} part_size_end=${cmd_list[$index + 4]} echo "${start_sector_from[$partid]},${part_size_end}" > /tmp/sfdisk.in - sfdisk --force -N "${partid}" "${disk_device}" < /tmp/sfdisk.in + udevadm lock --device "${disk_device}" \ + sfdisk --force -N "${partid}" "${disk_device}" < /tmp/sfdisk.in ;; "t") # change a partition type... part_type=${cmd_list[$index + 2]} partid=${cmd_list[$index + 1]} - sfdisk --force --change-id "${disk_device}" "${partid}" \ - "${part_type}" + udevadm lock --device "${disk_device}" \ + sfdisk --force --change-id "${disk_device}" "${partid}" "${part_type}" ;; esac index=$((index + 1)) @@ -108,7 +112,8 @@ function create_gpt_partitions { "d") # delete a partition... partid=${cmd_list[$index + 1]} - sgdisk --delete "${partid}" "${disk_device}" + udevadm lock --device "${disk_device}" \ + sgdisk --delete "${partid}" "${disk_device}" ;; "n") # create a partition... @@ -116,17 +121,17 @@ function create_gpt_partitions { partid=${cmd_list[$index + 2]} part_size_start=${cmd_list[$index + 3]} part_size_end=${cmd_list[$index + 4]} - sgdisk --new "${partid}:${part_size_start}:${part_size_end}" \ - "${disk_device}" - sgdisk --change-name "${partid}:${part_name}" \ - "${disk_device}" + udevadm lock --device "${disk_device}" \ + sgdisk --new "${partid}:${part_size_start}:${part_size_end}" "${disk_device}" + udevadm lock --device "${disk_device}" \ + sgdisk --change-name "${partid}:${part_name}" "${disk_device}" ;; "t") # change a partition type... part_type=${cmd_list[$index + 2]} partid=${cmd_list[$index + 1]} - sgdisk --typecode "${partid}:$(_to_guid "${part_type}")" \ - "${disk_device}" + udevadm lock --device "${disk_device}" \ + sgdisk --typecode "${partid}:$(_to_guid "${part_type}")" "${disk_device}" ;; esac index=$((index + 1)) @@ -148,7 +153,8 @@ function create_dasd_partitions { # partition table updated to the actual disk geometry. This is # to circumvent the fdasd limitation of not being capable to # expand the partition table up to the disk size bsc#1209247 - parted --script --machine "${disk_device}" resizepart 1 + udevadm lock --device "${disk_device}" \ + parted --script --machine "${disk_device}" resizepart 1 for cmd in ${partition_setup};do if [ "${ignore_cmd}" = 1 ] && echo "${cmd}" | grep -qE '[dntwq]';then @@ -182,7 +188,8 @@ function create_dasd_partitions { done echo "w" >> ${partition_setup_file} echo "q" >> ${partition_setup_file} - fdasd "${disk_device}" < ${partition_setup_file} 1>&2 + udevadm lock --device "${disk_device}" \ + fdasd "${disk_device}" < ${partition_setup_file} 1>&2 } function get_partition_node_name { @@ -336,7 +343,7 @@ function get_partition_uuid { } function relocate_gpt_at_end_of_disk { - if ! sfdisk --relocate gpt-bak-std "$1";then + if ! udevadm lock --device "$1" sfdisk --relocate gpt-bak-std "$1";then die "Failed to write backup GPT at end of disk" fi } @@ -378,7 +385,8 @@ function activate_boot_partition { pt_table_type=$(get_partition_table_type "${disk_device}") if [[ "$(uname -m)" =~ i.86|x86_64 ]];then if [ "${pt_table_type}" = "dos" ];then - sfdisk --activate "${disk_device}" "${boot_partition_id}" + udevadm lock --device "${disk_device}" \ + sfdisk --activate "${disk_device}" "${boot_partition_id}" fi fi } @@ -393,7 +401,9 @@ function create_hybrid_gpt { # see man sgdisk for details partition_count=3 fi - if ! sgdisk -h "$(seq -s : 1 "${partition_count}")" "${disk_device}";then + if ! udevadm lock --device "${disk_device}" \ + sgdisk -h "$(seq -s : 1 "${partition_count}")" "${disk_device}" + then die "Failed to create hybrid GPT/MBR !" fi }