All of lore.kernel.org
 help / color / mirror / Atom feed
From: Federico Bonfiglio <fedebonfi95@gmail.com>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH v4 2/2] Test ioctl syscall for NS_GET_* requests
Date: Thu, 28 Mar 2019 21:22:52 +0100	[thread overview]
Message-ID: <20190328202252.7927-1-fedebonfi95@gmail.com> (raw)
In-Reply-To: <20190326192052.GA15776@rei.lan>

---
 include/lapi/ioctl_ns.h                      | 28 ++++++++++
 runtest/syscalls                             |  8 +++
 testcases/kernel/syscalls/ioctl/.gitignore   |  7 +++
 testcases/kernel/syscalls/ioctl/ioctl_ns01.c | 65 +++++++++++++++++++++++
 testcases/kernel/syscalls/ioctl/ioctl_ns02.c | 49 +++++++++++++++++
 testcases/kernel/syscalls/ioctl/ioctl_ns04.c | 50 ++++++++++++++++++
 testcases/kernel/syscalls/ioctl/ioctl_ns05.c | 48 +++++++++++++++++
 testcases/kernel/syscalls/ioctl/ioctl_ns06.c | 77 +++++++++++++++++++++++++++
 testcases/kernel/syscalls/ioctl/ioctl_ns07.c | 78 ++++++++++++++++++++++++++++
 testcases/kernel/syscalls/ioctl/ioctl_ns08.c | 48 +++++++++++++++++
 10 files changed, 458 insertions(+)
 create mode 100644 include/lapi/ioctl_ns.h
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns01.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns02.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns04.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns05.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns06.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns07.c
 create mode 100644 testcases/kernel/syscalls/ioctl/ioctl_ns08.c

diff --git a/include/lapi/ioctl_ns.h b/include/lapi/ioctl_ns.h
new file mode 100644
index 000000000..2fb4f4cfb
--- /dev/null
+++ b/include/lapi/ioctl_ns.h
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+#ifndef IOCTL_NS_H__
+#define IOCTL_NS_H__
+
+#include <asm-generic/ioctl.h>
+
+#ifndef NSIO
+#define NSIO	0xb7
+#endif
+#ifndef NS_GET_PARENT
+#define NS_GET_PARENT		_IO(NSIO, 0x2)
+#endif
+#ifndef NS_GET_OWNER_UID
+#define NS_GET_OWNER_UID	_IO(NSIO, 0x4)
+#endif
+#ifndef NS_GET_USERNS
+#define NS_GET_USERNS		_IO(NSIO, 0x1)
+#endif
+#ifndef NS_GET_NSTYPE
+#define NS_GET_NSTYPE		_IO(NSIO, 0x3)
+#endif
+
+
+#endif /* IOCTL_NS_H__ */
diff --git a/runtest/syscalls b/runtest/syscalls
index cf8189ebd..58df02bf1 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -504,6 +504,14 @@ ioctl06      ioctl06
 ioctl07      ioctl07
 ioctl08      ioctl08
 
+ioctl_ns01 ioctl_ns01
+ioctl_ns02 ioctl_ns02
+ioctl_ns04 ioctl_ns04
+ioctl_ns05 ioctl_ns05
+ioctl_ns06 ioctl_ns06
+ioctl_ns07 ioctl_ns07
+ioctl_ns08 ioctl_ns08
+
 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 4d480a0ed..53a2d7b7b 100644
--- a/testcases/kernel/syscalls/ioctl/.gitignore
+++ b/testcases/kernel/syscalls/ioctl/.gitignore
@@ -6,3 +6,10 @@
 /ioctl06
 /ioctl07
 /ioctl08
