Blob Blame History Raw
From 2c5db60e46ad7f03789fe7e2beedb15496930468 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner@ubuntu.com>
Date: Mon, 20 May 2019 16:13:28 +0200
Subject: [PATCH] tests: add close_range() tests
Git-commit: 2c5db60e46ad7f03789fe7e2beedb15496930468
Patch-mainline: v5.9-rc1
References: jsc#SLE-17337, bsc#1179090

This adds basic tests for the new close_range() syscall.
- test that no invalid flags can be passed
- test that a range of file descriptors is correctly closed
- test that a range of file descriptors is correctly closed if there there
  are already closed file descriptors in the range
- test that max_fd is correctly capped to the current fdtable maximum

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jann Horn <jannh@google.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Dmitry V. Levin <ldv@altlinux.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-api@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
Acked-by: Michal Hocko <mhocko@suse.com>

---
 tools/testing/selftests/Makefile                |    1 
 tools/testing/selftests/core/.gitignore         |    1 
 tools/testing/selftests/core/Makefile           |    7 +
 tools/testing/selftests/core/close_range_test.c |   90 ++++++++++++++++++++++++
 4 files changed, 99 insertions(+)
 create mode 100644 tools/testing/selftests/core/.gitignore
 create mode 100644 tools/testing/selftests/core/Makefile
 create mode 100644 tools/testing/selftests/core/close_range_test.c

--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -4,6 +4,7 @@ TARGETS += bpf
 TARGETS += breakpoints
 TARGETS += capabilities
 TARGETS += cgroup
+TARGETS += core
 TARGETS += cpufreq
 TARGETS += cpu-hotplug
 TARGETS += drivers/dma-buf
--- /dev/null
+++ b/tools/testing/selftests/core/.gitignore
@@ -0,0 +1 @@
+close_range_test
--- /dev/null
+++ b/tools/testing/selftests/core/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+CFLAGS += -g -I../../../../usr/include/
+
+TEST_GEN_PROGS := close_range_test
+
+include ../lib.mk
+
--- /dev/null
+++ b/tools/testing/selftests/core/close_range_test.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/kernel.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syscall.h>
+#include <unistd.h>
+
+#include "../kselftest_harness.h"
+
+#ifndef __NR_close_range
+#define __NR_close_range -1
+#endif
+
+static inline int sys_close_range(unsigned int fd, unsigned int max_fd,
+				  unsigned int flags)
+{
+	return syscall(__NR_close_range, fd, max_fd, flags);
+}
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+TEST(close_range)
+{
+	int i, ret;
+	int open_fds[101];
+
+	for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
+		int fd;
+
+		fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+		ASSERT_GE(fd, 0) {
+			if (errno == ENOENT)
+				XFAIL(return, "Skipping test since /dev/null does not exist");
+		}
+
+		open_fds[i] = fd;
+	}
+
+	EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) {
+		if (errno == ENOSYS)
+			XFAIL(return, "close_range() syscall not supported");
+	}
+
+	EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0));
+
+	for (i = 0; i <= 50; i++)
+		EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
+
+	for (i = 51; i <= 100; i++)
+		EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
+
+	/* create a couple of gaps */
+	close(57);
+	close(78);
+	close(81);
+	close(82);
+	close(84);
+	close(90);
+
+	EXPECT_EQ(0, sys_close_range(open_fds[51], open_fds[92], 0));
+
+	for (i = 51; i <= 92; i++)
+		EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
+
+	for (i = 93; i <= 100; i++)
+		EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
+
+	/* test that the kernel caps and still closes all fds */
+	EXPECT_EQ(0, sys_close_range(open_fds[93], open_fds[99], 0));
+
+	for (i = 93; i <= 99; i++)
+		EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
+
+	EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
+
+	EXPECT_EQ(0, sys_close_range(open_fds[100], open_fds[100], 0));
+
+	EXPECT_EQ(-1, fcntl(open_fds[100], F_GETFL));
+}
+
+TEST_HARNESS_MAIN