[LTP] [PATCH] Add set_mempolicy05, CVE-2017-7616
Richard Palethorpe
rpalethorpe@suse.com
Mon Jul 26 17:46:05 CEST 2021
Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
Possibly this is useful for education, but not much else.
runtest/cve | 1 +
runtest/numa | 1 +
.../kernel/syscalls/set_mempolicy/.gitignore | 1 +
.../kernel/syscalls/set_mempolicy/Makefile | 3 +
.../syscalls/set_mempolicy/set_mempolicy05.c | 128 ++++++++++++++++++
5 files changed, 134 insertions(+)
create mode 100644 testcases/kernel/syscalls/set_mempolicy/set_mempolicy05.c
diff --git a/runtest/cve b/runtest/cve
index 226b5ea44..96cc98f20 100644
--- a/runtest/cve
+++ b/runtest/cve
@@ -22,6 +22,7 @@ cve-2017-2671 cve-2017-2671
cve-2017-6951 request_key05
cve-2017-7308 setsockopt02
cve-2017-7472 keyctl04
+cve-2017-7616 set_mempolicy05
cve-2017-10661 timerfd_settime02
cve-2017-12192 keyctl07
cve-2017-12193 add_key04
diff --git a/runtest/numa b/runtest/numa
index 7b9c2ae9d..3b9a9a7c5 100644
--- a/runtest/numa
+++ b/runtest/numa
@@ -20,3 +20,4 @@ set_mempolicy01 set_mempolicy01
set_mempolicy02 set_mempolicy02
set_mempolicy03 set_mempolicy03
set_mempolicy04 set_mempolicy04
+set_mempolicy05 set_mempolicy05
diff --git a/testcases/kernel/syscalls/set_mempolicy/.gitignore b/testcases/kernel/syscalls/set_mempolicy/.gitignore
index 52ae73b52..4c121d2e0 100644
--- a/testcases/kernel/syscalls/set_mempolicy/.gitignore
+++ b/testcases/kernel/syscalls/set_mempolicy/.gitignore
@@ -2,3 +2,4 @@
/set_mempolicy02
/set_mempolicy03
/set_mempolicy04
+/set_mempolicy05
diff --git a/testcases/kernel/syscalls/set_mempolicy/Makefile b/testcases/kernel/syscalls/set_mempolicy/Makefile
index e6e699808..1fbadf6e8 100644
--- a/testcases/kernel/syscalls/set_mempolicy/Makefile
+++ b/testcases/kernel/syscalls/set_mempolicy/Makefile
@@ -8,4 +8,7 @@ include $(top_srcdir)/include/mk/testcases.mk
LDLIBS += $(NUMA_LIBS)
LTPLDLIBS = -lltpnuma
+set_mempolicy05: LDLIBS=-lltp
+set_mempolicy05: LTPLDLIBS=
+
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/set_mempolicy/set_mempolicy05.c b/testcases/kernel/syscalls/set_mempolicy/set_mempolicy05.c
new file mode 100644
index 000000000..86f6a95dc
--- /dev/null
+++ b/testcases/kernel/syscalls/set_mempolicy/set_mempolicy05.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 SUSE LLC <rpalethorpe@suse.com>
+ */
+/*\
+ *
+ * [Description]
+ *
+ * This will reproduce an information leak in the set_mempolicy 32-bit
+ * compat syscall. The catch is that the 32-bit compat syscall is not
+ * used in x86_64 upstream. So at the time of writing, 32-bit programs
+ * on large x86_64 numa systems will be broken if they use
+ * set_mempolicy. OTOH they could not have been exploited either.
+ *
+ * On other architectures the compat syscall is connected. Including
+ * PowerPC which has also been included as well. It is possible some
+ * vendors connected the x86_64 compat call in their kernel branch.
+ *
+ * The kernel allocates memory from the user's stack as a temporary
+ * work area. Allowing it to copy the node array of 32-bit fields to
+ * 64-bit fields. It uses user memory so that it can share the
+ * non-compatability syscall functions which use copy_from_user()
+ * internally.
+ *
+ * Originally the compat call would copy a chunk of the
+ * uninitialized kernel stack to the user stack before checking the
+ * validation result. This meant when the user passed in an invalid
+ * node_mask_ptr. They would get kernel stack data somewhere below
+ * their stack pointer.
+ *
+ * So we allocate and set an array on the stack (larger than any
+ * redzone). Then move the stack pointer to the beginning of the
+ * array. Then move it back after the syscall. We can then check to
+ * see if the array has been modified.
+ */
+
+#include "config.h"
+#include "tst_test.h"
+
+#if defined(__i386__) || defined(__powerpc__)
+
+#include <string.h>
+
+static unsigned int i;
+static int sys_ret;
+#ifdef __i386__
+static const int sys_num = 276;
+static const int mode;
+static const int node_mask_ptr = UINT_MAX;
+static const int node_mask_sz = UINT_MAX;
+#endif
+static volatile char *stack_ptr;
+
+static void run(void)
+{
+#ifdef __powerpc__
+ register long sys_num __asm__("r0");
+ register long mode __asm__("r3");
+ register long node_mask_ptr __asm__("r4");
+ register long node_mask_sz __asm__("r5");
+#endif
+ char stack_pattern[0x400];
+
+ stack_ptr = stack_pattern;
+ memset(stack_pattern, 0xA5, sizeof(stack_pattern));
+ tst_res(TINFO, "stack pattern is in %p-%p", stack_ptr, stack_ptr + 0x400);
+
+#ifdef __powerpc__
+ sys_num = 261;
+ mode = 0;
+ node_mask_ptr = ~0UL;
+ node_mask_sz = ~0UL;
+ asm volatile (
+ "addi 1,1,1024\n\t"
+ "sc\n\t"
+ "addi 1,1,-1024\n\t" :
+ "+r"(sys_num), "+r"(mode), "+r"(node_mask_ptr), "+r"(node_mask_sz) :
+ :
+ "memory", "cr0", "r6", "r7", "r8", "r9", "r10", "r11", "r12");
+ sys_ret = mode;
+#else /* __i386__ */
+ asm volatile (
+ "add $0x400, %%esp\n\t"
+ "int $0x80\n\t"
+ "sub $0x400, %%esp\n\t" :
+ "=a"(sys_ret) :
+ "a"(sys_num), "b"(mode), "c"(node_mask_ptr), "d"(node_mask_sz) :
+ "memory");
+ sys_ret = -sys_ret;
+#endif
+
+ for (i = 0; i < sizeof(stack_pattern); i++) {
+ if (stack_ptr[i] != (char)0xA5) {
+ tst_brk(TFAIL,
+ "User stack was overwritten with something at %d", i);
+ }
+ }
+
+ switch (sys_ret) {
+ case EFAULT:
+ tst_res(TPASS,
+ "set_mempolicy returned EFAULT (compat assumed)");
+ break;
+ case EINVAL:
+ tst_res(TCONF,
+ "set_mempolicy returned EINVAL (non compat assumed)");
+ break;
+ default:
+ tst_res(TFAIL,
+ "set_mempolicy should fail with EFAULT or EINVAL, instead returned %ld",
+ (long)sys_ret);
+ }
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "cf01fb9985e8"},
+ {"CVE", "CVE-2017-7616"},
+ {}
+ }
+};
+
+#else /* #if defined(__x86_64__) || defined(__powerpc__) */
+
+TST_TEST_TCONF("not i386 or powerpc");
+
+#endif /* #else #if defined(__x86_64__) || defined(__powerpc__) */
--
2.31.1
More information about the ltp
mailing list