+/ioctl_ns01
+/ioctl_ns02
+/ioctl_ns04
+/ioctl_ns05
+/ioctl_ns06
+/ioctl_ns07
+/ioctl_ns08
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns01.c b/testcases/kernel/syscalls/ioctl/ioctl_ns01.c
new file mode 100644
index 000000000..340cb315f
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns01.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_PARENT request.
+ *
+ * Parent process tries to get parent of initial namespace, which should
+ * fail with EPERM because it has no parent.
+ *
+ * Child process has a new pid namespace, which should make the call fail
+ * with EPERM error.
+ *
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <sched.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+static void setup(void)
+{
+	int exists = access("/proc/self/ns/pid", F_OK);
+
+	if (exists < 0)
+		tst_res(TCONF, "namespace not available");
+}
+
+static void test_ns_get_parent(void)
+{
+	int fd, parent_fd;
+
+	fd = SAFE_OPEN("/proc/self/ns/pid", O_RDONLY);
+	parent_fd = ioctl(fd, NS_GET_PARENT);
+	if (parent_fd == -1) {
+		if (errno == EPERM)
+			tst_res(TPASS, "NS_GET_PARENT fails with EPERM");
+		else
+			tst_res(TFAIL | TERRNO, "unexpected ioctl error");
+	} else {
+		SAFE_CLOSE(fd);
+		tst_res(TFAIL, "call to ioctl succeded");
+	}
+}
+
+static void run(void)
+{
+	test_ns_get_parent();
+	SAFE_UNSHARE(CLONE_NEWPID);
+
+	pid_t pid = SAFE_FORK();
+
+	if (pid == 0)
+		test_ns_get_parent();
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.forks_child = 1,
+	.needs_root = 1,
+	.min_kver = "4.9",
+	.setup = setup
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns02.c b/testcases/kernel/syscalls/ioctl/ioctl_ns02.c
new file mode 100644
index 000000000..4f5cb1427
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns02.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_PARENT request.
+ *
+ * Tries to get namespace parent for UTS namespace, which
+ * should make the call fail with EINVAL, being a nonhierarchical
+ * namespace.
+ *
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+static void setup(void)
+{
+	int exists = access("/proc/self/ns/uts", F_OK);
+
+	if (exists < 0)
+		tst_res(TCONF, "namespace not available");
+}
+
+static void run(void)
+{
+	int fd, parent_fd;
+
+	fd = SAFE_OPEN("/proc/self/ns/uts", O_RDONLY);
+	parent_fd = ioctl(fd, NS_GET_PARENT);
+	if (parent_fd == -1) {
+		if (errno == EINVAL)
+			tst_res(TPASS, "NS_GET_PARENT fails with EINVAL");
+		else
+			tst_res(TFAIL | TERRNO, "unexpected ioctl error");
+	} else {
+		SAFE_CLOSE(fd);
+		tst_res(TFAIL, "call to ioctl succeded");
+	}
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.min_kver = "4.9",
+	.setup = setup
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns04.c b/testcases/kernel/syscalls/ioctl/ioctl_ns04.c
new file mode 100644
index 000000000..2e19cff3a
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns04.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_OWNER_UID request.
+ *
+ * Calls ioctl for a UTS namespace, which isn't a user namespace.
+ * This should make the call fail with EINVAL.
+ *
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+static void setup(void)
+{
+	int exists = access("/proc/self/ns/uts", F_OK);
+
+	if (exists < 0)
+		tst_res(TCONF, "namespace not available");
+}
+
+static void run(void)
+{
+	int fd, owner_fd;
+
+	fd = SAFE_OPEN("/proc/self/ns/uts", O_RDONLY);
+	uid_t uid;
+
+	owner_fd = ioctl(fd, NS_GET_OWNER_UID, &uid);
+	if (owner_fd == -1) {
+		if (errno == EINVAL)
+			tst_res(TPASS, "NS_GET_OWNER_UID fails, UTS namespace");
+		else
+			tst_res(TFAIL | TERRNO, "unexpected ioctl error");
+	} else {
+		SAFE_CLOSE(fd);
+		tst_res(TFAIL, "call to ioctl succeded");
+	}
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.min_kver = "4.11",
+	.setup = setup
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns05.c b/testcases/kernel/syscalls/ioctl/ioctl_ns05.c
new file mode 100644
index 000000000..b9181cb3d
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns05.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_USERNS request.
+ *
+ * Owning user namespace of process calling ioctl is out of scope,
+ * which should make the call fail with EPERM.
+ *
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+static void setup(void)
+{
+	int exists = access("/proc/self/ns/user", F_OK);
+
+	if (exists < 0)
+		tst_res(TCONF, "namespace not available");
+}
+
+static void run(void)
+{
+	int fd, parent_fd;
+
+	fd = SAFE_OPEN("/proc/self/ns/user", O_RDONLY);
+	parent_fd = ioctl(fd, NS_GET_USERNS);
+	if (parent_fd == -1) {
+		if (errno == EPERM)
+			tst_res(TPASS, "NS_GET_USERNS fails with EPERM");
+		else
+			tst_res(TFAIL | TERRNO, "unexpected ioctl error");
+	} else {
+		SAFE_CLOSE(fd);
+		tst_res(TFAIL, "call to ioctl succeded");
+	}
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.min_kver = "4.9",
+	.setup = setup
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns06.c b/testcases/kernel/syscalls/ioctl/ioctl_ns06.c
new file mode 100644
index 000000000..ae377b095
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns06.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_PARENT request.
+ *
+ * After the call to unshare with the CLONE_NEWPID flag,
+ * next new child is created in a new pid namespace. That's checked by
+ * comparing its /proc/self/ns/pid symlink and the parent's one.
+ * Also child thinks its pid is 1.
+ *
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <sched.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+static void setup(void)
+{
+	int exists = access("/proc/self/ns/pid", F_OK);
+
+	if (exists < 0)
+		tst_res(TCONF, "namespace not available");
+}
+
+static void run(void)
+{
+	SAFE_UNSHARE(CLONE_NEWPID);
+
+	pid_t pid = SAFE_FORK();
+
+	if (pid == 0) {
+		if (getpid() != 1)
+			tst_res(TFAIL, "child should think its pid is 1");
+		else
+			tst_res(TPASS, "child thinks its pid is 1");
+		TST_CHECKPOINT_WAIT(0);
+	} else {
+		char child_namespace[20];
+		int my_fd, child_fd, parent_fd;
+
+		sprintf(child_namespace, "/proc/%i/ns/pid", pid);
+		my_fd = SAFE_OPEN("/proc/self/ns/pid", O_RDONLY);
+		child_fd = SAFE_OPEN(child_namespace, O_RDONLY);
+		parent_fd = SAFE_IOCTL(child_fd, NS_GET_PARENT);
+
+		struct stat my_stat, child_stat, parent_stat;
+
+		SAFE_FSTAT(my_fd, &my_stat);
+		SAFE_FSTAT(child_fd, &child_stat);
+		SAFE_FSTAT(parent_fd, &parent_stat);
+		if (my_stat.st_ino != parent_stat.st_ino)
+			tst_res(TFAIL, "parents have different inodes");
+		else if (parent_stat.st_ino == child_stat.st_ino)
+			tst_res(TFAIL, "child and parent have same inode");
+		else
+			tst_res(TPASS, "child and parent are consistent");
+		SAFE_CLOSE(my_fd);
+		SAFE_CLOSE(child_fd);
+		SAFE_CLOSE(parent_fd);
+		TST_CHECKPOINT_WAKE(0);
+	}
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.forks_child = 1,
+	.needs_root = 1,
+	.needs_checkpoints = 1,
+	.min_kver = "4.9",
+	.setup = setup
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns07.c b/testcases/kernel/syscalls/ioctl/ioctl_ns07.c
new file mode 100644
index 000000000..f077a3bb7
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns07.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_USERNS request.
+ *
+ * After the call to clone with the CLONE_NEWUSER flag,
+ * child is created in a new user namespace. That's checked by
+ * comparing its /proc/self/ns/user symlink and the parent's one,
+ * which should be different.
+ *
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <sched.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+#define STACK_SIZE (1024 * 1024)
+
+static char child_stack[STACK_SIZE];
+
+static void setup(void)
+{
+	int exists = access("/proc/self/ns/user", F_OK);
+
+	if (exists < 0)
+		tst_res(TCONF, "namespace not available");
+}
+
+static int child(void *arg)
+{
+	TST_CHECKPOINT_WAIT(0);
+	return 0;
+}
+
+static void run(void)
+{
+	pid_t pid = ltp_clone(CLONE_NEWUSER, &child, 0,
+		STACK_SIZE, child_stack);
+	char child_namespace[20];
+
+	sprintf(child_namespace, "/proc/%i/ns/user", pid);
+	int my_fd, child_fd, parent_fd;
+
+	my_fd = SAFE_OPEN("/proc/self/ns/user", O_RDONLY);
+	child_fd = SAFE_OPEN(child_namespace, O_RDONLY);
+	parent_fd = SAFE_IOCTL(child_fd, NS_GET_USERNS);
+
+	struct stat my_stat, child_stat, parent_stat;
+
+	SAFE_FSTAT(my_fd, &my_stat);
+	SAFE_FSTAT(child_fd, &child_stat);
+	SAFE_FSTAT(parent_fd, &parent_stat);
+	if (my_stat.st_ino != parent_stat.st_ino)
+		tst_res(TFAIL, "parents have different inodes");
+	else if (parent_stat.st_ino == child_stat.st_ino)
+		tst_res(TFAIL, "child and parent have same inode");
+	else
+		tst_res(TPASS, "child and parent are consistent");
+	SAFE_CLOSE(my_fd);
+	SAFE_CLOSE(parent_fd);
+	SAFE_CLOSE(child_fd);
+	TST_CHECKPOINT_WAKE(0);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.forks_child = 1,
+	.needs_root = 1,
+	.needs_checkpoints = 1,
+	.min_kver = "4.9",
+	.setup = setup
+};
diff --git a/testcases/kernel/syscalls/ioctl/ioctl_ns08.c b/testcases/kernel/syscalls/ioctl/ioctl_ns08.c
new file mode 100644
index 000000000..06cf70a17
--- /dev/null
+++ b/testcases/kernel/syscalls/ioctl/ioctl_ns08.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com
+ */
+
+/*
+ * Test ioctl_ns with NS_GET_* request for file descriptors
+ * that aren't namespaces.
+ *
+ * Calling ioctl with test directory's file descriptor
+ * should make the call fail with ENOTTY.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include "tst_test.h"
+#include "lapi/ioctl_ns.h"
+
+static int requests[] = {NS_GET_PARENT, NS_GET_USERNS,
+	NS_GET_OWNER_UID, NS_GET_NSTYPE};
+
+static void test_request(unsigned int n)
+{
+	int request = requests[n];
+	int fd, ns_fd;
+
+	fd = SAFE_OPEN(".", O_RDONLY);
+	ns_fd = ioctl(fd, request);
+	if (ns_fd == -1) {
+		if (errno == ENOTTY)
+			tst_res(TPASS, "request failed with ENOTTY");
+		else
+			tst_res(TFAIL | TERRNO, "unexpected ioctl error");
+	} else {
+		tst_res(TFAIL, "request success for invalid fd");
+		SAFE_CLOSE(ns_fd);
+	}
+	SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+	.tcnt = ARRAY_SIZE(requests),
+	.test = test_request,
+	.needs_tmpdir = 1,
+	.min_kver = "4.11"
+};
-- 
2.11.0


  parent reply	other threads:[~2019-03-28 20:22 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-24 20:29 [LTP] [PATCH v1] Test ioctl syscall for NS_GET_* requests YourName
2019-03-04 16:16 ` Cyril Hrubis
2019-03-11  7:25   ` [LTP] [PATCH v2] " Federico Bonfiglio
2019-03-18 14:22     ` Cyril Hrubis
2019-03-18 15:30     ` Cyril Hrubis
2019-03-19 18:09       ` [LTP] [PATCH v3] " Federico Bonfiglio
2019-03-26 19:20         ` Cyril Hrubis
2019-03-28 20:22           ` [LTP] [PATCH v4 1/2] include/SAFE_UNSHARE() macro added Federico Bonfiglio
2019-04-03 15:19             ` Cyril Hrubis
2019-03-28 20:22           ` Federico Bonfiglio [this message]
2019-04-03 15:22             ` [LTP] [PATCH v4 2/2] Test ioctl syscall for NS_GET_* requests Cyril Hrubis
2019-04-11 19:25               ` [LTP] [PATCH v5] " Federico Bonfiglio
2019-04-12 14:33                 ` Cyril Hrubis
2019-05-06 10:14                   ` [LTP] NS_* ioctl commands fail in 32bit compat mode (-m32) Richard Palethorpe
2019-05-06 10:39                     ` Richard Palethorpe
2019-05-13  9:00                       ` Cyril Hrubis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190328202252.7927-1-fedebonfi95@gmail.com \
    --to=fedebonfi95@gmail.com \
    --cc=ltp@lists.linux.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.