Menu

#443 ocs-update-initrd cleanup can remove /dev from restored filesystem if root umount fails

testing_clonezilla
open
nobody
None
8
2 days ago
2 days ago
Jørgen Ask
No

Clonezilla version:
Clonezilla Live 3.3.0-33 amd64

Hardware:
Dell XPS 13 9340
Internal SSD: KIOXIA BG6 512 GB NVMe
Restored OS: Debian

Description:

I encountered a boot failure after restoring a Clonezilla disk image to the same machine and SSD.

The Clonezilla restore itself completed, but Debian subsequently failed to boot normally. Inspection from a Debian Live environment showed that the /dev directory was missing from the restored root filesystem.

I initially suspected either the image, Partclone, filesystem checking, or GRUB. I have since been able to eliminate those possibilities and reproduce a failure path in Clonezilla 3.3.0-33 which can produce exactly this result.

Image verification:

The compressed Partclone image was successfully verified with:

sudo zstd -t nvme0n1p2.ext4-ptcl-img.zst

The Partclone image itself was then checked:

sudo zstd -dc nvme0n1p2.ext4-ptcl-img.zst | sudo /usr/sbin/partclone.chkimg -s -

Result:

Partclone successfully checked the image (-)
Checked successfully.

I also manually restored the Partclone image to a separate sparse image file. The resulting ext4 filesystem contained the original /dev directory with mode 0755.

Therefore /dev is present in the Clonezilla backup and Partclone restores it correctly.

I additionally ran e2fsck -f against the manually restored image. /dev remained present and its inode metadata was unchanged.

Evidence from the affected restored SSD:

Using debugfs, the /dev directory in the backup had:

Inode: 23855105
Type: directory
Mode: 0755
crtime: Tue Aug 25 12:09:57 2026

On the affected SSD, /dev had to be manually recreated during recovery. Its creation time then became:

Fri Sep 4 21:55:43 2026

This exactly corresponds to the time when I ran mkdir during recovery.

Other top-level directories retained their original creation metadata. This strongly indicates that /dev alone had disappeared from the restored root filesystem.

Relevant Clonezilla code:

In Clonezilla Live 3.3.0-33, ocs-sr enables initramfs updating by default:

do_update_initrd="yes"

During restore, task_restoreparts() eventually invokes ocs-update-initrd, which calls:

do_run_update_initrd_from_restored_os()

This function bind-mounts /dev into the restored root filesystem while running the initramfs update.

Its cleanup sequence includes:

unmount_wait_and_try $mnt_pnt/$extra_root_path/sys
unmount_wait_and_try $mnt_pnt/$extra_root_path/proc
unmount_wait_and_try $mnt_pnt/$extra_root_path/dev
...
unmount_wait_and_try $mnt_pnt
[ -d "$mnt_pnt/$extra_root_path/dev" ] && rmdir $mnt_pnt/$extra_root_path/dev

The implementation of unmount_wait_and_try() in ocs-functions is:

unmount_wait_and_try() {
local mnt_dev_pnt="$1"
for i in seq 1 25; do
sleep 0.2
if umount $mnt_dev_pnt 2>/dev/null; then
break
fi
done
}

If all 25 umount attempts fail, the function simply returns after approximately five seconds. It does not return an error indicating that the filesystem remains mounted, and the caller does not verify that $mnt_pnt is actually unmounted before executing:

[ -d "$mnt_pnt/$extra_root_path/dev" ] && rmdir $mnt_pnt/$extra_root_path/dev

If the restored root filesystem is still mounted at $mnt_pnt, this rmdir operates on the real /dev directory of the restored filesystem.

Reproduction:

I reproduced this behavior independently using a disposable 128 MB ext4 image.

The test:

  1. created a normal /dev directory in the test filesystem;
  2. bind-mounted the running system's /dev over it;
  3. deliberately kept the root filesystem busy so its final umount could not succeed;
  4. used the same 25 x 0.2 second retry logic as unmount_wait_and_try();
  5. confirmed that the root filesystem remained mounted after the function returned;
  6. executed the same conditional rmdir;
  7. unmounted and remounted the test filesystem to verify the result.

Result:

CONFIRMED: root is still mounted after unmount_wait_and_try.
CONFIRMED: /dev on the restored filesystem was deleted.

=== CHECK AFTER REMOUNT ===
CONFIRMED: /dev is still missing after remounting.
This demonstrates that rmdir actually modified the ext4 filesystem.

=== TEST COMPLETED ===
The failure mechanism has been reproduced.

Expected behavior:

Failure to unmount the restored root filesystem should prevent cleanup operations from removing directories beneath that mountpoint.

unmount_wait_and_try() should report failure after exhausting its retries, and the caller should not execute rmdir against paths beneath $mnt_pnt unless it has positively verified that the restored filesystem is no longer mounted.

Actual behavior:

unmount_wait_and_try() silently gives up after approximately five seconds. Execution then continues.

If $mnt_pnt remains mounted, the subsequent:

rmdir "$mnt_pnt/$extra_root_path/dev"

can remove /dev from the restored filesystem.

Suggested fix:

I suggest making unmount_wait_and_try() explicitly return failure if all attempts fail, for example:

unmount_wait_and_try() {
local mnt_dev_pnt="$1"

for i in $(seq 1 25); do
sleep 0.2
if umount "$mnt_dev_pnt" 2>/dev/null; then
return 0
fi
done

return 1
}

The caller should then abort or skip the relevant cleanup when unmounting fails.

As an additional safeguard, the code could explicitly verify that $mnt_pnt is no longer a mountpoint before performing any rmdir operations beneath it.

Silencing umount errors also makes this failure difficult to diagnose from restore output.

Important qualification:

I do not have the original detailed restore log proving that the final root umount failed during the specific restore that caused my boot problem.

However:

  • the original Clonezilla image contains /dev;
  • the compressed image and Partclone checksums pass;
  • a manual Partclone restore preserves /dev;
  • e2fsck -f preserves /dev;
  • the affected SSD did not contain the original /dev after the Clonezilla restore;
  • filesystem metadata shows that /dev was subsequently recreated during manual recovery;
  • and the Clonezilla cleanup code above has been independently reproduced deleting /dev from an ext4 filesystem when the root umount fails.

Therefore I believe this is a real failure path in the Clonezilla restore post-processing code.

Additional information:

Restore mode/command:
Clonezilla restoredisk mode. The exact ocs-sr restore command was not preserved.

Exact restore date/time:
4 September 2026, approximately 21:22 CEST.

Clonezilla version/media:
Clonezilla Live 3.3.0-33 amd64. The boot media identifies itself as
3.3.0-33-amd64. Exact original ISO filename not currently recorded.

Additional logs/screenshots:
The original detailed restore log was not preserved.

However, I can provide the following diagnostic evidence if required:

  • successful zstd integrity test of the original partition image;
  • successful partclone.chkimg verification;
  • Partclone image metadata;
  • debugfs inode/timestamp comparison between the backup and restored SSD;
  • relevant source code from ocs-functions and ocs-update-initrd in
    Clonezilla Live 3.3.0-33;
  • complete reproduction procedure demonstrating deletion of /dev when
    the restored root filesystem remains mounted after unmount_wait_and_try();
  • reproduction output confirming that /dev remains absent after the
    test filesystem is unmounted and remounted.

Discussion


Log in to post a comment.