From patchwork Mon Jul 26 15:46:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Palethorpe X-Patchwork-Id: 1510121 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=suse.com header.i=@suse.com header.a=rsa-sha256 header.s=susede1 header.b=e83mTbAP; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GYPRH3CBHz9t8j for ; Tue, 27 Jul 2021 01:46:19 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id D0F163C9228 for ; Mon, 26 Jul 2021 17:46:16 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-5.smtp.seeweb.it (in-5.smtp.seeweb.it [IPv6:2001:4b78:1:20::5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by picard.linux.it (Postfix) with ESMTPS id 137213C6615 for ; Mon, 26 Jul 2021 17:46:13 +0200 (CEST) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by in-5.smtp.seeweb.it (Postfix) with ESMTPS id 5763A600875 for ; Mon, 26 Jul 2021 17:46:12 +0200 (CEST) Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id 8896F1FEB5; Mon, 26 Jul 2021 15:46:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1627314372; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=HV4hGjPNfbLxIeXtlYb0n75kWOE8rXdLjU5fmVnn2KA=; b=e83mTbAPsmgnqIhhrNGfZx1c8ricY18F7pjhi5pRcu0E4VnJ1EK4F2BNnRjVvC6snhgCxu +Wg772z2AuONXa756BKtoIEZp9dZxvn10FO8omJXBN4PdAy1IVzhuB6h/iqtlKhmDNJ17w fawgZJEKnUFkkty0mPFBy+B5R7QzOJg= Received: from g78.suse.de (unknown [10.163.24.38]) by relay2.suse.de (Postfix) with ESMTP id 59791A3B8C; Mon, 26 Jul 2021 15:46:12 +0000 (UTC) To: ltp@lists.linux.it Date: Mon, 26 Jul 2021 16:46:05 +0100 Message-Id: <20210726154605.7828-1-rpalethorpe@suse.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.102.4 at in-5.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on in-5.smtp.seeweb.it Subject: [LTP] [PATCH] Add set_mempolicy05, CVE-2017-7616 X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Richard Palethorpe via ltp From: Richard Palethorpe Reply-To: Richard Palethorpe Cc: Richard Palethorpe Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Signed-off-by: Richard Palethorpe --- 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 + */ +/*\ + * + * [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 + +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__) */