[LTP] [PATCH] Add test for CVE 2018-18559

Martin Doucha mdoucha@suse.cz
Tue Mar 31 14:48:49 CEST 2020


Fixes #411

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---

This is a rather slow test. The bind() thread can take on average 15ms due to
kernel locks on the socket or netdevice and the kernel crash is only triggered
on process exit. So the test takes about 2 to 3 minutes even with really low
number of race loops. But it reliably crashes SLE-12SP3 GM kernel.

 runtest/cve                               |   1 +
 runtest/syscalls                          |   1 +
 testcases/kernel/syscalls/bind/.gitignore |   1 +
 testcases/kernel/syscalls/bind/Makefile   |   1 +
 testcases/kernel/syscalls/bind/bind06.c   | 128 ++++++++++++++++++++++
 5 files changed, 132 insertions(+)
 create mode 100644 testcases/kernel/syscalls/bind/bind06.c

diff --git a/runtest/cve b/runtest/cve
index a9a534300..932d97451 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -42,4 +42,5 @@ cve-2017-1000380 snd_timer01
 cve-2018-5803 sctp_big_chunk
 cve-2018-1000001 realpath01
 cve-2018-1000204 ioctl_sg01
+cve-2018-18559 bind06
 cve-2018-19854 crypto_user01
diff --git a/runtest/syscalls b/runtest/syscalls
index 83d16d20e..f2073af96 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -34,6 +34,7 @@ bind02 bind02
 bind03 bind03
 bind04 bind04
 bind05 bind05
+bind06 bind06
 
 bpf_map01 bpf_map01
 bpf_prog01 bpf_prog01
diff --git a/testcases/kernel/syscalls/bind/.gitignore b/testcases/kernel/syscalls/bind/.gitignore
index e18ceea56..c85774441 100644
--- a/testcases/kernel/syscalls/bind/.gitignore
+++ b/testcases/kernel/syscalls/bind/.gitignore
@@ -3,3 +3,4 @@
 /bind03
 /bind04
 /bind05
+/bind06
diff --git a/testcases/kernel/syscalls/bind/Makefile b/testcases/kernel/syscalls/bind/Makefile
index fffa146ad..3de725143 100644
--- a/testcases/kernel/syscalls/bind/Makefile
+++ b/testcases/kernel/syscalls/bind/Makefile
@@ -6,5 +6,6 @@ top_srcdir		?= ../../../..
 include $(top_srcdir)/include/mk/testcases.mk
 
 bind04 bind05:	CFLAGS		+= -pthread
+bind06:		LDFLAGS		+= -pthread -lrt
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/bind/bind06.c b/testcases/kernel/syscalls/bind/bind06.c
new file mode 100644
index 000000000..23f65fef6
--- /dev/null
+++ b/testcases/kernel/syscalls/bind/bind06.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 SUSE LLC <mdoucha@suse.cz>
+ *
+ * CVE-2018-18559
+ *
+ * Test for race condition vulnerability in bind() on AF_PACKET socket.
+ * Fixed in:
+ *
+ *  commit 15fe076edea787807a7cdc168df832544b58eba6
+ *  Author: Eric Dumazet <edumazet@google.com>
+ *  Date:   Tue Nov 28 08:03:30 2017 -0800
+ *
+ *  net/packet: fix a race in packet_bind() and packet_notifier()
+ */
+
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <linux/if_packet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <sched.h>
+#include "tst_test.h"
+#include "tst_fuzzy_sync.h"
+#include "tst_taint.h"
+
+static volatile int fd = -1;
+static struct sockaddr_ll addr1, addr2;
+static struct tst_fzsync_pair fzsync_pair;
+
+static void setup(void)
+{
+	int real_uid = getuid();
+	int real_gid = getgid();
+	struct ifreq ifr;
+
+	tst_taint_init(TST_TAINT_W | TST_TAINT_D);
+
+	SAFE_UNSHARE(CLONE_NEWUSER);
+	SAFE_UNSHARE(CLONE_NEWNET);
+	SAFE_FILE_PRINTF("/proc/self/setgroups", "deny");
+	SAFE_FILE_PRINTF("/proc/self/uid_map", "0 %d 1\n", real_uid);
+	SAFE_FILE_PRINTF("/proc/self/gid_map", "0 %d 1\n", real_gid);
+
+	fd = SAFE_SOCKET(AF_PACKET, SOCK_DGRAM, PF_PACKET);
+	strcpy(ifr.ifr_name, "lo");
+	SAFE_IOCTL(fd, SIOCGIFINDEX, &ifr);
+	SAFE_CLOSE(fd);
+
+	addr1.sll_family = AF_PACKET;
+	addr1.sll_ifindex = ifr.ifr_ifindex;
+	addr2.sll_family = AF_PACKET;
+}
+
+static void do_bind(void) {
+	bind(fd, (struct sockaddr *)&addr1, sizeof(addr1));
+	bind(fd, (struct sockaddr *)&addr2, sizeof(addr2));
+}
+
+static void *thread_run(void *arg)
+{
+	while (tst_fzsync_run_b(&fzsync_pair)) {
+		tst_fzsync_start_race_b(&fzsync_pair);
+		do_bind();
+		tst_fzsync_end_race_b(&fzsync_pair);
+	}
+
+	return arg;
+}
+
+static void child_run(void)
+{
+	struct ifreq ifr;
+
+	fzsync_pair.exec_loops = 10000;
+	tst_fzsync_pair_init(&fzsync_pair);
+	tst_fzsync_pair_reset(&fzsync_pair, thread_run);
+	strcpy(ifr.ifr_name, "lo");
+
+	while (tst_fzsync_run_a(&fzsync_pair)) {
+		fd = SAFE_SOCKET(AF_PACKET, SOCK_DGRAM, PF_PACKET);
+		ifr.ifr_flags = 0;
+		ioctl(fd, SIOCSIFFLAGS, &ifr);
+		ifr.ifr_flags = IFF_UP;
+		tst_fzsync_start_race_a(&fzsync_pair);
+		ioctl(fd, SIOCSIFFLAGS, &ifr);
+		tst_fzsync_end_race_a(&fzsync_pair);
+		SAFE_CLOSE(fd);
+
+	}
+
+	tst_fzsync_pair_cleanup(&fzsync_pair);
+}
+
+static void run(void)
+{
+	pid_t child;
+
+	/* The kernel crash is triggered on process exit. */
+	child = SAFE_FORK();
+
+	if (!child) {
+		child_run();
+		exit(0);
+	}
+
+	SAFE_WAITPID(child, NULL, 0);
+
+	if (tst_taint_check()) {
+		tst_res(TFAIL, "Kernel is vulnerable");
+		return;
+	}
+
+	tst_res(TPASS, "Nothing bad happened, probably");
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.timeout = 600,
+	.forks_child = 1,
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "15fe076edea7"},
+		{"CVE", "2018-18559"},
+		{}
+	}
+};
-- 
2.25.1



More information about the ltp mailing list