selftests/pidfd: decode pidfd file handles withou having to specify an fd
authorChristian Brauner <brauner@kernel.org>
Tue, 24 Jun 2025 08:29:14 +0000 (10:29 +0200)
committerChristian Brauner <brauner@kernel.org>
Tue, 24 Jun 2025 15:06:35 +0000 (17:06 +0200)
Link: https://lore.kernel.org/20250624-work-pidfs-fhandle-v2-11-d02a04858fe3@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
tools/testing/selftests/pidfd/Makefile
tools/testing/selftests/pidfd/pidfd.h
tools/testing/selftests/pidfd/pidfd_file_handle_test.c

index 03a6eede9c9e3780ebdcadbaefc9776760f16d1a..764a8f9ecefab1accf6a1fc1e662c8a5691d61cc 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-CFLAGS += -g $(KHDR_INCLUDES) -pthread -Wall
+CFLAGS += -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) -pthread -Wall
 
 TEST_GEN_PROGS := pidfd_test pidfd_fdinfo_test pidfd_open_test \
        pidfd_poll_test pidfd_wait pidfd_getfd_test pidfd_setns_test \
index 5dfeb1bdf399c5adcfa1c8ace701d491364b35ae..cd244d0860ff9acf7a30818420494ed05abf4064 100644 (file)
 #include "../kselftest.h"
 #include "../clone3/clone3_selftests.h"
 
+#ifndef FD_PIDFS_ROOT
+#define FD_PIDFS_ROOT -10002
+#endif
+
 #ifndef P_PIDFD
 #define P_PIDFD 3
 #endif
index 439b9c6c04573375f1a09b2550af4172a338a3d5..6bd2e9c9565b874f3c4758d87fd422954b1e0e6c 100644 (file)
@@ -500,4 +500,64 @@ TEST_F(file_handle, valid_name_to_handle_at_flags)
        ASSERT_EQ(close(pidfd), 0);
 }
 
+/*
+ * That we decode a file handle without having to pass a pidfd.
+ */
+TEST_F(file_handle, decode_purely_based_on_file_handle)
+{
+       int mnt_id;
+       struct file_handle *fh;
+       int pidfd = -EBADF;
+       struct stat st1, st2;
+
+       fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
+       ASSERT_NE(fh, NULL);
+       memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
+       fh->handle_bytes = MAX_HANDLE_SZ;
+
+       ASSERT_EQ(name_to_handle_at(self->child_pidfd1, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
+
+       ASSERT_EQ(fstat(self->child_pidfd1, &st1), 0);
+
+       pidfd = open_by_handle_at(FD_PIDFS_ROOT, fh, 0);
+       ASSERT_GE(pidfd, 0);
+
+       ASSERT_EQ(fstat(pidfd, &st2), 0);
+       ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+
+       ASSERT_EQ(close(pidfd), 0);
+
+       pidfd = open_by_handle_at(FD_PIDFS_ROOT, fh, O_CLOEXEC);
+       ASSERT_GE(pidfd, 0);
+
+       ASSERT_EQ(fstat(pidfd, &st2), 0);
+       ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+
+       ASSERT_EQ(close(pidfd), 0);
+
+       pidfd = open_by_handle_at(FD_PIDFS_ROOT, fh, O_NONBLOCK);
+       ASSERT_GE(pidfd, 0);
+
+       ASSERT_EQ(fstat(pidfd, &st2), 0);
+       ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+
+       ASSERT_EQ(close(pidfd), 0);
+
+       pidfd = open_by_handle_at(self->pidfd, fh, 0);
+       ASSERT_GE(pidfd, 0);
+
+       ASSERT_EQ(fstat(pidfd, &st2), 0);
+       ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+
+       ASSERT_EQ(close(pidfd), 0);
+
+       pidfd = open_by_handle_at(-EBADF, fh, 0);
+       ASSERT_LT(pidfd, 0);
+
+       pidfd = open_by_handle_at(AT_FDCWD, fh, 0);
+       ASSERT_LT(pidfd, 0);
+
+       free(fh);
+}
+
 TEST_HARNESS_MAIN