[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