diff mbox series

[v2,4/7] Add ioctl_ficlone03 test

Message ID 20240723-ioctl_ficlone-v2-4-33075bbc117f@suse.com
State Accepted
Headers show
Series Add ioctl_ficlone testing suite | expand

Commit Message

Andrea Cervesato July 23, 2024, 7:15 a.m. UTC
From: Andrea Cervesato <andrea.cervesato@suse.com>

This test verifies that ioctl() FICLONE/FICLONERANGE feature correctly
raises exceptions when it's supposed to.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/syscalls                                  |   1 +
 testcases/kernel/syscalls/ioctl/.gitignore        |   1 +
 testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c | 124 ++++++++++++++++++++++
 3 files changed, 126 insertions(+)

Comments

Cyril Hrubis July 24, 2024, 12:20 p.m. UTC | #1
Hi!
Pushed with a small fix, thanks.

The immutable file has to be on the MNTPOINT as well as th source for
the immutable file, otherwise we get EOPNOTSUPP instead of EPERM since
the check for supported filesystems kicks in first:

diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c b/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c
index be069836a..406b64cca 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c
@@ -37,7 +37,7 @@ static struct tcase {
        {&wo_file, &rw_file, EBADF, "write-only source"},
        {&rw_file, &dir_fd, EISDIR, "source is a directory"},
        {&dir_fd, &rw_file, EISDIR, "destination is a directory"},
-       {&rw_file, &immut_fd, EPERM, "destination is immutable"},
+       {&mnt_file, &immut_fd, EPERM, "destination is immutable"},
        {&rw_file, &mnt_file, EXDEV, "destination is on a different mount"},
        {&mnt_file, &rw_file, EXDEV, "source is on a different mount"},
 };
@@ -72,7 +72,7 @@ static void setup(void)
        dir_fd = SAFE_OPEN("mydir", O_DIRECTORY, 0640);

        attr = FS_IMMUTABLE_FL;
-       immut_fd = SAFE_OPEN("immutable", O_CREAT | O_RDWR, 0640);
+       immut_fd = SAFE_OPEN(MNTPOINT"/immutable", O_CREAT | O_RDWR, 0640);
        SAFE_IOCTL(immut_fd, FS_IOC_SETFLAGS, &attr);

        mnt_file = SAFE_OPEN(MNTPOINT"/file", O_CREAT | O_RDWR, 0640);
diff mbox series

Patch

diff --git a/runtest/syscalls b/runtest/syscalls
index 48fe85c97..5aef2b97e 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -594,6 +594,7 @@  ioctl_sg01 ioctl_sg01
 
 ioctl_ficlone01 ioctl_ficlone01
 ioctl_ficlone02 ioctl_ficlone02
+ioctl_ficlone03 ioctl_ficlone03
 
 inotify_init1_01 inotify_init1_01
 inotify_init1_02 inotify_init1_02
diff --git a/testcases/kernel/syscalls/ioctl/.gitignore b/testcases/kernel/syscalls/ioctl/.gitignore
index 3d25fdfb2..d0b470714 100644
--- a/testcases/kernel/syscalls/ioctl/.gitignore
+++ b/testcases/kernel/syscalls/ioctl/.gitignore
@@ -24,3 +24,4 @@ 
 /ioctl_sg01
 /ioctl_ficlone01
 /ioctl_ficlone02
