From patchwork Wed Nov 16 14:39:38 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gengjia Chen X-Patchwork-Id: 9431761 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 284D060476 for ; Wed, 16 Nov 2016 14:39:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1869A28713 for ; Wed, 16 Nov 2016 14:39:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0CDFF2871C; Wed, 16 Nov 2016 14:39: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=-2.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, HTML_MESSAGE, RCVD_IN_DNSWL_MED, TRACKER_ID, T_DKIM_INVALID 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 11FD028713 for ; Wed, 16 Nov 2016 14:39:56 +0000 (UTC) Received: (qmail 24362 invoked by uid 550); 16 Nov 2016 14:39: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: Reply-To: kernel-hardening@lists.openwall.com Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 24329 invoked from network); 16 Nov 2016 14:39:51 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:cc; bh=zApFaGeuJNuVZA4o8Of1J91kumIGN3tpYqBCDomLAXk=; b=eINwRF42XQwy31DtLn42fmYaH7gu2WGGAtMp8V3SSmdWXvfXsSYv80T48WdhCFsy7v KnhbJe/BnnXZvtKDnIiKPZ+hbkbq5AkO7OV9+Jg7E9O9tf+ZfyuMfYXVpaCDkBym5TYJ VM5LfzMjG4qdCU1EOaMpJdNPCId1qrQF7UU3LVsburDVJ/hbZBFqOUBeBmz4XMc7xt/d 4QcyBazv7s52H8qqo2ldT/My6aWIfHfSiwT/pRZdzayIwfGwMEGXS2W0u+ent60bsTrJ wW1EBUuDhcKKeGx0ZZ9CKLQLo3TCTA9ifRWThrsGOl8w3C3szfYxrmKV9Oxr01ElnqWJ XlnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=zApFaGeuJNuVZA4o8Of1J91kumIGN3tpYqBCDomLAXk=; b=BcejLEeEp4FBiN3VPDDo8POgH0jM3QsZxvhnsui7EKFHk2Mwv1vH22QK4wZdCGC6sm GdM1aamRvOh0bZ9L1A9hJYU2uLMDtMMjHrGS1SBv4KVDRtnBSR6GDV6Byj5wm/oHTTKS 3+Imlc9Q4Ojt/uy8i4w21/SX88B6XkBxUwPQ0yqcMT0R62iYVAhkzimeHj+1tWRziI0e euBAr3JDYhBbmjVQfYp0EcZ8fUGZeY3+bqpGTcDWxG5IB8jXmJsjWGmQWhAU2W29T2Af G13DyaYzqHBono7IVh2yqEPZ62POBRnnvdLMTIa9AzhV0VY8cnmRTQ0LBtxpJc6HWWXx TmMw== X-Gm-Message-State: ABUngveC521eKET0CXTz0vF7rc35DS466MUTin5RnKTaYwSHk8Wy1Xp5TzSMGrSgiI0e9E8/HHNAa6muvGzWYA== X-Received: by 10.25.21.205 with SMTP id 74mr1219445lfv.138.1479307179688; Wed, 16 Nov 2016 06:39:39 -0800 (PST) MIME-Version: 1.0 From: Gengjia Chen Date: Wed, 16 Nov 2016 22:39:38 +0800 Message-ID: To: kernel-hardening@lists.openwall.com Cc: Kees Cook Subject: [kernel-hardening] patches for __write_rarely section X-Virus-Scanned: ClamAV using ClamSMTP Hello kees and everyone : This email introduces two patches. Patch 1 introduce the write-rarely memory section for those kernel objects which are read only mostly but need to be written to sometimes. Patch 2 introduce two helper functions (mark_wrdata_rw/ mark_wrdata_ro) to make __write_rarely memory section writable or unwritable. They play like the pax_open_kernel/ pax_close_kernel functions in grsecurity patch.Right now this only been implemented on arm32. These two patches were based on the work by PaxTeam and Grsecurity. These two patched were based on https://github.com/torvalds/linux.git : 27bcd37e0240bbe33f0efe244b5aad52104115b3 By the way, I am a new recruit for kernel coding so I hope that someone can review these patches and tell me what to do next. Also, I am working on the implement of mark_wrdata_rw/mark_wrdata_ro on aarch64, any advice about that would be appreciated. * mapping to be mapped at. This is particularly important for ==== patch 1 ===== From 7ee1ed5a723723112167ca8603f4e2945d133b33 Mon Sep 17 00:00:00 2001 From: chengengjia Date: Wed, 16 Nov 2016 21:46:49 +0800 Subject: [PATCH] arch: introduce write-rarely memory section This introduces __write_rarely section as a way to mark those memory that read only in most case, but also need to be written to sometimes. Signed-off-by: chengengjia --- include/asm-generic/vmlinux.lds.h | 9 +++++++++ include/linux/cache.h | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 3074796..684bcf2 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -263,6 +263,14 @@ #endif /* + * Allow architectures to handle write_rarely data on their + * own by defining an empty WRITE_RARELY_DATA. + */ +#ifndef WRITE_RARELY_DATA +#define WRITE_RARELY_DATA *(.data..write_rarely) +#endif + +/* * Read only Data */ #define RO_DATA_SECTION(align) \ @@ -271,6 +279,7 @@ VMLINUX_SYMBOL(__start_rodata) = .; \ *(.rodata) *(.rodata.*) \ RO_AFTER_INIT_DATA /* Read only after init */ \ + WRITE_RARELY_DATA /* write rarely*/ \ *(__vermagic) /* Kernel version magic */ \ . = ALIGN(8); \ VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .; \ diff --git a/include/linux/cache.h b/include/linux/cache.h index 1be04f8..d2c30cd 100644 --- a/include/linux/cache.h +++ b/include/linux/cache.h @@ -30,6 +30,15 @@ #define __ro_after_init __attribute__((__section__(".data..ro_after_init"))) #endif +/* + * __write_rarely is used to mark things that are read-only mostly but need to be + * written to sometimes. To write to __write_rarely variables, mark_wrdata_rw() + * need to be called, after write, mark_wrdata_ro() should be called. + */ +#ifndef __write_rarely +#define __write_rarely __attribute__((__section__(".data..write_rarely"))) +#endif + #ifndef ____cacheline_aligned #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) #endif -- 1.9.1 ==== patch 2 ===== From 0472f3f14532577a1963d517da8a0edfe1d99375 Mon Sep 17 00:00:00 2001 From: chengengjia Date: Wed, 16 Nov 2016 22:16:43 +0800 Subject: [PATCH] arch: arm: add mark_wrdata_rw/mark_wrdata_ro functions This introduces mark_wrdata_rw/mark_wrdata_ro to mark __write_rarely section writable/unwritable. Based on work by PaxTeam and Grsecurity. Signed-off-by: chengengjia --- arch/arm/include/asm/domain.h | 14 ++++++++++++++ arch/arm/include/asm/pgtable.h | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index 99d9f63..01f18a5 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h @@ -54,6 +54,10 @@ #else #define DOMAIN_MANAGER 1 #endif +#ifdef CONFIG_DEBUG_RODATA +#define DOMAIN_OPENKERN 3 +#endif + #define domain_mask(dom) ((3) << (2 * (dom))) #define domain_val(dom,type) ((type) << (2 * (dom))) @@ -124,6 +128,16 @@ static inline void set_domain(unsigned val) set_domain(domain); \ } while (0) +#elif defined(CONFIG_DEBUG_RODATA) +#define modify_domain(dom,type) \ + do { \ + struct thread_info *thread = current_thread_info(); \ + unsigned int domain = get_domain(); \ + domain &= ~domain_mask(dom); \ + domain = domain | domain_val(dom, type); \ + thread->cpu_domain = domain; \ + set_domain(domain); \ + } while (0) #else static inline void modify_domain(unsigned dom, unsigned type) { } #endif diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a8d656d..5e6f553 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -56,6 +56,44 @@ #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) +#ifdef CONFIG_DEBUG_RODATA +#include +#include +#include + +static inline int test_domain(int domain, int domaintype) +{ + return ((current_thread_info()->cpu_domain) & domain_val(domain, 3)) + == domain_val(domain, domaintype); +} + +static inline unsigned long mark_wrdata_rw(void) { +#ifdef CONFIG_ARM_LPAE + /* TODO */ +#else + preempt_disable(); + BUG_ON(test_domain(DOMAIN_KERNEL, DOMAIN_OPENKERN)); + modify_domain(DOMAIN_KERNEL, DOMAIN_OPENKERN); +#endif + return 0; +} + +static inline unsigned long mark_wrdata_ro(void) { +#ifdef CONFIG_ARM_LPAE + /* TODO */ +#else + BUG_ON(test_domain(DOMAIN_KERNEL, DOMAIN_MANAGER)); + modify_domain(DOMAIN_KERNEL, DOMAIN_MANAGER); + preempt_enable_no_resched(); +#endif + return 0; +} +#else +static inline unsigned long mark_wrdata_rw(void) { return 0; } +static inline unsigned long mark_wrdata_ro(void) { return 0; } +#endif + + /* * This is the lowest virtual address we can permit any user space