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: 10711677 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 1265917DB for ; Tue, 4 Dec 2018 12:19:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0536F2A0E0 for ; Tue, 4 Dec 2018 12:19:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EDA212A0E7; Tue, 4 Dec 2018 12:19:03 +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=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 7DE4D2A0E0 for ; Tue, 4 Dec 2018 12:19:02 +0000 (UTC) Received: (qmail 19932 invoked by uid 550); 4 Dec 2018 12:18:53 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 19889 invoked from network); 4 Dec 2018 12:18:52 -0000 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=EwYP8xn9N3nZuIX23RJ5A6N/m7fVIqLaKAXuoDn5O0ngg8IWfMkxQ/VF1A8LFt+Sdl YVAr7//5lk4D2/XdjwZi5qVhQoKB4xQuWoUND+HjvH0CBPJPrjYFldXePdWrzJp3+fAM 1AmgvaOZ/sjWUyM3jlN7++WnuRYY7j+PqoZwWcpalZ2z1ofxkNPNggPzDS6V6TSUTTTf uck6U3iIn9l5UC2v8x5he6cCRpS1PGqIZpaWQ4JmQVr80XxnvU5P9xlsvXF5hZoHmT7x ruyv8R+YKuOX22RnPVJyTSlJ8Az9lJZR4RiUysZIbAccDE6WdHAWtzU/mvojdqc9gRDf b6QQ== X-Gm-Message-State: AA+aEWZZm8+lZBoTaZ54kg2/rn4Lk41yiEh2CqQpeQf0ibN8fs+HHv8k 2zlT0S3BuXGJ6C0/dG8reQk= 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) 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> MIME-Version: 1.0 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: 10711681 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 7BBC017DB 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 6BBC12A39D for ; Tue, 4 Dec 2018 12:19:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 59DFB2A3A1; 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=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id B31AE2A37D for ; Tue, 4 Dec 2018 12:19:10 +0000 (UTC) Received: (qmail 20110 invoked by uid 550); 4 Dec 2018 12:18:54 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 20015 invoked from network); 4 Dec 2018 12:18:54 -0000 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=RksvQrXwp3azuC3hYeQH9PvGLHlmjnulB1k4jp9Ji3B5Fyxntqm1Aio6465Vv0cKeI 0YTP9uOfIG6Hb4xJUdxucuI9NKLyqjUeUQtZAos5oUjppb9fSn1xMa0DX+SU2R1O8gh2 VKu+yXaeoMQYnu9lzbIWdvlOB4+vY8p0URtgtg45hd8PML8PQLI+ao0Ek9mnGBFG0LKS HsVLcUFLD9EB7rnBZ/impVesEEKlOBD5Cn+fISnIHKOWNFb2/KgdRXZRXCRlemrFCoFS t0bEmAe+Nc2gOZUNkuSUb3pNQB7HZd2zINFxdyErZ0N1XkNNfMMpMNfsq43V39+YwBHL 5Y6w== X-Gm-Message-State: AA+aEWYrcJr8jvWhsVv77BjZhSSPHkfiDDiDOZOzf3+i2DfMRpoKGokz FLRlHOXA+6YMj0iyjrdnIm0= 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) 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> MIME-Version: 1.0 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: 10711691 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 06CC815A6 for ; Tue, 4 Dec 2018 12:19:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE1302A37D for ; Tue, 4 Dec 2018 12:19:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E1A892A391; Tue, 4 Dec 2018 12:19:23 +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=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 3ECBA2A37D for ; Tue, 4 Dec 2018 12:19:22 +0000 (UTC) Received: (qmail 20324 invoked by uid 550); 4 Dec 2018 12:18:56 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 20204 invoked from network); 4 Dec 2018 12:18:55 -0000 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=kV5+EWDqunzelZLYUh3oJeC/bYaPL1hK1BoJnlHcP6HSFaaznl/hVpryPogX9HXUc+ RSaNVqzd5dC84Ty6jh9ZjlTUIVhCYq0Y/3e4RnmvuMKH8mgjp5ATMHch+hWLxWCEh9zI tc928extcNr3yGe2ErJlpzKpF1pXp0tI/TKoNJ6LzVaWZiDRZRNxkQaVGJbNoVQZhKIs fczKXr24LY9dc2UzmBJgQI9RcgBjnZcOpvAATyBNpynWEPiM/HEI50APA0Pz3suy/rnK bc6bgFn0HuwfsJyMJIC3Lo6zXqJ1Da9B5dNmbqgSm3CUURjAl8AyKTGN56vhKOpmO8Wq xmsw== X-Gm-Message-State: AA+aEWb7W8oN5gke66vmTPv7miIYMT9AYR+CT9h11ItXUaaymCtH+oLL fT6mgBNiSFuZUWzgdHcmRUY= 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) 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> MIME-Version: 1.0 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: 10711693 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 6F3BC14BD for ; Tue, 4 Dec 2018 12:19:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5FE7A2A37D for ; Tue, 4 Dec 2018 12:19:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5264C2A391; Tue, 4 Dec 2018 12:19:33 +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=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 7952E2A37D for ; Tue, 4 Dec 2018 12:19:32 +0000 (UTC) Received: (qmail 20452 invoked by uid 550); 4 Dec 2018 12:18:57 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 20336 invoked from network); 4 Dec 2018 12:18:56 -0000 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=FgGFWKHC8Y3Fzm9nPRcnK1CSUzg0lhG09Kh8BNW/awTdV6J1Vgse2SXUIAIxAQT8Wu EPjrGdcAQXBKuHIzucNsd1BSfuo+cCXl2o2Q34EtDd7FEyYslgVq3eoMY/PeCoqMkdbA MNA82CGL9XnvHb/p6SNScjtrHE79otw4Ln+M4i9I1ppIPZMYPJjtqcN2JfrIiZhla9Mv BO3DIoyPHnSQOZHhzIE5dpcAb8Z/ihdsX78kFdkPB7bZxpcLqwCt01LpnqPJCJjd2Yzm jptIlZK3TU+irek9Q5O5U4YlxYkg1No8NBBiBBbZXHig/kOKMFaua9PJP8SJlDCZW2w1 qXlA== X-Gm-Message-State: AA+aEWZ26GbQS+J2KZ2aLci/sUV+vv58wcB+Ws7Itfor6sqUgY2H3X20 WGgrbUKRVUMg0Je5y0LeamY= 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) 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> MIME-Version: 1.0 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: 10711695 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 D3EE114BD for ; Tue, 4 Dec 2018 12:19:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C58932A35A for ; Tue, 4 Dec 2018 12:19:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B5B972A3A1; Tue, 4 Dec 2018 12:19:45 +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=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 4D0B52A386 for ; Tue, 4 Dec 2018 12:19:44 +0000 (UTC) Received: (qmail 21582 invoked by uid 550); 4 Dec 2018 12:18:58 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 21524 invoked from network); 4 Dec 2018 12:18:58 -0000 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=EvM8x8mJe+3tenKxq4E9jl+/N2anQ6UCjx7vDI/LV7YUNbtG7087kecGBIoS0d+Gf4 UHLLQsbBtXA6d0/RWHQWP2ZqzTOBTheLuALk6RKW3vuokLNtcXD6Z5jiRa4RtjDHcMGx 6+h27oZj/aqdIBtXdkp9FABN+BCvYMQ2jwCdjSl76SViJXeKRwcY6pVkl70uv0uYjTDR Ekad//+Y6oQMAvLPrw852xakJVmhW+8iohi4Q0YkmatEXjK9AqvjySNON1styfA/DUTG 3UjFFZfrJIs9hXyvIXrn5BsPr9WNPQErhCbLfZLCVQFXq9psC3FnUcr3NIY9WCzUFMnj 1uyQ== X-Gm-Message-State: AA+aEWZQnBIHEBFHzgfhG/2bPB3NnG5k8754Ompao8pXuKkZzpPXHb9t w2OivJYVM0EDBEVqIEwmN2rdcTdLyaA= 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) 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> MIME-Version: 1.0 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: 10711697 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 279BB14BD for ; Tue, 4 Dec 2018 12:19:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 194FD2A3A1 for ; Tue, 4 Dec 2018 12:19:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0D7BF2A3AB; Tue, 4 Dec 2018 12:19:59 +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=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 6E1ED2A3A1 for ; Tue, 4 Dec 2018 12:19:57 +0000 (UTC) Received: (qmail 21733 invoked by uid 550); 4 Dec 2018 12:19:00 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 21650 invoked from network); 4 Dec 2018 12:18:59 -0000 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=IzDAw00QjYkUaiQFaHcUkQ0chybm0iCksBJmsAHKBRTWnlvaBZqmqH8VHRvK21umwY WKBp/Ir0gO5fYKfUXJ5Khez8GL5D0hOYlZbW6ZgmShE0MTUYKT/sG03UZYb1FQO8/ZaH FOz80I4j4qHaQor8adz/F5fDF/sJBfesJABbvjbPIuc3ALGaUExILZ63UxZVtG6+MPD7 /zqxP7LhFhHhrEJxAFli17IXSn5nu3xXaURi2tTHhWGVtH3y0zBh+Ti6yuxEy7hk7lNz y9urVXtdo0s0WAlutTr3uXhpef82psLL6A5rxmPDr7TIoItUQIxkxs7Zncf8An4kDqui nwAg== X-Gm-Message-State: AA+aEWbwE5HzwYyPBT/v+kBC2B96k6Y6U+F43elEVBuPA+yON9ljRiuf 9Xm5FPLFrLQ2N5d88E94Ge0= 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) 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> MIME-Version: 1.0 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; }