+/ioctl_ficlone03
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c b/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c
new file mode 100644
index 000000000..be069836a
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ficlone03.c
@@ -0,0 +1,124 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2024 Andrea Cervesato andrea.cervesato@suse.com
+ */
+
+/*\
+ * [Description]
+ *
+ * This test verifies that ioctl() FICLONE/FICLONERANGE feature correctly raises
+ * exceptions when it's supposed to.
+ */
+
+#include "tst_test.h"
+#include "lapi/fs.h"
+
+#define MNTPOINT "mnt"
+
+static struct file_clone_range *clone_range;
+
+static int invalid_fd = -1;
+static int rw_file = -1;
+static int ro_file = -1;
+static int wo_file = -1;
+static int dir_fd = -1;
+static int immut_fd = -1;
+static int mnt_file = -1;
+
+static struct tcase {
+	int *src_fd;
+	int *dst_fd;
+	int errno_exp;
+	char *msg;
+} tcases[] = {
+	{&invalid_fd, &rw_file, EBADF, "invalid source"},
+	{&rw_file, &invalid_fd, EBADF, "invalid destination"},
+	{&rw_file, &ro_file, EBADF, "read-only destination"},
+	{&wo_file, &rw_file, EBADF, "write-only source"},
+	{&rw_file, &dir_fd, EISDIR, "source is a directory"},
+	{&dir_fd, &rw_file, EISDIR, "destination is a directory"},
+	{&rw_file, &immut_fd, EPERM, "destination is immutable"},
+	{&rw_file, &mnt_file, EXDEV, "destination is on a different mount"},
+	{&mnt_file, &rw_file, EXDEV, "source is on a different mount"},
+};
+
+static void run(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+
+	TST_EXP_FAIL(ioctl(*tc->dst_fd, FICLONE, *tc->src_fd),
+		tc->errno_exp,
+		"%s", tc->msg);
+
+	clone_range->src_fd = *tc->src_fd;
+
+	TST_EXP_FAIL(ioctl(*tc->dst_fd, FICLONERANGE, clone_range),
+		tc->errno_exp,
+		"%s", tc->msg);
+}
+
+static void setup(void)
+{
+	int attr;
+	struct stat sb;
+
+	rw_file = SAFE_OPEN("ok_only", O_CREAT | O_RDWR, 0640);
+	ro_file = SAFE_OPEN("rd_only", O_CREAT | O_RDONLY, 0640);
+	wo_file = SAFE_OPEN("rw_only", O_CREAT | O_WRONLY, 0640);
+
+	if (access("mydir", F_OK) == -1)
+		SAFE_MKDIR("mydir", 0640);
+
+	dir_fd = SAFE_OPEN("mydir", O_DIRECTORY, 0640);
+
+	attr = FS_IMMUTABLE_FL;
+	immut_fd = SAFE_OPEN("immutable", O_CREAT | O_RDWR, 0640);
+	SAFE_IOCTL(immut_fd, FS_IOC_SETFLAGS, &attr);
+
+	mnt_file = SAFE_OPEN(MNTPOINT"/file", O_CREAT | O_RDWR, 0640);
+
+	SAFE_STAT(MNTPOINT, &sb);
+
+	clone_range->src_offset = 0;
+	clone_range->src_length = sb.st_blksize;
+	clone_range->dest_offset = 0;
+}
+
+static void cleanup(void)
+{
+	int attr;
+
+	SAFE_IOCTL(immut_fd, FS_IOC_GETFLAGS, &attr);
+	attr &= ~FS_IMMUTABLE_FL;
+	SAFE_IOCTL(immut_fd, FS_IOC_SETFLAGS, &attr);
+	SAFE_CLOSE(immut_fd);
+
+	SAFE_CLOSE(rw_file);
+	SAFE_CLOSE(ro_file);
+	SAFE_CLOSE(wo_file);
+	SAFE_CLOSE(dir_fd);
+	SAFE_CLOSE(mnt_file);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+	.cleanup = cleanup,
+	.min_kver = "4.5",
+	.needs_root = 1,
+	.mount_device = 1,
+	.mntpoint = MNTPOINT,
+	.filesystems = (struct tst_fs []) {
+		{.type = "btrfs"},
+		{
+			.type = "xfs",
+			.mkfs_opts = (const char *const []) {"-m", "reflink=1", NULL},
+		},
+		{}
+	},
+	.bufs = (struct tst_buffers []) {
+		{&clone_range, .size = sizeof(struct file_clone_range)},
+		{},
+	}
+};