linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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;
as well as URLs for NNTP newsgroup(s).