From patchwork Sat Feb 11 20:23:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 9568151 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 B4E6D6043D for ; Sat, 11 Feb 2017 20:24:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A50BA284F6 for ; Sat, 11 Feb 2017 20:24:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 99AC728567; Sat, 11 Feb 2017 20:24:21 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,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 BE6AD284F6 for ; Sat, 11 Feb 2017 20:24:20 +0000 (UTC) Received: (qmail 19700 invoked by uid 550); 11 Feb 2017 20:24:14 -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 19478 invoked from network); 11 Feb 2017 20:24:11 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Puf3zBBBZUfv479ywJAO5i6z4Bwj+6QfHfc//SHuuJ8=; b=A0WXJo8zR/J1/K8iCz6hwGqKaFXGiWh0D3RF1/m3s+IKqR0vzkoTIQ+sLIVptqoRzF QGOSXHEQSsQQPK0Z8valsUvVvdnYfvFruf2bQgzI2YyYkDv3qIYO1/Qg1u93a6YYeymG RObEnPMQKc8+g1TI1L+Kl9FMy/w2xOVt7gGoQ= 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; bh=Puf3zBBBZUfv479ywJAO5i6z4Bwj+6QfHfc//SHuuJ8=; b=snxA8wNGiA4/zY0Aroz6QVjMGQbZpsC7DE6DsDfWYI4NsdbvhfIM4JYu2CRMjHLyaT 40rJRVEszN5uw1tCLvaYG2g4MQA7dJUH3DBc7yDJD9pHdOka7bgAHD/l3gLqXW5qdA5s X6k8A2DXt/Zzge3qAzWoTsLdRv0j4SehO+DgoiaufG7nIaQiBvcTQldunSjXRJdSkp5S ErtbaEAupfW5lE2RzWcuRTAVAJ2j7aP2PI1EjWKf7arm8iXri+KgvdoSrsIfknVVk5H2 0z+2T0Nq3MXM3ep6wC473rQ4r5Y6f1xVhGaFAHn1vUc3TkfA/g1NWdwWyR/qFqBBl8qK bnMQ== X-Gm-Message-State: AMke39kD4bpQpo7kxmwDnin3+DOGLxeBdSrSJvs8JmSglUEqm1Jt9wK2u9H84eZyF0jrssOf X-Received: by 10.223.131.99 with SMTP id 90mr13061019wrd.146.1486844639523; Sat, 11 Feb 2017 12:23:59 -0800 (PST) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, mark.rutland@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, labbott@fedoraproject.org Cc: kvmarm@lists.cs.columbia.edu, marc.zyngier@arm.com, andre.przywara@arm.com, Suzuki.Poulose@arm.com, james.morse@arm.com, keescook@chromium.org, kernel-hardening@lists.openwall.com, Ard Biesheuvel Date: Sat, 11 Feb 2017 20:23:04 +0000 Message-Id: <1486844586-26135-4-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486844586-26135-1-git-send-email-ard.biesheuvel@linaro.org> References: <1486844586-26135-1-git-send-email-ard.biesheuvel@linaro.org> Subject: [kernel-hardening] [PATCH v2 3/5] arm64: alternatives: apply boot time fixups via the linear mapping X-Virus-Scanned: ClamAV using ClamSMTP One important rule of thumb when desiging a secure software system is that memory should never be writable and executable at the same time. We mostly adhere to this rule in the kernel, except at boot time, when regions may be mapped RWX until after we are done applying alternatives or making other one-off changes. For the alternative patching, we can improve the situation by applying the fixups via the linear mapping, which is never mapped with executable permissions. So map the linear alias of .text with RW- permissions initially, and remove the write permissions as soon as alternative patching has completed. Reviewed-by: Laura Abbott Signed-off-by: Ard Biesheuvel Reviewed-by: Mark Rutland Tested-by: Mark Rutland --- arch/arm64/include/asm/mmu.h | 1 + arch/arm64/kernel/alternative.c | 2 +- arch/arm64/kernel/smp.c | 1 + arch/arm64/mm/mmu.c | 22 +++++++++++++++----- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 47619411f0ff..5468c834b072 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -37,5 +37,6 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot, bool page_mappings_only); extern void *fixmap_remap_fdt(phys_addr_t dt_phys); +extern void mark_linear_text_alias_ro(void); #endif diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c index 06d650f61da7..8cee29d9bc07 100644 --- a/arch/arm64/kernel/alternative.c +++ b/arch/arm64/kernel/alternative.c @@ -128,7 +128,7 @@ static void __apply_alternatives(void *alt_region) for (i = 0; i < nr_inst; i++) { insn = get_alt_insn(alt, origptr + i, replptr + i); - *(origptr + i) = cpu_to_le32(insn); + ((u32 *)lm_alias(origptr))[i] = cpu_to_le32(insn); } flush_icache_range((uintptr_t)origptr, diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a8ec5da530af..d6307e311a10 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -432,6 +432,7 @@ void __init smp_cpus_done(unsigned int max_cpus) setup_cpu_features(); hyp_mode_check(); apply_alternatives_all(); + mark_linear_text_alias_ro(); } void __init smp_prepare_boot_cpu(void) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 9e0ec1a8cd3b..7ed981c7f4c0 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -398,16 +398,28 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end debug_pagealloc_enabled()); /* - * Map the linear alias of the [_text, __init_begin) interval as - * read-only/non-executable. This makes the contents of the - * region accessible to subsystems such as hibernate, but - * protects it from inadvertent modification or execution. + * Map the linear alias of the [_text, __init_begin) interval + * as non-executable now, and remove the write permission in + * mark_linear_text_alias_ro() below (which will be called after + * alternative patching has completed). This makes the contents + * of the region accessible to subsystems such as hibernate, + * but protects it from inadvertent modification or execution. */ __create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start), - kernel_end - kernel_start, PAGE_KERNEL_RO, + kernel_end - kernel_start, PAGE_KERNEL, early_pgtable_alloc, debug_pagealloc_enabled()); } +void __init mark_linear_text_alias_ro(void) +{ + /* + * Remove the write permissions from the linear alias of .text/.rodata + */ + create_mapping_late(__pa_symbol(_text), (unsigned long)lm_alias(_text), + (unsigned long)__init_begin - (unsigned long)_text, + PAGE_KERNEL_RO); +} + static void __init map_mem(pgd_t *pgd) { struct memblock_region *reg;