All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH 1/4] Prevent linker issues in lapi/io_uring.h
@ 2021-02-01 16:39 Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 2/4] Add safe functions for io_uring to LTP library Martin Doucha
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Martin Doucha @ 2021-02-01 16:39 UTC (permalink / raw)
  To: ltp

Fallback io_uring syscall wrappers were not defined as static inline. This
will lead to linker issues when safe function variants get added to LTP
library.

Also add check for <linux/io_uring.h> to configure script and #include it
in the LAPI header if it's available.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 configure.ac            |  1 +
 include/lapi/io_uring.h | 17 +++++++++++------
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 8bdb96300..9fb50c173 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,7 @@ AC_CHECK_HEADERS_ONCE([ \
     linux/if_alg.h \
     linux/if_ether.h \
     linux/if_packet.h \
+    linux/io_uring.h \
     linux/keyctl.h \
     linux/mempolicy.h \
     linux/module.h \
diff --git a/include/lapi/io_uring.h b/include/lapi/io_uring.h
index 174e81e4d..9d280f155 100644
--- a/include/lapi/io_uring.h
+++ b/include/lapi/io_uring.h
@@ -18,6 +18,10 @@
 
 #include "lapi/syscalls.h"
 
+#ifdef HAVE_LINUX_IO_URING_H
+#include <linux/io_uring.h>
+#endif
+
 #ifndef IOSQE_FIXED_FILE
 
 #ifndef __kernel_rwf_t
@@ -260,8 +264,8 @@ struct io_uring_probe {
 
 
 #ifndef HAVE_IO_URING_REGISTER
-int io_uring_register(int fd, unsigned int opcode, void *arg,
-		      unsigned int nr_args)
+static inline int io_uring_register(int fd, unsigned int opcode, void *arg,
+	unsigned int nr_args)
 {
 	return tst_syscall(__NR_io_uring_register, fd, opcode, arg, nr_args);
 }
@@ -269,22 +273,23 @@ int io_uring_register(int fd, unsigned int opcode, void *arg,
 
 
 #ifndef HAVE_IO_URING_SETUP
-int io_uring_setup(unsigned int entries, struct io_uring_params *p)
+static inline int io_uring_setup(unsigned int entries,
+	struct io_uring_params *p)
 {
 	return tst_syscall(__NR_io_uring_setup, entries, p);
 }
 #endif /* HAVE_IO_URING_SETUP */
 
 #ifndef HAVE_IO_URING_ENTER
-int io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete,
-		   unsigned int flags, sigset_t *sig)
+static inline int io_uring_enter(int fd, unsigned int to_submit,
+	unsigned int min_complete, unsigned int flags, sigset_t *sig)
 {
 	return tst_syscall(__NR_io_uring_enter, fd, to_submit, min_complete,
 			flags, sig, _NSIG / 8);
 }
 #endif /* HAVE_IO_URING_ENTER */
 
-void io_uring_setup_supported_by_kernel(void)
+static inline void io_uring_setup_supported_by_kernel(void)
 {
 	if ((tst_kvercmp(5, 1, 0)) < 0) {
 		TEST(syscall(__NR_io_uring_setup, NULL, 0));
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [LTP] [PATCH 2/4] Add safe functions for io_uring to LTP library
  2021-02-01 16:39 [LTP] [PATCH 1/4] Prevent linker issues in lapi/io_uring.h Martin Doucha
@ 2021-02-01 16:39 ` Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 3/4] Add CAP_SYS_CHROOT to lapi/capability.h Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 4/4] Add test for CVE 2020-29373 Martin Doucha
  2 siblings, 0 replies; 4+ messages in thread
From: Martin Doucha @ 2021-02-01 16:39 UTC (permalink / raw)
  To: ltp

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 include/tst_safe_io_uring.h |  63 +++++++++++++++++++++
 lib/tst_safe_io_uring.c     | 108 ++++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+)
 create mode 100644 include/tst_safe_io_uring.h
 create mode 100644 lib/tst_safe_io_uring.c

diff --git a/include/tst_safe_io_uring.h b/include/tst_safe_io_uring.h
new file mode 100644
index 000000000..fa416e35c
--- /dev/null
+++ b/include/tst_safe_io_uring.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) Linux Test Project, 2021
+ */
+
+#ifndef TST_IO_URING_H__
+#define TST_IO_URING_H__
+
+#include "config.h"
+#include "lapi/io_uring.h"
+
+struct tst_io_uring {
+	int fd;
+	void *sqr_base, *cqr_base;
+	/* buffer sizes in bytes for unmapping */
+	size_t sqr_mapsize, cqr_mapsize;
+
+	/* Number of entries in the ring buffers */
+	uint32_t sqr_size, cqr_size;
+
+	/* Submission queue pointers */
+	struct io_uring_sqe *sqr_entries;
+	const uint32_t *sqr_head, *sqr_mask, *sqr_flags, *sqr_dropped;
+	uint32_t *sqr_tail, *sqr_array;
+
+	/* Completion queue pointers */
+	const struct io_uring_cqe *cqr_entries;
+	const uint32_t *cqr_tail, *cqr_mask, *cqr_overflow;
+	uint32_t *cqr_head;
+
+};
+
+/*
+ * Call io_uring_setup() with given arguments and prepare memory mappings
+ * into the tst_io_uring structure passed in the third argument.
+ */
+#define SAFE_IO_URING_INIT(entries, params, uring) \
+	safe_io_uring_init(__FILE__, __LINE__, (entries), (params), (uring))
+int safe_io_uring_init(const char *file, const int lineno,
+	unsigned int entries, struct io_uring_params *params,
+	struct tst_io_uring *uring);
+
+/*
+ * Release io_uring mappings and close the file descriptor. uring->fd will
+ * be set to -1 after close.
+ */
+#define SAFE_IO_URING_CLOSE(uring) \
+	safe_io_uring_close(__FILE__, __LINE__, (uring))
+int safe_io_uring_close(const char *file, const int lineno,
+	struct tst_io_uring *uring);
+
+/*
+ * Call io_uring_enter() and check for errors. The "strict" argument controls
+ * pedantic check whether return value is equal to "to_submit" argument.
+ */
+#define SAFE_IO_URING_ENTER(strict, fd, to_submit, min_complete, flags, sig) \
+	safe_io_uring_enter(__FILE__, __LINE__, (strict), (fd), (to_submit), \
+		(min_complete), (flags), (sig))
+int safe_io_uring_enter(const char *file, const int lineno, int strict,
+	int fd, unsigned int to_submit, unsigned int min_complete,
+	unsigned int flags, sigset_t *sig);
+
+#endif /* TST_IO_URING_H__ */
diff --git a/lib/tst_safe_io_uring.c b/lib/tst_safe_io_uring.c
new file mode 100644
index 000000000..f300fd38c
--- /dev/null
+++ b/lib/tst_safe_io_uring.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 SUSE LLC <mdoucha@suse.cz>
+ */
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_safe_io_uring.h"
+
+int safe_io_uring_init(const char *file, const int lineno,
+	unsigned int entries, struct io_uring_params *params,
+	struct tst_io_uring *uring)
+{
+	errno = 0;
+	uring->fd = io_uring_setup(entries, params);
+
+	if (uring->fd == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"io_uring_setup() failed");
+		return uring->fd;
+	} else if (uring->fd < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"io_uring_setup() returned invalid value %d",
+			uring->fd);
+		return uring->fd;
+	}
+
+	uring->sqr_size = params->sq_entries;
+	uring->cqr_size = params->cq_entries;
+	uring->sqr_mapsize = params->sq_off.array +
+		params->sq_entries * sizeof(__u32);
+	uring->cqr_mapsize = params->cq_off.cqes +
+		params->cq_entries * sizeof(struct io_uring_cqe);
+
+	uring->sqr_base = safe_mmap(file, lineno, NULL, uring->sqr_mapsize,
+		PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, uring->fd,
+		IORING_OFF_SQ_RING);
+
+	if (uring->sqr_base == MAP_FAILED)
+		return -1;
+
+	uring->sqr_entries = safe_mmap(file, lineno, NULL,
+		params->sq_entries * sizeof(struct io_uring_sqe),
+		PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, uring->fd,
+		IORING_OFF_SQES);
+
+	if (uring->sqr_entries == MAP_FAILED)
+		return -1;
+
+	uring->cqr_base = safe_mmap(file, lineno, NULL, uring->cqr_mapsize,
+		PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, uring->fd,
+		IORING_OFF_CQ_RING);
+
+	if (uring->cqr_base == MAP_FAILED)
+		return -1;
+
+	uring->sqr_head = uring->sqr_base + params->sq_off.head;
+	uring->sqr_tail = uring->sqr_base + params->sq_off.tail;
+	uring->sqr_mask = uring->sqr_base + params->sq_off.ring_mask;
+	uring->sqr_flags = uring->sqr_base + params->sq_off.flags;
+	uring->sqr_dropped = uring->sqr_base + params->sq_off.dropped;
+	uring->sqr_array = uring->sqr_base + params->sq_off.array;
+
+	uring->cqr_head = uring->cqr_base + params->cq_off.head;
+	uring->cqr_tail = uring->cqr_base + params->cq_off.tail;
+	uring->cqr_mask = uring->cqr_base + params->cq_off.ring_mask;
+	uring->cqr_overflow = uring->cqr_base + params->cq_off.overflow;
+	uring->cqr_entries = uring->cqr_base + params->cq_off.cqes;
+	return uring->fd;
+}
+
+int safe_io_uring_close(const char *file, const int lineno,
+	struct tst_io_uring *uring)
+{
+	int ret;
+
+	safe_munmap(file, lineno, NULL, uring->cqr_base, uring->cqr_mapsize);
+	safe_munmap(file, lineno, NULL, uring->sqr_entries,
+		uring->sqr_size * sizeof(struct io_uring_sqe));
+	safe_munmap(file, lineno, NULL, uring->sqr_base, uring->sqr_mapsize);
+	ret = safe_close(file, lineno, NULL, uring->fd);
+	uring->fd = -1;
+	return ret;
+}
+
+int safe_io_uring_enter(const char *file, const int lineno, int strict,
+	int fd, unsigned int to_submit, unsigned int min_complete,
+	unsigned int flags, sigset_t *sig)
+{
+	int ret;
+
+	errno = 0;
+	ret = io_uring_enter(fd, to_submit, min_complete, flags, sig);
+
+	if (ret == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"io_uring_enter() failed");
+	} else if (ret < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid io_uring_enter() return value %d", ret);
+	} else if (strict && to_submit != (unsigned int)ret) {
+		tst_brk_(file, lineno, TBROK,
+			"io_uring_enter() submitted %d items (expected %d)",
+			ret, to_submit);
+	}
+
+	return ret;
+}
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [LTP] [PATCH 3/4] Add CAP_SYS_CHROOT to lapi/capability.h
  2021-02-01 16:39 [LTP] [PATCH 1/4] Prevent linker issues in lapi/io_uring.h Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 2/4] Add safe functions for io_uring to LTP library Martin Doucha
@ 2021-02-01 16:39 ` Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 4/4] Add test for CVE 2020-29373 Martin Doucha
  2 siblings, 0 replies; 4+ messages in thread
From: Martin Doucha @ 2021-02-01 16:39 UTC (permalink / raw)
  To: ltp

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 include/lapi/capability.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/lapi/capability.h b/include/lapi/capability.h
index fde27efd3..95cb6819b 100644
--- a/include/lapi/capability.h
+++ b/include/lapi/capability.h
@@ -24,6 +24,10 @@
 # define CAP_NET_RAW          13
 #endif
 
+#ifndef CAP_SYS_CHROOT
+# define CAP_SYS_CHROOT       18
+#endif
+
 #ifndef CAP_SYS_ADMIN
 # define CAP_SYS_ADMIN        21
 #endif
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [LTP] [PATCH 4/4] Add test for CVE 2020-29373
  2021-02-01 16:39 [LTP] [PATCH 1/4] Prevent linker issues in lapi/io_uring.h Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 2/4] Add safe functions for io_uring to LTP library Martin Doucha
  2021-02-01 16:39 ` [LTP] [PATCH 3/4] Add CAP_SYS_CHROOT to lapi/capability.h Martin Doucha
@ 2021-02-01 16:39 ` Martin Doucha
  2 siblings, 0 replies; 4+ messages in thread
From: Martin Doucha @ 2021-02-01 16:39 UTC (permalink / raw)
  To: ltp

Fixes #770

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 runtest/cve                                   |   1 +
 runtest/syscalls                              |   1 +
 .../kernel/syscalls/io_uring/io_uring02.c     | 197 ++++++++++++++++++
 3 files changed, 199 insertions(+)
 create mode 100644 testcases/kernel/syscalls/io_uring/io_uring02.c

diff --git a/runtest/cve b/runtest/cve
index 0bb1983bc..f650854f9 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -60,3 +60,4 @@ cve-2019-8912 af_alg07
 cve-2020-11494 pty04
 cve-2020-14386 sendto03
 cve-2020-14416 pty03
+cve-2020-29373 io_uring02
diff --git a/runtest/syscalls b/runtest/syscalls
index 11a1e83c2..dbb33a2cd 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1712,3 +1712,4 @@ statx07 statx07
 membarrier01 membarrier01
 
 io_uring01 io_uring01
+io_uring02 io_uring02
diff --git a/testcases/kernel/syscalls/io_uring/io_uring02.c b/testcases/kernel/syscalls/io_uring/io_uring02.c
new file mode 100644
index 000000000..b045cc34e
--- /dev/null
+++ b/testcases/kernel/syscalls/io_uring/io_uring02.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 SUSE LLC
+ * Author: Nicolai Stange <nstange@suse.de>
+ * LTP port: Martin Doucha <mdoucha@suse.cz>
+ *
+ * CVE-2020-29373
+ *
+ * Check that io_uring does not bypass chroot. Fixed in:
+ *
+ *  commit ff002b30181d30cdfbca316dadd099c3ca0d739c
+ *  Author: Jens Axboe <axboe@kernel.dk>
+ *  Date:   Fri Feb 7 16:05:21 2020 -0700
+ *
+ *  io_uring: grab ->fs as part of async preparation
+ */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "tst_test.h"
+#include "tst_safe_io_uring.h"
+
+#define CHROOT_DIR "test_root"
+#define SOCK_NAME "sock"
+#define SPAM_MARK 0xfa7
+#define BEEF_MARK 0xbeef
+
+static struct sockaddr_un addr;
+static int sendsock = -1, recvsock = -1, sockpair[2] = {-1, -1};
+static struct io_uring_params params;
+static struct tst_io_uring uring = { .fd = -1 };
+static char buf[16];
+static struct iovec iov = {
+	.iov_base = buf,
+	.iov_len = sizeof(buf)
+};
+
+static struct msghdr spam_header = {
+	.msg_name = NULL,
+	.msg_namelen = 0,
+	.msg_iov = &iov,
+	.msg_iovlen = 1
+};
+
+static struct msghdr beef_header = {
+	.msg_name = &addr,
+	.msg_namelen = sizeof(addr),
+	.msg_iov = &iov,
+	.msg_iovlen = 1
+};
+
+static void setup(void)
+{
+	char *tmpdir = tst_get_tmpdir();
+	int ret;
+
+	addr.sun_family = AF_UNIX;
+	ret = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", tmpdir,
+		SOCK_NAME);
+	free(tmpdir);
+
+	if (ret >= (int)sizeof(addr.sun_path))
+		tst_brk(TBROK, "Tempdir path is too long");
+
+	io_uring_setup_supported_by_kernel();
+
+	sendsock = SAFE_SOCKET(AF_UNIX, SOCK_DGRAM, 0);
+	recvsock = SAFE_SOCKET(AF_UNIX, SOCK_DGRAM, 0);
+	SAFE_BIND(recvsock, (struct sockaddr *)&addr, sizeof(addr));
+
+	SAFE_MKDIR(CHROOT_DIR, 0755);
+	SAFE_CHROOT(CHROOT_DIR);
+}
+
+static void run(void)
+{
+	uint32_t i, count, tail;
+	int beef_found = 0;
+	struct io_uring_sqe *sqe_ptr;
+	const struct io_uring_cqe *cqe_ptr;
+
+	SAFE_SOCKETPAIR(AF_UNIX, SOCK_DGRAM, 0, sockpair);
+	SAFE_SETSOCKOPT_INT(sockpair[0], SOL_SOCKET, SO_SNDBUF,
+		32+sizeof(buf));
+	SAFE_FCNTL(sockpair[0], F_SETFL, O_NONBLOCK);
+
+	SAFE_IO_URING_INIT(512, &params, &uring);
+	sqe_ptr = uring.sqr_entries;
+
+	/* Add spam requests to force async processing of the real test */
+	for (i = 0, tail = *uring.sqr_tail; i < 255; i++, tail++, sqe_ptr++) {
+		memset(sqe_ptr, 0, sizeof(*sqe_ptr));
+		sqe_ptr->opcode = IORING_OP_SENDMSG;
+		sqe_ptr->flags = IOSQE_IO_DRAIN;
+		sqe_ptr->fd = sockpair[0];
+		sqe_ptr->addr = (__u64)&spam_header;
+		sqe_ptr->user_data = SPAM_MARK;
+		uring.sqr_array[tail & *uring.sqr_mask] = i;
+	}
+
+	/* Add the real test to queue */
+	memset(sqe_ptr, 0, sizeof(*sqe_ptr));
+	sqe_ptr->opcode = IORING_OP_SENDMSG;
+	sqe_ptr->flags = IOSQE_IO_DRAIN;
+	sqe_ptr->fd = sendsock;
+	sqe_ptr->addr = (__u64)&beef_header;
+	sqe_ptr->user_data = BEEF_MARK;
+	uring.sqr_array[tail & *uring.sqr_mask] = i;
+	count = ++i;
+	tail++;
+
+	__atomic_store(uring.sqr_tail, &tail, __ATOMIC_RELEASE);
+	SAFE_IO_URING_ENTER(1, uring.fd, count, count, IORING_ENTER_GETEVENTS,
+		NULL);
+
+	/* Check test results */
+	__atomic_load(uring.cqr_tail, &tail, __ATOMIC_ACQUIRE);
+
+	for (i = *uring.cqr_head; i != tail; i++, count--) {
+		cqe_ptr = uring.cqr_entries + (i & *uring.cqr_mask);
+		TST_ERR = -cqe_ptr->res;
+
+		if (cqe_ptr->user_data == SPAM_MARK) {
+			if (cqe_ptr->res >= 0 || cqe_ptr->res == -EAGAIN)
+				continue;
+
+			tst_res(TFAIL | TTERRNO,
+				"Spam request failed unexpectedly");
+			continue;
+		}
+
+		if (cqe_ptr->user_data != BEEF_MARK) {
+			tst_res(TFAIL, "Unexpected entry in completion queue");
+			count++;
+			continue;
+		}
+
+		beef_found = 1;
+
+		if (cqe_ptr->res >= 0) {
+			tst_res(TFAIL, "Write outside chroot succeeded.");
+		} else if (cqe_ptr->res != -ENOENT) {
+			tst_res(TFAIL | TTERRNO,
+				"Write outside chroot failed unexpectedly");
+		} else {
+			tst_res(TPASS,
+				"Write outside chroot failed as expected");
+		}
+	}
+
+	__atomic_store(uring.cqr_head, &i, __ATOMIC_RELEASE);
+
+	if (!beef_found)
+		tst_res(TFAIL, "Write outside chroot result not found");
+
+	if (count)
+		tst_res(TFAIL, "Wrong number of entries in completion queue");
+
+	/* iteration cleanup */
+	SAFE_IO_URING_CLOSE(&uring);
+	SAFE_CLOSE(sockpair[0]);
+	SAFE_CLOSE(sockpair[1]);
+}
+
+static void cleanup(void)
+{
+	if (uring.fd >= 0)
+		SAFE_IO_URING_CLOSE(&uring);
+
+	if (sockpair[0] >= 0) {
+		SAFE_CLOSE(sockpair[0]);
+		SAFE_CLOSE(sockpair[1]);
+	}
+
+	if (recvsock >= 0)
+		SAFE_CLOSE(recvsock);
+
+	if (sendsock >= 0)
+		SAFE_CLOSE(sendsock);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.caps = (struct tst_cap []) {
+		TST_CAP(TST_CAP_REQ, CAP_SYS_CHROOT),
+		{}
+	},
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "ff002b30181d"},
+		{"CVE", "2020-29373"},
+		{}
+	}
+};
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-02-01 16:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-01 16:39 [LTP] [PATCH 1/4] Prevent linker issues in lapi/io_uring.h Martin Doucha
2021-02-01 16:39 ` [LTP] [PATCH 2/4] Add safe functions for io_uring to LTP library Martin Doucha
2021-02-01 16:39 ` [LTP] [PATCH 3/4] Add CAP_SYS_CHROOT to lapi/capability.h Martin Doucha
2021-02-01 16:39 ` [LTP] [PATCH 4/4] Add test for CVE 2020-29373 Martin Doucha

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.