* [PATCH blktests] loop/014: Add test for backing file on loop device partition
@ 2026-08-20 20:00 Bart Van Assche
0 siblings, 0 replies; only message in thread
From: Bart Van Assche @ 2026-08-20 20:00 UTC (permalink / raw)
To: Shin'ichiro Kawasaki; +Cc: linux-block, Bart Van Assche
Add a new loop driver test that verifies that attempting to set the
backing file of a loop device to a file located on a filesystem on one of
the same loop device's partitions fails as expected by triggering the
kernel function loop_validate_file().
Modify src/loop_change_fd.c to accept a -r option to open the loop device
and backing file in read-only mode (O_RDONLY).
The test performs the following steps:
- Create a 1 GB image file ($TMPDIR/img).
- Instantiate a loop device for the image file with partition scanning
enabled.
- Create two partitions of equal size on that loop device.
- Format the second partition with the ext4 filesystem and mount it.
- Create a 1 GB file on the mounted filesystem.
- Unmount the filesystem, detach the loop device, and re-instantiate it in
read-only mode.
- Mount the partition read-only.
- Use src/loop_change_fd -r to attempt to change the backing file
descriptor of the loop device to the file on its own partition via
LOOP_CHANGE_FD, and verify that loop_validate_file() rejects it.
- Clean up by unmounting the filesystem and detaching the loop device.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
src/loop_change_fd.c | 20 ++++++--
tests/loop/014 | 107 +++++++++++++++++++++++++++++++++++++++++++
tests/loop/014.out | 2 +
3 files changed, 125 insertions(+), 4 deletions(-)
create mode 100755 tests/loop/014
create mode 100644 tests/loop/014.out
diff --git a/src/loop_change_fd.c b/src/loop_change_fd.c
index b124d829f380..722f14d3d91f 100644
--- a/src/loop_change_fd.c
+++ b/src/loop_change_fd.c
@@ -11,25 +11,37 @@
void usage(const char *progname)
{
- fprintf(stderr, "usage: %s LOOPDEV PATH\n", progname);
+ fprintf(stderr, "usage: %s [-r] LOOPDEV PATH\n", progname);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
+ int flags = O_RDWR;
int ret;
int fd, filefd;
+ int c;
- if (argc != 3)
+ while ((c = getopt(argc, argv, "r")) != -1) {
+ switch (c) {
+ case 'r':
+ flags = O_RDONLY;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if (optind + 2 != argc)
usage(argv[0]);
- fd = open(argv[1], O_RDWR);
+ fd = open(argv[optind], flags);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
- filefd = open(argv[2], O_RDWR);
+ filefd = open(argv[optind + 1], flags);
if (filefd == -1) {
perror("open");
return EXIT_FAILURE;
diff --git a/tests/loop/014 b/tests/loop/014
new file mode 100755
index 000000000000..5814b8148a26
--- /dev/null
+++ b/tests/loop/014
@@ -0,0 +1,107 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-3.0+
+# Copyright (C) 2026 Google LLC
+#
+# Verify that attempting to change a loop device's backing file (via
+# LOOP_CHANGE_FD) to a file on a filesystem residing on one of its own
+# partitions triggers the kernel function loop_validate_file() and fails.
+
+. tests/loop/rc
+
+DESCRIPTION="trigger loop_validate_file() when changing backing file to own partition"
+QUICK=1
+
+loop_device=
+mount_dir=
+
+requires() {
+ _have_program mkfs.ext4
+ _have_program parted
+ _have_src_program loop_change_fd
+}
+
+cleanup() {
+ if [[ -n "$mount_dir" ]]; then
+ umount "$mount_dir" &>/dev/null
+ fi
+ if [[ -n "$loop_device" ]]; then
+ losetup --detach "$loop_device" &>/dev/null
+ fi
+}
+
+test() {
+ echo "Running ${TEST_NAME}"
+ _register_test_cleanup cleanup
+
+ mount_dir="$TMPDIR/mnt"
+
+ truncate -s 1G "$TMPDIR/img"
+
+ if ! loop_device="$(losetup --find --partscan --show "$TMPDIR/img")"; then
+ echo "Failed to instantiate loop device"
+ return 1
+ fi
+
+ if ! parted --script "$loop_device" \
+ mklabel gpt \
+ mkpart primary 0% 50% \
+ mkpart primary 50% 100% >>"$FULL" 2>&1; then
+ echo "Failed to create partitions on loop device"
+ return 1
+ fi
+
+ udevadm settle
+
+ local part="${loop_device}p2"
+ if [[ ! -b "$part" ]]; then
+ echo "Partition $part does not exist"
+ return 1
+ fi
+
+ if ! mkfs.ext4 -F "$part" >>"$FULL" 2>&1; then
+ echo "Failed to format $part with ext4"
+ return 1
+ fi
+
+ mkdir -p "$mount_dir"
+ if ! mount -t ext4 "$part" "$mount_dir" >>"$FULL" 2>&1; then
+ echo "Failed to mount $part on $mount_dir"
+ return 1
+ fi
+
+ truncate -s 1G "$mount_dir/file"
+
+ umount "$mount_dir"
+ losetup --detach "$loop_device"
+ udevadm settle
+
+ # Reopen the loop device in read-only mode so that LOOP_CHANGE_FD can be used.
+ if ! loop_device="$(losetup --read-only --partscan --find --show "$TMPDIR/img")"; then
+ echo "Failed to re-instantiate loop device in read-only mode"
+ return 1
+ fi
+
+ udevadm settle
+
+ part="${loop_device}p2"
+ if ! mount -o ro -t ext4 "$part" "$mount_dir" >>"$FULL" 2>&1; then
+ echo "Failed to mount $part read-only on $mount_dir"
+ return 1
+ fi
+
+ # LOOP_CHANGE_FD triggers loop_validate_file() in the kernel, which must
+ # detect that the backing file resides on a partition of this loop device
+ # and reject the change.
+ if src/loop_change_fd -r "$loop_device" "$mount_dir/file" >>"$FULL" 2>&1; then
+ echo "Changing backing file succeeded unexpectedly"
+ fi
+
+ umount "$mount_dir"
+ mount_dir=
+
+ losetup --detach "$loop_device"
+ loop_device=
+ udevadm settle
+
+ echo "Test complete"
+}
diff --git a/tests/loop/014.out b/tests/loop/014.out
new file mode 100644
index 000000000000..78a7928c5249
--- /dev/null
+++ b/tests/loop/014.out
@@ -0,0 +1,2 @@
+Running loop/014
+Test complete
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-08-20 20:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 20:00 [PATCH blktests] loop/014: Add test for backing file on loop device partition Bart Van Assche
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox