[LTP] [PATCH v1] syscalls/accept02: add CVE-2017-8890 test case

Christian Amann camann@suse.com
Mon Jun 3 08:27:01 CEST 2019


In Kernels prior to 4.10.15 missing commit 657831ff the multicast group
of a socket was copied over to a new socket created using the accept()
syscall. This leads to a double free when closing both those sockets.

This can only be checked once a new socket was created which has to be
closed eventually. That means that this test case can cause an unstable
system if it does not succeed.

Signed-off-by: Christian Amann <camann@suse.com>
---
 runtest/syscalls                            |   2 +
 testcases/kernel/syscalls/accept/.gitignore |   1 +
 testcases/kernel/syscalls/accept/Makefile   |   2 +
 testcases/kernel/syscalls/accept/accept02.c | 143 ++++++++++++++++++++++++++++
 4 files changed, 148 insertions(+)
 create mode 100644 testcases/kernel/syscalls/accept/accept02.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 762b15b1f..79ef294fe 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -2,6 +2,8 @@
 abort01 abort01
 
 accept01 accept01
+accept02 accept02
+
 accept4_01 accept4_01
 
 access01 access01
diff --git a/testcases/kernel/syscalls/accept/.gitignore b/testcases/kernel/syscalls/accept/.gitignore
index 1f6f8ada0..5b1462699 100644
--- a/testcases/kernel/syscalls/accept/.gitignore
+++ b/testcases/kernel/syscalls/accept/.gitignore
@@ -1 +1,2 @@
 /accept01
+/accept02
diff --git a/testcases/kernel/syscalls/accept/Makefile b/testcases/kernel/syscalls/accept/Makefile
index bd617d806..0910871c7 100644
--- a/testcases/kernel/syscalls/accept/Makefile
+++ b/testcases/kernel/syscalls/accept/Makefile
@@ -21,3 +21,5 @@ top_srcdir		?= ../../../..
 include $(top_srcdir)/include/mk/testcases.mk
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+accept02: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/accept/accept02.c b/testcases/kernel/syscalls/accept/accept02.c
new file mode 100644
index 000000000..662ae4346
--- /dev/null
+++ b/testcases/kernel/syscalls/accept/accept02.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 SUSE LLC
+ * Author: Christian Amann <camann@suse.com>
+ */
+/* Test for CVE-2017-8890
+ *
+ * In Kernels up to 4.10.15 missing commit 657831ff the multicast
+ * group information of a socket gets copied over to a newly created
+ * socket when using the accept() syscall. This will cause a double free
+ * when closing the original and the cloned socket.
+ *
+ * WARNING:
+ * There is a high chance that this test will cause an unstable system
+ * if it does not succeed!
+ *
+ * For more information about this CVE see:
+ * https://www.suse.com/security/cve/CVE-2017-8890/
+ */
+
+#include <errno.h>
+#include <sys/socket.h>
+#include "tst_test.h"
+#include "tst_safe_net.h"
+#include "tst_safe_pthread.h"
+
+#define MULTICASTIP "224.0.0.0"
+#define LOCALHOSTIP "127.0.0.1"
+
+static int server_sockfd;
+static int clone_server_sockfd;
+static int client_sockfd;
+static int server_port;
+static socklen_t addr_len;
+
+static struct sockaddr_in server_addr;
+static struct sockaddr_in client_addr;
+static struct group_req mc_group;
+
+
+static void *server_thread(void *arg)
+{
+	int op, op_len, mc_group_len;
+
+	op = 1;
+	op_len = sizeof(op);
+	mc_group_len = sizeof(mc_group);
+
+	server_sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+
+	SAFE_SETSOCKOPT(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &op, op_len);
+	SAFE_SETSOCKOPT(server_sockfd, SOL_IP, MCAST_JOIN_GROUP,
+			&mc_group, mc_group_len);
+
+	SAFE_BIND(server_sockfd, (struct sockaddr *)&server_addr, addr_len);
+	SAFE_LISTEN(server_sockfd, 1);
+
+	TST_CHECKPOINT_WAKE(0);
+
+	TEST(accept(server_sockfd, (struct sockaddr *)&client_addr, &addr_len));
+	if (TST_RET == -1)
+		tst_brk(TBROK | TTERRNO, "Could not accept connection");
+
+	clone_server_sockfd = TST_RET;
+
+	TEST(setsockopt(clone_server_sockfd, SOL_IP, MCAST_LEAVE_GROUP,
+			&mc_group, mc_group_len));
+
+	if (TST_RET != -1)
+		tst_res(TFAIL, "Multicast group was copied!");
+	else if (TST_ERR == EADDRNOTAVAIL)
+		tst_res(TPASS | TTERRNO, "Multicast group was not copied");
+	else
+		tst_brk(TBROK | TTERRNO, "setsockopt() failed unexpectedly");
+
+	SAFE_CLOSE(server_sockfd);
+	return arg;
+}
+
+static void *client_thread(void *arg)
+{
+	client_sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
+	SAFE_BIND(client_sockfd, (struct sockaddr *)&client_addr, addr_len);
+
+	SAFE_CONNECT(client_sockfd, (struct sockaddr *)&server_addr, addr_len);
+
+	SAFE_CLOSE(client_sockfd);
+	return arg;
+}
+
+static void run(void)
+{
+	pthread_t server_thr, client_thr;
+
+	server_addr.sin_port = htons(server_port);
+	client_addr.sin_port = htons(0);
+
+	SAFE_PTHREAD_CREATE(&server_thr, NULL, server_thread, NULL);
+	TST_CHECKPOINT_WAIT(0);
+	SAFE_PTHREAD_CREATE(&client_thr, NULL, client_thread, NULL);
+
+	SAFE_PTHREAD_JOIN(server_thr, NULL);
+	SAFE_PTHREAD_JOIN(client_thr, NULL);
+}
+
+static void setup(void)
+{
+	struct sockaddr_in *mc_group_addr;
+
+	mc_group.gr_interface = 0;
+	mc_group_addr = (struct sockaddr_in *) &mc_group.gr_group;
+	mc_group_addr->sin_family = AF_INET;
+	inet_aton(MULTICASTIP, &mc_group_addr->sin_addr);
+
+	server_addr.sin_family = AF_INET;
+	inet_aton(LOCALHOSTIP, &server_addr.sin_addr);
+
+	client_addr.sin_family = AF_INET;
+	client_addr.sin_addr.s_addr = htons(INADDR_ANY);
+
+	addr_len = sizeof(struct sockaddr_in);
+
+	server_port = TST_GET_UNUSED_PORT(AF_INET, SOCK_STREAM);
+	tst_res(TINFO, "Starting listener on port: %d", server_port);
+}
+
+static void cleanup(void)
+{
+	if (clone_server_sockfd > 0)
+		SAFE_CLOSE(clone_server_sockfd);
+	if (client_sockfd > 0)
+		SAFE_CLOSE(client_sockfd);
+	if (server_sockfd > 0)
+		SAFE_CLOSE(server_sockfd);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_checkpoints = 1,
+	.needs_root = 1,
+};
-- 
2.16.4



More information about the ltp mailing list