Expose Disk Image Partitions Safely with kpartx
kpartx turns the partitions inside a disk image into real device-mapper paths, handy right up until you forget to clean them up. This guide builds a repeatable way to inspect the partition table in a disk image, create temporary device-mapper paths for its partitions, and remove those paths afterwards. The examples use kpartx 0.9.4 from the installed kpartx package, version 0.9.4-5ubuntu8.2.
The route
Jump straight to the step you need, or tick off Done means at the end.
- Time: about fifteen minutes.
- You need: a Linux host with kpartx and device-mapper support, a disk image you are allowed to read, and elevated privileges for operations that create or remove mappings. This guide does not mount a filesystem or alter the image.
Safety boundary
Treat an image as untrusted input. Creating a mapping exposes its partition contents to the host. Do not mount an unknown filesystem automatically, and do not use a writable mapping when read-only access is enough.
1. Check the installed command
Start with ordinary, read-only checks. The installed command uses the short options documented by its local manpage; --version is not a supported long option in this build.
$ command -v kpartx
/usr/sbin/kpartx
$ dpkg-query -W -f='${Package} ${Version}\n' kpartx
kpartx 0.9.4-5ubuntu8.2
$ kpartx -v 2>&1 | sed -n '1,3p'
kpartx: invalid option -- 'v'
multipath-tools v0.9.4 (12/19, 2022)
Usage:
The final command is only a syntax probe. It prints usage because -v needs an operation such as -l and a whole-disk argument. The version string is printed by the multipath-tools build while handling invalid arguments, so do not infer that -v means version.
Checkpoint
If command -v finds a different binary, stop and confirm its package and manpage before trusting the examples below.
2. Choose and validate the whole-disk input
Set one shell variable to the image or whole-disk device containing the partition table. Use an explicit path. Do not point kpartx at a partition such as /dev/sdb1, because the command needs the whole disk from which it can discover partitions.
$ IMAGE=/srv/images/example-disk.img
$ test -r "$IMAGE" && printf 'readable: %s\n' "$IMAGE"
readable: /srv/images/example-disk.img
$ file "$IMAGE"
/srv/images/example-disk.img: DOS/MBR boot sector ...
The file result is only a clue, not a complete partition-table audit. If you do not recognise the source or its expected partitions, investigate it before mapping it. Keep the image variable quoted in every command so whitespace in a path cannot change the arguments.
3. Preview the mappings
Use -l to list the partition mappings that -a would add. This is the least disruptive operation in the kpartx workflow, but it can still need access to loop and device-mapper support on the host.
$ sudo kpartx -l "$IMAGE"
loop1p1 : 0 409597 /dev/loop1 3
loop1p2 : 409600 1048576 /dev/loop1 409600
Exact names, offsets and counts depend on the image; treat the output above as representative rather than a value to copy. An error about /dev/mapper/control, the device-mapper kernel driver or loop setup describes the host environment, not necessarily a bad partition table. Check that device-mapper support is available and that the command is running with the privilege your host requires.
Checkpoint
Record the partitions you expect. If the list is empty or surprising, do not continue to -a. Recheck the whole-disk path and partition format first.
4. Add read-only partition mappings
When the preview is sensible, add mappings with -a. Add -r when the image only needs to be inspected. These options change host state, so use elevated privileges and avoid doing this while another tool is automatically probing or mounting new block devices.
$ sudo kpartx -arv "$IMAGE"
add map loop1p1 (254:4): 0 409597 linear 7:1 3
add map loop1p2 (254:5): 0 1048576 linear 7:1 409600
The manpage's -s synchronous mode is the default: kpartx waits until the partitions are created. The command prints one add map line for each mapping in verbose mode. Device names are normally available below /dev/mapper, for example:
$ ls -l /dev/mapper/loop1p*
lrwxrwxrwx 1 root root 7 ... /dev/mapper/loop1p1 -> ../dm-4
lrwxrwxrwx 1 root root 7 ... /dev/mapper/loop1p2 -> ../dm-5
The loop number and device-mapper minor numbers vary. Use the names printed by your own command, not the example names. If you need a different delimiter between the whole-disk name and partition number, supply -p when adding and use the resulting names consistently.
Do not use -f casually. It forces mapping creation and overrides the device's no_partitions feature. The normal path is to understand why partition detection was suppressed, then decide whether forcing it is justified.
5. Inspect a mapped partition without mounting it
Use the mapped path as a block device for a tool that supports read-only inspection. For example, identify the filesystem without changing it:
$ sudo blkid -p -o full /dev/mapper/loop1p1
/dev/mapper/loop1p1: UUID="..." VERSION="..." TYPE="ext4" USAGE="filesystem"
Output varies with the filesystem and image. A mapped partition is not a mounted filesystem. If you later mount it, use a separate, explicitly read-only mount workflow and an isolated mount point; that is outside this guide.
Warning
Never run a filesystem repair tool against a mounted filesystem, and do not assume -r on kpartx replaces all of the safety controls of the tool you run next.
6. Remove the mappings
When inspection is complete, unmount anything you mounted and close tools that still have the mapped devices open. Then remove the mappings with the same whole-disk input:
$ sudo kpartx -dv "$IMAGE"
delete map loop1p1 (254:4)
delete map loop1p2 (254:5)
-d deletes the partition mappings. It does not delete the image. The verbose output should contain one delete map line per mapping. Check that the paths have gone:
$ test ! -e /dev/mapper/loop1p1 && echo 'partition mappings removed'
partition mappings removed
If deletion reports a device is busy, find and stop the process holding it, or undo the mount that still uses it. Do not force removal by killing an unrelated process. Once the holders are gone, repeat the documented -d command. If you used a non-default delimiter or another whole-disk path, use the same mapping identity when cleaning up.
7. Understand the less common switches
- -u updates existing partition mappings after the partition table has changed. Treat that as a state-changing operation and only use it when you deliberately changed the underlying whole-disk layout while the mappings were managed. Do not edit a mounted or actively used image and then update mappings under it.
- -n selects nosync mode and returns before partition creation finishes. That can be useful for a caller with its own readiness handling, but it creates a race for a shell session. Keep the default synchronous mode unless you have a specific reason to manage readiness yourself.
- -g forces GPT interpretation, so use it only when the image is known to require that override.
Tip
For a normal image workflow, the useful sequence is -l to preview, -arv to add read-only mappings, inspection through the printed /dev/mapper paths, and -dv to remove them. A failed preview is a reason to investigate, not a reason to add -f or guess at a partition number.
Done means
- Confirmed the version. You checked the installed kpartx package and used its short-option syntax.
- Used the whole disk. You passed the whole-disk image, not one of its partitions.
- Previewed first. You previewed the partition mappings before creating them.
- Used read-only where possible. You used
-rfor inspection and treated mapping creation as a privileged state change. - Used the real names. You used the actual
/dev/mappernames printed on your host. - Cleaned up. You removed the mappings and confirmed they no longer exist.