From patchwork Tue Dec 4 12:18:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10711689 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 259AA14BD for ; Tue, 4 Dec 2018 12:19:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 17FDF2A37D for ; Tue, 4 Dec 2018 12:19:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0BDF22A391; Tue, 4 Dec 2018 12:19:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 993052A37D for ; Tue, 4 Dec 2018 12:19:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726280AbeLDMSq (ORCPT ); Tue, 4 Dec 2018 07:18:46 -0500 Received: from mail-lj1-f195.google.com ([209.85.208.195]:42147 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725802AbeLDMSp (ORCPT ); Tue, 4 Dec 2018 07:18:45 -0500 Received: by mail-lj1-f195.google.com with SMTP id l15-v6so14687990lja.9; Tue, 04 Dec 2018 04:18:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=T87JHThg7UO8QeA5V6fJftPPsz9yV1R5uLnw0cNr6IE=; b=TPvhzGMmuAy/Jp0MHlJaRrPY46SLLw9OCFu9x7y/7C3iLUWX6sx/58dG6VOnI9s+ii elacBrNvCv7bx6l6EpThFnTO1lCV5SGekhd1Rar+rEZeAsjGZG1rQgPJNAlpCG71eM/v g8HlTY1izmemrME/+NCDkGwZlyvNt7t/tAL+hhlDXceESY/ixa8cMheISX7krODoVRWi ivJSQ6f77thNBnNHiBa+rk2q22S/tvNKKkKNiS7pFv0accHWmF67oZwooIUS14bReL7d ZiT4VfsSj2pWQPKZc8Iz9bV2UxNpoteV0gCwF5BTUvU65TPJ5woU9c+oJ+7s3SUHY4hq HekA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=T87JHThg7UO8QeA5V6fJftPPsz9yV1R5uLnw0cNr6IE=; b=gnGwFc5gyM0xnyy7TjW5PI4R49wi8fOGIDxWrbauWzxIR3PcoOK+xLyT9D3MFgOtbp 7ZwjQE2Mg0TqE+5izctHm2/XKoIriZvWP6vbyKo0+4wyxuIfptGUCRJWo67LtwUV1OBG R175fNMiR2AVw1C/ElrP17hEcMyidT6fEyG7JmFL1gNaLKXWPt5RALFNmxzeNUFCZC6X xuhOjjDn2o9t+eds4BcMDxHP1yfTwQaSzkuOy+WeavUPRV6WwP2S/b1xyCsRwln36NXx XsHaas7wDl/+B283mQSprUED9tHeEayC84oJEE/ErNttrjY0aQAn6XC3T982UhgJ1G+H vApw== X-Gm-Message-State: AA+aEWZ6NseDzl2JvOjJUwb4Dl/e3qD0rFrs7DsvrvjNnUApF8C33bEA oa71clUtuqvXcM/4IktYwlc= X-Google-Smtp-Source: AFSGD/XfqQYN3wQyhBnGHV3cFZdJapmpbdPk784/DsTCfqnFrfRkG3qqaeqi2sFbGQh+z65PmwJTYA== X-Received: by 2002:a2e:12d0:: with SMTP id 77-v6mr1051581ljs.132.1543925921312; Tue, 04 Dec 2018 04:18:41 -0800 (PST) Received: from localhost.localdomain (91-156-179-117.elisa-laajakaista.fi. [91.156.179.117]) by smtp.gmail.com with ESMTPSA id h3sm2899653lfj.25.2018.12.04.04.18.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Dec 2018 04:18:40 -0800 (PST) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: Andy Lutomirski , Kees Cook , Matthew Wilcox Cc: igor.stoppa@huawei.com, Nadav Amit , Peter Zijlstra , Dave Hansen , linux-integrity@vger.kernel.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/6] __wr_after_init: linker section and label Date: Tue, 4 Dec 2018 14:18:00 +0200 Message-Id: <20181204121805.4621-2-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181204121805.4621-1-igor.stoppa@huawei.com> References: <20181204121805.4621-1-igor.stoppa@huawei.com> Reply-To: Igor Stoppa MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Introduce a section and a label for statically allocated write rare data. The label is named "__wr_after_init". As the name implies, after the init phase is completed, this section will be modifiable only by invoking write rare functions. The section must take up a set of full pages. Signed-off-by: Igor Stoppa CC: Andy Lutomirski CC: Nadav Amit CC: Matthew Wilcox CC: Peter Zijlstra CC: Kees Cook CC: Dave Hansen CC: linux-integrity@vger.kernel.org CC: kernel-hardening@lists.openwall.com CC: linux-mm@kvack.org CC: linux-kernel@vger.kernel.org --- include/asm-generic/vmlinux.lds.h | 20 ++++++++++++++++++++ include/linux/cache.h | 17 +++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 3d7a6a9c2370..b711dbe6999f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -311,6 +311,25 @@ KEEP(*(__jump_table)) \ __stop___jump_table = .; +/* + * Allow architectures to handle wr_after_init data on their + * own by defining an empty WR_AFTER_INIT_DATA. + * However, it's important that pages containing WR_RARE data do not + * hold anything else, to avoid both accidentally unprotecting something + * that is supposed to stay read-only all the time and also to protect + * something else that is supposed to be writeable all the time. + */ +#ifndef WR_AFTER_INIT_DATA +#define WR_AFTER_INIT_DATA(align) \ + . = ALIGN(PAGE_SIZE); \ + __start_wr_after_init = .; \ + . = ALIGN(align); \ + *(.data..wr_after_init) \ + . = ALIGN(PAGE_SIZE); \ + __end_wr_after_init = .; \ + . = ALIGN(align); +#endif + /* * Allow architectures to handle ro_after_init data on their * own by defining an empty RO_AFTER_INIT_DATA. @@ -332,6 +351,7 @@ __start_rodata = .; \ *(.rodata) *(.rodata.*) \ RO_AFTER_INIT_DATA /* Read only after init */ \ + WR_AFTER_INIT_DATA(align) /* wr after init */ \ KEEP(*(__vermagic)) /* Kernel version magic */ \ . = ALIGN(8); \ __start___tracepoints_ptrs = .; \ diff --git a/include/linux/cache.h b/include/linux/cache.h index 750621e41d1c..9a7e7134b887 100644 --- a/include/linux/cache.h +++ b/include/linux/cache.h @@ -31,6 +31,23 @@ #define __ro_after_init __attribute__((__section__(".data..ro_after_init"))) #endif +/* + * __wr_after_init is used to mark objects that cannot be modified + * directly after init (i.e. after mark_rodata_ro() has been called). + * These objects become effectively read-only, from the perspective of + * performing a direct write, like a variable assignment. + * However, they can be altered through a dedicated function. + * It is intended for those objects which are occasionally modified after + * init, however they are modified so seldomly, that the extra cost from + * the indirect modification is either negligible or worth paying, for the + * sake of the protection gained. + */ +#ifndef __wr_after_init +#define __wr_after_init \ + __attribute__((__section__(".data..wr_after_init"))) +#endif + + #ifndef ____cacheline_aligned #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) #endif From patchwork Tue Dec 4 12:18:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10711687 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9BD3514BD for ; Tue, 4 Dec 2018 12:19:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8DD662A386 for ; Tue, 4 Dec 2018 12:19:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 810752A37D; Tue, 4 Dec 2018 12:19:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A97C92A37D for ; Tue, 4 Dec 2018 12:19:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726246AbeLDMSs (ORCPT ); Tue, 4 Dec 2018 07:18:48 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:37394 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725955AbeLDMSr (ORCPT ); Tue, 4 Dec 2018 07:18:47 -0500 Received: by mail-lj1-f193.google.com with SMTP id e5-v6so14715187lja.4; Tue, 04 Dec 2018 04:18:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=MKhXHv/I+suoXSvWY4nOkDQg0yGt8f18bNJLOYzoxHQ=; b=gfnQgWeQffX3wVdRPVcjmboL00JGC8t7TbC+RAMpKpuzEMI+2s/f8LK1imQ05mYwT/ xcZLvzDYnNbaxT+JydGhBz58/N/6lbErp5QaiSfpLPs72sqz3Yv9UaHeyz2OlijZsumy dm1JMso9OG00MasdYPVwBFor6ktklkuQlSzYutp2DuNYA8+DIrvg4WC7etgHnXvUAa4f HopTED6G7o74rDwIPEvyW9qPC3D7wRyd9dNfxyDU2+8GU61BQNgpvnSDb+LfKXm0t1fJ kYS+RDYeDQW48BCz2BseM+MmIUDB52S/kihoje7fOf4VxfTtqJQbN0PsbeGLxD4JKGWK NFGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=MKhXHv/I+suoXSvWY4nOkDQg0yGt8f18bNJLOYzoxHQ=; b=TTewxZUdbU43jWMSyZouwq1UyQiAaiMSbBfkAvdGNRFOcr/IjL54K9+U0S8pJ7mXon ivHXMeR9FUZDQ/iMRNlIyThY/c3gMSzaiei8wg/YKu+4ujNl6Cm0lfu9jMz3+O/Vl4S2 6CX5dXzBtVHp+ztY7Qg8y5K2ghpu9XI9MEzkG1GbIt+p6MSZdDvF/bes1QpIubWBFD28 eEV2T+BroIHLBusqIwa+h4CbIt2zClonWZ1NzI+HIWyzxv1LoS2VVmvFEpku7gkWd4Ra tyCCyLZ92RxCLOZJ4thDB0hO4nmBBqvVeGBjI8bvDQ6CRD532+gPyRYMjdzf//T5omGg RhkA== X-Gm-Message-State: AA+aEWZaWCkCRc+A0CYNeiqhbac/abgL+A1JRW2B7GFRpEUCLRspFktX X6/oQQ//MhljsPTla6M++mi37B4ps84= X-Google-Smtp-Source: AFSGD/X5Ld4X34L6vNoHWDuvQhMxb5FqI8KA/+UtlMLx0Bgb9exvu91YMLJ7FP/CibfWnxue3VJ6fA== X-Received: by 2002:a2e:2c02:: with SMTP id s2-v6mr12920743ljs.118.1543925922527; Tue, 04 Dec 2018 04:18:42 -0800 (PST) Received: from localhost.localdomain (91-156-179-117.elisa-laajakaista.fi. [91.156.179.117]) by smtp.gmail.com with ESMTPSA id h3sm2899653lfj.25.2018.12.04.04.18.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Dec 2018 04:18:41 -0800 (PST) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: Andy Lutomirski , Kees Cook , Matthew Wilcox Cc: igor.stoppa@huawei.com, Nadav Amit , Peter Zijlstra , Dave Hansen , linux-integrity@vger.kernel.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/6] __wr_after_init: write rare for static allocation Date: Tue, 4 Dec 2018 14:18:01 +0200 Message-Id: <20181204121805.4621-3-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181204121805.4621-1-igor.stoppa@huawei.com> References: <20181204121805.4621-1-igor.stoppa@huawei.com> Reply-To: Igor Stoppa MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implementation of write rare for statically allocated data, located in a specific memory section through the use of the __write_rare label. The basic functions are: - wr_memset(): write rare counterpart of memset() - wr_memcpy(): write rare counterpart of memcpy() - wr_assign(): write rare counterpart of the assignment ('=') operator - wr_rcu_assign_pointer(): write rare counterpart of rcu_assign_pointer() The implementation is based on code from Andy Lutomirski and Nadav Amit for patching the text on x86 [here goes reference to commits, once merged] The modification of write protected data is done through an alternate mapping of the same pages, as writable. This mapping is local to each core and is active only for the duration of each write operation. Local interrupts are disabled, while the alternate mapping is active. In theory, it could introduce a non-predictable delay, in a preemptible system, however the amount of data to be altered is likely to be far smaller than a page. Signed-off-by: Igor Stoppa CC: Andy Lutomirski CC: Nadav Amit CC: Matthew Wilcox CC: Peter Zijlstra CC: Kees Cook CC: Dave Hansen CC: linux-integrity@vger.kernel.org CC: kernel-hardening@lists.openwall.com CC: linux-mm@kvack.org CC: linux-kernel@vger.kernel.org --- include/linux/prmem.h | 133 ++++++++++++++++++++++++++++++++++++++++++ init/main.c | 2 + mm/Kconfig | 4 ++ mm/Makefile | 1 + mm/prmem.c | 124 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 264 insertions(+) create mode 100644 include/linux/prmem.h create mode 100644 mm/prmem.c diff --git a/include/linux/prmem.h b/include/linux/prmem.h new file mode 100644 index 000000000000..b0131c1f5dc0 --- /dev/null +++ b/include/linux/prmem.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * prmem.h: Header for memory protection library + * + * (C) Copyright 2018 Huawei Technologies Co. Ltd. + * Author: Igor Stoppa + * + * Support for: + * - statically allocated write rare data + */ + +#ifndef _LINUX_PRMEM_H +#define _LINUX_PRMEM_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * memtst() - test n bytes of the source to match the c value + * @p: beginning of the memory to test + * @c: byte to compare against + * @len: amount of bytes to test + * + * Returns 0 on success, non-zero otherwise. + */ +static inline int memtst(void *p, int c, __kernel_size_t len) +{ + __kernel_size_t i; + + for (i = 0; i < len; i++) { + u8 d = *(i + (u8 *)p) - (u8)c; + + if (unlikely(d)) + return d; + } + return 0; +} + + +#ifndef CONFIG_PRMEM + +static inline void *wr_memset(void *p, int c, __kernel_size_t len) +{ + return memset(p, c, len); +} + +static inline void *wr_memcpy(void *p, const void *q, __kernel_size_t size) +{ + return memcpy(p, q, size); +} + +#define wr_assign(var, val) ((var) = (val)) + +#define wr_rcu_assign_pointer(p, v) \ + rcu_assign_pointer(p, v) + +#else + +enum wr_op_type { + WR_MEMCPY, + WR_MEMSET, + WR_RCU_ASSIGN_PTR, + WR_OPS_NUMBER, +}; + +void *__wr_op(unsigned long dst, unsigned long src, __kernel_size_t len, + enum wr_op_type op); + +/** + * wr_memset() - sets n bytes of the destination to the c value + * @p: beginning of the memory to write to + * @c: byte to replicate + * @len: amount of bytes to copy + * + * Returns true on success, false otherwise. + */ +static inline void *wr_memset(void *p, int c, __kernel_size_t len) +{ + return __wr_op((unsigned long)p, (unsigned long)c, len, WR_MEMSET); +} + +/** + * wr_memcpy() - copyes n bytes from source to destination + * @dst: beginning of the memory to write to + * @src: beginning of the memory to read from + * @n_bytes: amount of bytes to copy + * + * Returns pointer to the destination + */ +static inline void *wr_memcpy(void *p, const void *q, __kernel_size_t size) +{ + return __wr_op((unsigned long)p, (unsigned long)q, size, WR_MEMCPY); +} + +/** + * wr_assign() - sets a write-rare variable to a specified value + * @var: the variable to set + * @val: the new value + * + * Returns: the variable + * + * Note: it might be possible to optimize this, to use wr_memset in some + * cases (maybe with NULL?). + */ + +#define wr_assign(var, val) ({ \ + typeof(var) tmp = (typeof(var))val; \ + \ + wr_memcpy(&var, &tmp, sizeof(var)); \ + var; \ +}) + +/** + * wr_rcu_assign_pointer() - initialize a pointer in rcu mode + * @p: the rcu pointer + * @v: the new value + * + * Returns the value assigned to the rcu pointer. + * + * It is provided as macro, to match rcu_assign_pointer() + */ +#define wr_rcu_assign_pointer(p, v) ({ \ + __wr_op((unsigned long)&p, v, sizeof(p), WR_RCU_ASSIGN_PTR); \ + p; \ +}) +#endif +#endif diff --git a/init/main.c b/init/main.c index a461150adfb1..a36f2e54f937 100644 --- a/init/main.c +++ b/init/main.c @@ -498,6 +498,7 @@ void __init __weak thread_stack_cache_init(void) void __init __weak mem_encrypt_init(void) { } void __init __weak poking_init(void) { } +void __init __weak wr_poking_init(void) { } bool initcall_debug; core_param(initcall_debug, initcall_debug, bool, 0644); @@ -734,6 +735,7 @@ asmlinkage __visible void __init start_kernel(void) delayacct_init(); poking_init(); + wr_poking_init(); check_bugs(); acpi_subsystem_init(); diff --git a/mm/Kconfig b/mm/Kconfig index d85e39da47ae..9b09339c027f 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -142,6 +142,10 @@ config ARCH_DISCARD_MEMBLOCK config MEMORY_ISOLATION bool +config PRMEM + def_bool n + depends on STRICT_KERNEL_RWX && X86_64 + # # Only be set on architectures that have completely implemented memory hotplug # feature. If you are not sure, don't touch it. diff --git a/mm/Makefile b/mm/Makefile index d210cc9d6f80..ef3867c16ce0 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_SPARSEMEM) += sparse.o obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o obj-$(CONFIG_SLOB) += slob.o obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o +obj-$(CONFIG_PRMEM) += prmem.o obj-$(CONFIG_KSM) += ksm.o obj-$(CONFIG_PAGE_POISONING) += page_poison.o obj-$(CONFIG_SLAB) += slab.o diff --git a/mm/prmem.c b/mm/prmem.c new file mode 100644 index 000000000000..e8ab76701831 --- /dev/null +++ b/mm/prmem.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * prmem.c: Memory Protection Library + * + * (C) Copyright 2017-2018 Huawei Technologies Co. Ltd. + * Author: Igor Stoppa + */ + +#include +#include +#include +#include +#include +#include +#include + +static __ro_after_init bool wr_ready; +static __ro_after_init struct mm_struct *wr_poking_mm; +static __ro_after_init unsigned long wr_poking_base; + +/* + * The following two variables are statically allocated by the linker + * script at the the boundaries of the memory region (rounded up to + * multiples of PAGE_SIZE) reserved for __wr_after_init. + */ +extern long __start_wr_after_init; +extern long __end_wr_after_init; + +static inline bool is_wr_after_init(unsigned long ptr, __kernel_size_t size) +{ + unsigned long start = (unsigned long)&__start_wr_after_init; + unsigned long end = (unsigned long)&__end_wr_after_init; + unsigned long low = ptr; + unsigned long high = ptr + size; + + return likely(start <= low && low <= high && high <= end); +} + + +void *__wr_op(unsigned long dst, unsigned long src, __kernel_size_t len, + enum wr_op_type op) +{ + temporary_mm_state_t prev; + unsigned long flags; + unsigned long offset; + unsigned long wr_poking_addr; + + /* Confirm that the writable mapping exists. */ + BUG_ON(!wr_ready); + + if (WARN_ONCE(op >= WR_OPS_NUMBER, "Invalid WR operation.") || + WARN_ONCE(!is_wr_after_init(dst, len), "Invalid WR range.")) + return (void *)dst; + + offset = dst - (unsigned long)&__start_wr_after_init; + wr_poking_addr = wr_poking_base + offset; + local_irq_save(flags); + prev = use_temporary_mm(wr_poking_mm); + + kasan_disable_current(); + if (op == WR_MEMCPY) + memcpy((void *)wr_poking_addr, (void *)src, len); + else if (op == WR_MEMSET) + memset((u8 *)wr_poking_addr, (u8)src, len); + else if (op == WR_RCU_ASSIGN_PTR) + /* generic version of rcu_assign_pointer */ + smp_store_release((void **)wr_poking_addr, + RCU_INITIALIZER((void **)src)); + kasan_enable_current(); + + barrier(); /* XXX redundant? */ + + unuse_temporary_mm(prev); + /* XXX make the verification optional? */ + if (op == WR_MEMCPY) + BUG_ON(memcmp((void *)dst, (void *)src, len)); + else if (op == WR_MEMSET) + BUG_ON(memtst((void *)dst, (u8)src, len)); + else if (op == WR_RCU_ASSIGN_PTR) + BUG_ON(*(unsigned long *)dst != src); + local_irq_restore(flags); + return (void *)dst; +} + +struct mm_struct *copy_init_mm(void); +void __init wr_poking_init(void) +{ + unsigned long start = (unsigned long)&__start_wr_after_init; + unsigned long end = (unsigned long)&__end_wr_after_init; + unsigned long i; + unsigned long wr_range; + + wr_poking_mm = copy_init_mm(); + BUG_ON(!wr_poking_mm); + + /* XXX What if it's too large to fit in the task unmapped mem? */ + wr_range = round_up(end - start, PAGE_SIZE); + + /* Randomize the poking address base*/ + wr_poking_base = TASK_UNMAPPED_BASE + + (kaslr_get_random_long("Write Rare Poking") & PAGE_MASK) % + (TASK_SIZE - (TASK_UNMAPPED_BASE + wr_range)); + + /* Create alternate mapping for the entire wr_after_init range. */ + for (i = start; i < end; i += PAGE_SIZE) { + struct page *page; + spinlock_t *ptl; + pte_t pte; + pte_t *ptep; + unsigned long wr_poking_addr; + + BUG_ON(!(page = virt_to_page(i))); + wr_poking_addr = i - start + wr_poking_base; + + /* The lock is not needed, but avoids open-coding. */ + ptep = get_locked_pte(wr_poking_mm, wr_poking_addr, &ptl); + VM_BUG_ON(!ptep); + + pte = mk_pte(page, PAGE_KERNEL); + set_pte_at(wr_poking_mm, wr_poking_addr, ptep, pte); + spin_unlock(ptl); + } + wr_ready = true; +} From patchwork Tue Dec 4 12:18:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10711663 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CF02615A6 for ; Tue, 4 Dec 2018 12:18:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C03F42A0E0 for ; Tue, 4 Dec 2018 12:18:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B407F2A0E7; Tue, 4 Dec 2018 12:18:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4C0B32A0E0 for ; Tue, 4 Dec 2018 12:18:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726306AbeLDMSs (ORCPT ); Tue, 4 Dec 2018 07:18:48 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:38225 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725770AbeLDMSs (ORCPT ); Tue, 4 Dec 2018 07:18:48 -0500 Received: by mail-lj1-f196.google.com with SMTP id c19-v6so14695233lja.5; Tue, 04 Dec 2018 04:18:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=mJMksY6rKhfNGrlxoC/9f5P6S8jnAMH+e8y1ppLmkig=; b=nfKfgur+7NfxEvS1bNr5TrPQffifXufN2M74WYOVBCnHg6RWnRAHN6d1ot1S7MtTFS eY6DtAA8gW2IZoeav6Xcc5AP95lgP/FMR2427gUjvvUKkZBBR3G5NhF+CkCWXT9Gsk4m x9k9BzMQN2TNCkuYtBDF/xYteWxZNp/86VmbYls2v/jcsPvK2fqd5xzHOV5FAOWYnIGz 0WKvrgqSEpNV3438xLguGp0GrrkH6H+tCLK+45XnYElomR2jxOX8lvd5JR14KFSZLfYU YE6/+wD2ec0YztQZ/xtRLG428m5WKqopIB+uMESIKB9u99CVaVDuMQM6y3xclCIqVPpn PVQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=mJMksY6rKhfNGrlxoC/9f5P6S8jnAMH+e8y1ppLmkig=; b=SF3wnHVXqG7cDo1+o+KjBNaixcYQJ/QUk2pG4AiHwmx9p0GHyNP+TkGuGHujyo8DPF TJlgi/pUoY1TLwQhrZbmo6y2zWeEq9ikimebl4gevlYGaS4nsXtnqYlvGJTpX2Y2VpUH 6FI51uVBjJBmipmbcO4dt3xd62Mqs1t+OVXnhsk3TN3wH6lb11O7pNLVtRn4+ypfYuJX 2SqgcP3T1lbR4ZLIxWtWfXGJ6/nP/XDJUoHNPjtjJar1bTQBR8kV0sWeChIdQVdUQs53 6xxiDnlXj8l6WuxUPTcV5KgQcXI2U5HxUzw0vUVRTJrhnsJuazv/KYFtTMFQWqOqAYO1 liRw== X-Gm-Message-State: AA+aEWZpN1OxCrxC16jfEDHvVD2IrHlO4Mfo+EIcHtNbOnZss9Ason8E OE7uFEVuo/HxdEWWjvvH49Y= X-Google-Smtp-Source: AFSGD/WWQI8QGsQXXSTC5ZysrJ5U8vMjuWZFjwJ8suURld6RLcFQmBCHttm98abwWPkEAZpczf/7pA== X-Received: by 2002:a2e:63cd:: with SMTP id s74-v6mr12265480lje.117.1543925923947; Tue, 04 Dec 2018 04:18:43 -0800 (PST) Received: from localhost.localdomain (91-156-179-117.elisa-laajakaista.fi. [91.156.179.117]) by smtp.gmail.com with ESMTPSA id h3sm2899653lfj.25.2018.12.04.04.18.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Dec 2018 04:18:43 -0800 (PST) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: Andy Lutomirski , Kees Cook , Matthew Wilcox Cc: igor.stoppa@huawei.com, Nadav Amit , Peter Zijlstra , Dave Hansen , linux-integrity@vger.kernel.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/6] rodata_test: refactor tests Date: Tue, 4 Dec 2018 14:18:02 +0200 Message-Id: <20181204121805.4621-4-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181204121805.4621-1-igor.stoppa@huawei.com> References: <20181204121805.4621-1-igor.stoppa@huawei.com> Reply-To: Igor Stoppa MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Refactor the test cases, in preparation for using them also for testing __wr_after_init memory. Signed-off-by: Igor Stoppa CC: Andy Lutomirski CC: Nadav Amit CC: Matthew Wilcox CC: Peter Zijlstra CC: Kees Cook CC: Dave Hansen CC: linux-integrity@vger.kernel.org CC: kernel-hardening@lists.openwall.com CC: linux-mm@kvack.org CC: linux-kernel@vger.kernel.org --- mm/rodata_test.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/mm/rodata_test.c b/mm/rodata_test.c index d908c8769b48..3c1e515ca9b1 100644 --- a/mm/rodata_test.c +++ b/mm/rodata_test.c @@ -14,44 +14,52 @@ #include #include -static const int rodata_test_data = 0xC3; +#define INIT_TEST_VAL 0xC3 -void rodata_test(void) +static const int rodata_test_data = INIT_TEST_VAL; + +static bool test_data(char *data_type, const int *data, + unsigned long start, unsigned long end) { - unsigned long start, end; int zero = 0; /* test 1: read the value */ /* If this test fails, some previous testrun has clobbered the state */ - if (!rodata_test_data) { - pr_err("test 1 fails (start data)\n"); - return; + if (*data != INIT_TEST_VAL) { + pr_err("%s: test 1 fails (init data value)\n", data_type); + return false; } /* test 2: write to the variable; this should fault */ - if (!probe_kernel_write((void *)&rodata_test_data, - (void *)&zero, sizeof(zero))) { - pr_err("test data was not read only\n"); - return; + if (!probe_kernel_write((void *)data, (void *)&zero, sizeof(zero))) { + pr_err("%s: test data was not read only\n", data_type); + return false; } /* test 3: check the value hasn't changed */ - if (rodata_test_data == zero) { - pr_err("test data was changed\n"); - return; + if (*data != INIT_TEST_VAL) { + pr_err("%s: test data was changed\n", data_type); + return false; } /* test 4: check if the rodata section is PAGE_SIZE aligned */ - start = (unsigned long)__start_rodata; - end = (unsigned long)__end_rodata; if (start & (PAGE_SIZE - 1)) { - pr_err("start of .rodata is not page size aligned\n"); - return; + pr_err("%s: start of data is not page size aligned\n", + data_type); + return false; } if (end & (PAGE_SIZE - 1)) { - pr_err("end of .rodata is not page size aligned\n"); - return; + pr_err("%s: end of data is not page size aligned\n", + data_type); + return false; } + return true; +} - pr_info("all tests were successful\n"); +void rodata_test(void) +{ + if (test_data("rodata", &rodata_test_data, + (unsigned long)&__start_rodata, + (unsigned long)&__end_rodata)) + pr_info("all tests were successful\n"); } From patchwork Tue Dec 4 12:18:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10711685 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5B18214BD for ; Tue, 4 Dec 2018 12:19:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4ABB32A37D for ; Tue, 4 Dec 2018 12:19:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3EFCB2A391; Tue, 4 Dec 2018 12:19:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DB32A2A37D for ; Tue, 4 Dec 2018 12:19:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726313AbeLDMSu (ORCPT ); Tue, 4 Dec 2018 07:18:50 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:33596 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726289AbeLDMSt (ORCPT ); Tue, 4 Dec 2018 07:18:49 -0500 Received: by mail-lj1-f194.google.com with SMTP id v1-v6so14708135ljd.0; Tue, 04 Dec 2018 04:18:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=WBnbM87FYiZB144WHH+WIErpqzF5ZNVsWJfotUGC/To=; b=E3RY5vkybSvPTIG8UuGMwEVOwkUplL0AFDj1MN9T0ROLaaMBhx3o6sL9qiBqK8cDpF lHokL4Goz61X1sMwWX2rqe8g+i/xkU80XCiz6Keo5mY+N2QwkuztsW8I1TLYVZ36cJL0 cH3fN77tAZGhRIwFjGT/udN/UU2XaH/2piLYSuFcG9+mF0rVBDyJkSqRWN10wU0RGVLp g/U3CKeZCh+PdGUKf8B7AMY64oqIvcBkpDi5JA5HxCI6tSjMn8oOG8MbP/CCJI23fOqP OzTixarbLeKA4neW+891Bwfc31u1LhGzMb0feY22cbNyFQTUMEWbsqO2Kl8cBZC+/vvy QAYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=WBnbM87FYiZB144WHH+WIErpqzF5ZNVsWJfotUGC/To=; b=tt48kyoff7pEIyg4FEPYKGDQ2vzW3/6CTRYpTsS7iSN2waDsDBTyPYo/TXSMOqflko jtJFZi+yQuinUrstRazjnDM83Walk//lomVvw8xeVNsfbHUH0zotgm1yWV8FdMkdrSSg vOJJIAKeGCST4belywHEMuvPuCGRu6UcaS9YtlWfBKK1xWJ7OMVaMk9hKpuEjdS0V5KH /31zHs7Iz9Hhd+pXn2WZBF8UG4l3V30dbAAFy50hGe6Qgp1VcWA8a2YKvwTnCJjmLbkx cnIgm47W/TGBcMFyIPzNWTbS0hLMnJMpgwsKGzOyI1WT6k4/jx+ScjIE/F7YaAAth6/2 Fihg== X-Gm-Message-State: AA+aEWYdSqZYoLzYIxye2nGkXoKy1hfffX63GJBL30MqJeGTtxlSKSsH bEJQXpDvDjpjk6u93qTxehA= X-Google-Smtp-Source: AFSGD/Uz5k3knHQnWYcPn5vvfo8l7N0tmCpAv9nXtZVRKiyo8X/OPZgpu0935A98/eCYHI1LGa7rXQ== X-Received: by 2002:a2e:9957:: with SMTP id r23-v6mr12190962ljj.98.1543925925285; Tue, 04 Dec 2018 04:18:45 -0800 (PST) Received: from localhost.localdomain (91-156-179-117.elisa-laajakaista.fi. [91.156.179.117]) by smtp.gmail.com with ESMTPSA id h3sm2899653lfj.25.2018.12.04.04.18.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Dec 2018 04:18:44 -0800 (PST) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: Andy Lutomirski , Kees Cook , Matthew Wilcox Cc: igor.stoppa@huawei.com, Nadav Amit , Peter Zijlstra , Dave Hansen , linux-integrity@vger.kernel.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/6] rodata_test: add verification for __wr_after_init Date: Tue, 4 Dec 2018 14:18:03 +0200 Message-Id: <20181204121805.4621-5-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181204121805.4621-1-igor.stoppa@huawei.com> References: <20181204121805.4621-1-igor.stoppa@huawei.com> Reply-To: Igor Stoppa MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The write protection of the __wr_after_init data can be verified with the same methodology used for const data. Signed-off-by: Igor Stoppa CC: Andy Lutomirski CC: Nadav Amit CC: Matthew Wilcox CC: Peter Zijlstra CC: Kees Cook CC: Dave Hansen CC: linux-integrity@vger.kernel.org CC: kernel-hardening@lists.openwall.com CC: linux-mm@kvack.org CC: linux-kernel@vger.kernel.org --- mm/rodata_test.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mm/rodata_test.c b/mm/rodata_test.c index 3c1e515ca9b1..a98d088ad9cc 100644 --- a/mm/rodata_test.c +++ b/mm/rodata_test.c @@ -16,7 +16,19 @@ #define INIT_TEST_VAL 0xC3 +/* + * Note: __ro_after_init data is, for every practical effect, equivalent to + * const data, since they are even write protected at the same time; there + * is no need for separate testing. + * __wr_after_init data, otoh, is altered also after the write protection + * takes place and it cannot be exploitable for altering more permanent + * data. + */ + static const int rodata_test_data = INIT_TEST_VAL; +static int wr_after_init_test_data __wr_after_init = INIT_TEST_VAL; +extern long __start_wr_after_init; +extern long __end_wr_after_init; static bool test_data(char *data_type, const int *data, unsigned long start, unsigned long end) @@ -60,6 +72,9 @@ void rodata_test(void) { if (test_data("rodata", &rodata_test_data, (unsigned long)&__start_rodata, - (unsigned long)&__end_rodata)) + (unsigned long)&__end_rodata) && + test_data("wr after init data", &wr_after_init_test_data, + (unsigned long)&__start_wr_after_init, + (unsigned long)&__end_wr_after_init)) pr_info("all tests were successful\n"); } From patchwork Tue Dec 4 12:18:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10711679 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1F95B14BD for ; Tue, 4 Dec 2018 12:19:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1259F2A0E0 for ; Tue, 4 Dec 2018 12:19:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 064952A0E7; Tue, 4 Dec 2018 12:19:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 612C92A0E0 for ; Tue, 4 Dec 2018 12:19:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726151AbeLDMS7 (ORCPT ); Tue, 4 Dec 2018 07:18:59 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:42154 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725801AbeLDMSw (ORCPT ); Tue, 4 Dec 2018 07:18:52 -0500 Received: by mail-lj1-f194.google.com with SMTP id l15-v6so14688257lja.9; Tue, 04 Dec 2018 04:18:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=KelN+/epBNC6XQnXj/EwWYuqT/y6Dkv8jfVNF/vOmp0=; b=Ucrw/UqR6jj/kLnoRFUkGZh+bpI5fmBzCwCETF/CLgfnVVGru5oqqJZ+7QhYx5n5Fm Shp9pV7DYoFwZs6KOZIyeT5wTjZS1uNj9k1Pg7deoq7ohIYKI71ZnH5xa+kAYKeNq9sF S6jfWP/cyuzeYLp/XNxveiW8CNlYDHQM0l/ckxNqSLKFHfTn0HNhcur/UMZRXbCJq9M9 9gAZs1sR7tX/jQ6B3WZuVDvxMqJ6T9hcsLJ4zarJBspjLmz0Z2ojq0McRWoy63duE35n rjJpzfvnYHiZd7LYQegCvO1OxGLFBA7aOH7VHMeUFs/MBPoKl8l8Afm50pcAvBUr0fHK 8i4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=KelN+/epBNC6XQnXj/EwWYuqT/y6Dkv8jfVNF/vOmp0=; b=GZr5DDlEkAvmOuckyszFK5SHWNGtixoqjI4Dw1IbkPj7dL18f0Cc3tQkuVt5O0Z6Ay uiOp5SC9JZHcgH7jftNOTzzbBBVD4/FRmz1uqqKnQfT8Bf1eyttjWajk6cSuhZKLp+7V JwD91iXXLiFlF1pm7hmhD1JQlz1qWWppHDnR1VLVrH8OkO3hSkyMZESs7XITY6VWqbzD K44gm5eTFhf5Ds2l5ySSrPg+ea7NTsjdcgNgTSqMYoWlK3l4PHkeLdw0gX2866YjUmKF 8xjUoalnf1mZOYK/lpmIfBhFIa/1XtxkI2ga+9jcXkhs6Vc5rb4JhGyoZuJEPN5OGNnK ZXYw== X-Gm-Message-State: AA+aEWY9mQhRbsQP92M48wOP5l/JnRv98njpmwEJ1ZnN3Z3+GH0rU+xB xXsbkkS5+BiEyT/Ezzd2G74= X-Google-Smtp-Source: AFSGD/U2cqReuGWQC1ZRgos10lgGbtiWNxDr3WCe9FOfg/C7eVOwLMAuyb7v5shFbtygFYMfaJo1eA== X-Received: by 2002:a2e:4299:: with SMTP id h25-v6mr12224879ljf.5.1543925926664; Tue, 04 Dec 2018 04:18:46 -0800 (PST) Received: from localhost.localdomain (91-156-179-117.elisa-laajakaista.fi. [91.156.179.117]) by smtp.gmail.com with ESMTPSA id h3sm2899653lfj.25.2018.12.04.04.18.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Dec 2018 04:18:46 -0800 (PST) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: Andy Lutomirski , Kees Cook , Matthew Wilcox Cc: igor.stoppa@huawei.com, Nadav Amit , Peter Zijlstra , Dave Hansen , linux-integrity@vger.kernel.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/6] __wr_after_init: test write rare functionality Date: Tue, 4 Dec 2018 14:18:04 +0200 Message-Id: <20181204121805.4621-6-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181204121805.4621-1-igor.stoppa@huawei.com> References: <20181204121805.4621-1-igor.stoppa@huawei.com> Reply-To: Igor Stoppa MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Set of test cases meant to confirm that the write rare functionality works as expected. Signed-off-by: Igor Stoppa CC: Andy Lutomirski CC: Nadav Amit CC: Matthew Wilcox CC: Peter Zijlstra CC: Kees Cook CC: Dave Hansen CC: linux-integrity@vger.kernel.org CC: kernel-hardening@lists.openwall.com CC: linux-mm@kvack.org CC: linux-kernel@vger.kernel.org --- include/linux/prmem.h | 7 ++- mm/Kconfig.debug | 9 +++ mm/Makefile | 1 + mm/test_write_rare.c | 135 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 mm/test_write_rare.c diff --git a/include/linux/prmem.h b/include/linux/prmem.h index b0131c1f5dc0..d2492ec24c8c 100644 --- a/include/linux/prmem.h +++ b/include/linux/prmem.h @@ -125,9 +125,10 @@ static inline void *wr_memcpy(void *p, const void *q, __kernel_size_t size) * * It is provided as macro, to match rcu_assign_pointer() */ -#define wr_rcu_assign_pointer(p, v) ({ \ - __wr_op((unsigned long)&p, v, sizeof(p), WR_RCU_ASSIGN_PTR); \ - p; \ +#define wr_rcu_assign_pointer(p, v) ({ \ + __wr_op((unsigned long)&p, (unsigned long)v, sizeof(p), \ + WR_RCU_ASSIGN_PTR); \ + p; \ }) #endif #endif diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug index 9a7b8b049d04..a26ecbd27aea 100644 --- a/mm/Kconfig.debug +++ b/mm/Kconfig.debug @@ -94,3 +94,12 @@ config DEBUG_RODATA_TEST depends on STRICT_KERNEL_RWX ---help--- This option enables a testcase for the setting rodata read-only. + +config DEBUG_PRMEM_TEST + tristate "Run self test for statically allocated protected memory" + depends on STRICT_KERNEL_RWX + select PRMEM + default n + help + Tries to verify that the protection for statically allocated memory + works correctly and that the memory is effectively protected. diff --git a/mm/Makefile b/mm/Makefile index ef3867c16ce0..8de1d468f4e7 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o obj-$(CONFIG_SLOB) += slob.o obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o obj-$(CONFIG_PRMEM) += prmem.o +obj-$(CONFIG_DEBUG_PRMEM_TEST) += test_write_rare.o obj-$(CONFIG_KSM) += ksm.o obj-$(CONFIG_PAGE_POISONING) += page_poison.o obj-$(CONFIG_SLAB) += slab.o diff --git a/mm/test_write_rare.c b/mm/test_write_rare.c new file mode 100644 index 000000000000..240cc43793d1 --- /dev/null +++ b/mm/test_write_rare.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * test_write_rare.c + * + * (C) Copyright 2018 Huawei Technologies Co. Ltd. + * Author: Igor Stoppa + */ + +#include +#include +#include +#include +#include + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +extern long __start_wr_after_init; +extern long __end_wr_after_init; + +static __wr_after_init int scalar = '0'; +static __wr_after_init u8 array[PAGE_SIZE * 3] __aligned(PAGE_SIZE); + +/* The section must occupy a non-zero number of whole pages */ +static bool test_alignment(void) +{ + unsigned long pstart = (unsigned long)&__start_wr_after_init; + unsigned long pend = (unsigned long)&__end_wr_after_init; + + if (WARN((pstart & ~PAGE_MASK) || (pend & ~PAGE_MASK) || + (pstart >= pend), "Boundaries test failed.")) + return false; + pr_info("Boundaries test passed."); + return true; +} + +static inline bool test_pattern(void) +{ + return (memtst(array, '0', PAGE_SIZE / 2) || + memtst(array + PAGE_SIZE / 2, '1', PAGE_SIZE * 3 / 4) || + memtst(array + PAGE_SIZE * 5 / 4, '0', PAGE_SIZE / 2) || + memtst(array + PAGE_SIZE * 7 / 4, '1', PAGE_SIZE * 3 / 4) || + memtst(array + PAGE_SIZE * 5 / 2, '0', PAGE_SIZE / 2)); +} + +static bool test_wr_memset(void) +{ + int new_val = '1'; + + wr_memset(&scalar, new_val, sizeof(scalar)); + if (WARN(memtst(&scalar, new_val, sizeof(scalar)), + "Scalar write rare memset test failed.")) + return false; + + pr_info("Scalar write rare memset test passed."); + + wr_memset(array, '0', PAGE_SIZE * 3); + if (WARN(memtst(array, '0', PAGE_SIZE * 3), + "Array write rare memset test failed.")) + return false; + + wr_memset(array + PAGE_SIZE / 2, '1', PAGE_SIZE * 2); + if (WARN(memtst(array + PAGE_SIZE / 2, '1', PAGE_SIZE * 2), + "Array write rare memset test failed.")) + return false; + + wr_memset(array + PAGE_SIZE * 5 / 4, '0', PAGE_SIZE / 2); + if (WARN(memtst(array + PAGE_SIZE * 5 / 4, '0', PAGE_SIZE / 2), + "Array write rare memset test failed.")) + return false; + + if (WARN(test_pattern(), "Array write rare memset test failed.")) + return false; + + pr_info("Array write rare memset test passed."); + return true; +} + +static u8 array_1[PAGE_SIZE * 2]; +static u8 array_2[PAGE_SIZE * 2]; + +static bool test_wr_memcpy(void) +{ + int new_val = 0x12345678; + + wr_assign(scalar, new_val); + if (WARN(memcmp(&scalar, &new_val, sizeof(scalar)), + "Scalar write rare memcpy test failed.")) + return false; + pr_info("Scalar write rare memcpy test passed."); + + wr_memset(array, '0', PAGE_SIZE * 3); + memset(array_1, '1', PAGE_SIZE * 2); + memset(array_2, '0', PAGE_SIZE * 2); + wr_memcpy(array + PAGE_SIZE / 2, array_1, PAGE_SIZE * 2); + wr_memcpy(array + PAGE_SIZE * 5 / 4, array_2, PAGE_SIZE / 2); + + if (WARN(test_pattern(), "Array write rare memcpy test failed.")) + return false; + + pr_info("Array write rare memcpy test passed."); + return true; +} + +static __wr_after_init int *dst; +static int reference = 0x54; + +static bool test_wr_rcu_assign_pointer(void) +{ + wr_rcu_assign_pointer(dst, &reference); + return dst == &reference; +} + +static int __init test_static_wr_init_module(void) +{ + pr_info("static write_rare test"); + if (WARN(!(test_alignment() && + test_wr_memset() && + test_wr_memcpy() && + test_wr_rcu_assign_pointer()), + "static rare-write test failed")) + return -EFAULT; + pr_info("static write_rare test passed"); + return 0; +} + +module_init(test_static_wr_init_module); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Igor Stoppa "); +MODULE_DESCRIPTION("Test module for static write rare."); From patchwork Tue Dec 4 12:18:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10711683 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77BA115A6 for ; Tue, 4 Dec 2018 12:19:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 686A12A386 for ; Tue, 4 Dec 2018 12:19:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5B96F2A37D; Tue, 4 Dec 2018 12:19:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E2D9B2A386 for ; Tue, 4 Dec 2018 12:19:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725801AbeLDMTG (ORCPT ); Tue, 4 Dec 2018 07:19:06 -0500 Received: from mail-lj1-f195.google.com ([209.85.208.195]:46170 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726308AbeLDMSv (ORCPT ); Tue, 4 Dec 2018 07:18:51 -0500 Received: by mail-lj1-f195.google.com with SMTP id v15-v6so14662143ljh.13; Tue, 04 Dec 2018 04:18:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=NVdqMmCKQZDysvXYUM4dpuRHk0CW6y96xz6tH9NdrSw=; b=HRfrXCFQvzKgQhKYWkbS/im8+XnLQmGG8ccr5n3DY3AvBzv51R79u/dWJYuhk3Y/QB 5F3PX6ti+fzfyYUTTRkeMeP2Qkk/GOPZC3dVKjWeDjWxzfaNsQWYwv8PUBhakUjEMGpC +3eyvJFkXoEIJcYl3HPC01uHhpdzkuhiE5IctH//w5KYZf8JD/Y7Gole7e9dz6kxhzmW ZC9eXZteiMUUw1lsEK1t4DghxBzJd4NJHIq3xxVBIuqzUX0poFyAOWyUxaemqKC77wOK Ydsd8ZfPrBokXf7ifOd5x8NzNp/7evrgARi/7ve5XNikMvobqmD29jlx6kR0upcm+wRp 8YMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=NVdqMmCKQZDysvXYUM4dpuRHk0CW6y96xz6tH9NdrSw=; b=hcmwnRcYAMEpKVc6dzPRQvqHlsjgKSkry0Rh/Ao44+/D9BLeI0LoBLZqBOb9RL7M2K zmXucjApP4B0aTxwPaA+wjFEl1tZwWt2cgR/Sif3vY1YEyq5WF+kigyVZXMJEjo2AGe2 CeyM5huPdQFAVa0yK7PRNXuJt5HFuvv1X9CBJy7iIViJZXqGzzGWcx0xDYm+HgllTexZ AUvUupSi9PbNKgwbT1zOAQAdQNneWV9GuVIpkTN10WEMvrSwQEuZlIeKKesvIhaH27FE afgClq8S4aUrSM4fQJVf3nJ8LW5dvw8DIQ0CP99FQqhaQq7UksP8u1tGoabdcJbJOEmz 3K9Q== X-Gm-Message-State: AA+aEWao5hC5fdvzkVwHmm03GmXD2ZRkY0OWhJRAgbJ0OWpnp/2UsSjH z1VAPltGfJmWAHbBQIi/68Q= X-Google-Smtp-Source: AFSGD/UPXTOGRAw/49T9676bvJ9/1gFe/zO9Lwr0qxwwIUQFs7TARHUmypZrYSVjqRzSte4x5ibGcg== X-Received: by 2002:a2e:9a16:: with SMTP id o22-v6mr3119346lji.112.1543925928237; Tue, 04 Dec 2018 04:18:48 -0800 (PST) Received: from localhost.localdomain (91-156-179-117.elisa-laajakaista.fi. [91.156.179.117]) by smtp.gmail.com with ESMTPSA id h3sm2899653lfj.25.2018.12.04.04.18.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Dec 2018 04:18:47 -0800 (PST) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: Andy Lutomirski , Kees Cook , Matthew Wilcox Cc: igor.stoppa@huawei.com, Nadav Amit , Peter Zijlstra , Dave Hansen , linux-integrity@vger.kernel.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/6] __wr_after_init: lkdtm test Date: Tue, 4 Dec 2018 14:18:05 +0200 Message-Id: <20181204121805.4621-7-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181204121805.4621-1-igor.stoppa@huawei.com> References: <20181204121805.4621-1-igor.stoppa@huawei.com> Reply-To: Igor Stoppa MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Verify that trying to modify a variable with the __wr_after_init modifier wil lcause a crash. Signed-off-by: Igor Stoppa CC: Andy Lutomirski CC: Nadav Amit CC: Matthew Wilcox CC: Peter Zijlstra CC: Kees Cook CC: Dave Hansen CC: linux-integrity@vger.kernel.org CC: kernel-hardening@lists.openwall.com CC: linux-mm@kvack.org CC: linux-kernel@vger.kernel.org --- drivers/misc/lkdtm/core.c | 3 +++ drivers/misc/lkdtm/lkdtm.h | 3 +++ drivers/misc/lkdtm/perms.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index 2837dc77478e..73c34b17c433 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -155,6 +155,9 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(ACCESS_USERSPACE), CRASHTYPE(WRITE_RO), CRASHTYPE(WRITE_RO_AFTER_INIT), +#ifdef CONFIG_PRMEM + CRASHTYPE(WRITE_WR_AFTER_INIT), +#endif CRASHTYPE(WRITE_KERN), CRASHTYPE(REFCOUNT_INC_OVERFLOW), CRASHTYPE(REFCOUNT_ADD_OVERFLOW), diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index 3c6fd327e166..abba2f52ffa6 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -38,6 +38,9 @@ void lkdtm_READ_BUDDY_AFTER_FREE(void); void __init lkdtm_perms_init(void); void lkdtm_WRITE_RO(void); void lkdtm_WRITE_RO_AFTER_INIT(void); +#ifdef CONFIG_PRMEM +void lkdtm_WRITE_WR_AFTER_INIT(void); +#endif void lkdtm_WRITE_KERN(void); void lkdtm_EXEC_DATA(void); void lkdtm_EXEC_STACK(void); diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c index 53b85c9d16b8..f681730aa652 100644 --- a/drivers/misc/lkdtm/perms.c +++ b/drivers/misc/lkdtm/perms.c @@ -9,6 +9,7 @@ #include #include #include +#include #include /* Whether or not to fill the target memory area with do_nothing(). */ @@ -27,6 +28,10 @@ static const unsigned long rodata = 0xAA55AA55; /* This is marked __ro_after_init, so it should ultimately be .rodata. */ static unsigned long ro_after_init __ro_after_init = 0x55AA5500; +/* This is marked __wr_after_init, so it should be in .rodata. */ +static +unsigned long wr_after_init __wr_after_init = 0x55AA5500; + /* * This just returns to the caller. It is designed to be copied into * non-executable memory regions. @@ -104,6 +109,28 @@ void lkdtm_WRITE_RO_AFTER_INIT(void) *ptr ^= 0xabcd1234; } +#ifdef CONFIG_PRMEM + +void lkdtm_WRITE_WR_AFTER_INIT(void) +{ + unsigned long *ptr = &wr_after_init; + + /* + * Verify we were written to during init. Since an Oops + * is considered a "success", a failure is to just skip the + * real test. + */ + if ((*ptr & 0xAA) != 0xAA) { + pr_info("%p was NOT written during init!?\n", ptr); + return; + } + + pr_info("attempting bad wr_after_init write at %p\n", ptr); + *ptr ^= 0xabcd1234; +} + +#endif + void lkdtm_WRITE_KERN(void) { size_t size; @@ -200,4 +227,6 @@ void __init lkdtm_perms_init(void) /* Make sure we can write to __ro_after_init values during __init */ ro_after_init |= 0xAA; + /* Make sure we can write to __wr_after_init during __init */ + wr_after_init |= 0xAA; }