Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2713629imu; Sat, 10 Nov 2018 22:37:19 -0800 (PST) X-Google-Smtp-Source: AJdET5e9ybgvKe0+DHjhuzkfYvRg2td7C/QcawJBuKJKMPJUuW5yzpSUwjTSDUs+eCixMbJr6Csa X-Received: by 2002:a17:902:784c:: with SMTP id e12-v6mr15260742pln.185.1541918239646; Sat, 10 Nov 2018 22:37:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541918239; cv=none; d=google.com; s=arc-20160816; b=sf+ZorL2YQfs87nfVAfPOdSXGo+JEbUX98KpxxJU3DDWzmEKPwLsVyHb2ABWkSwBWB pECXiN/avv8bnbZK27/MgzyEUvJNOPpabwOUDDGvgqGe7BRY8TehMmVawCSJrdKSQr/X ApdRDLCVv96lZ3ny/yRNS87tGlj7A4M5qfAIo8cRljrVlNzTniwxdpt4uS9/6JOvI1Ni 8Bb0a7v8U3dFuIGSKjIqKcW74PsX9pGOeYit4Rrf3/0xoTyad3zmf/Hvd7fHJ3NU44YJ /yg+iAwXKYJxGyBSdVnleWPps7Zb/g90R/EsTTI2NqXxD/PAGhCX+sa80soETtgW2YSo eFRw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=AxLt6P5h90cDFAP6UYNB2xHlHBlWgdvvG4Hn4pPm71g=; b=lb2wo777roTn5+Gqe+JRJsxcjXrKu30wpgs1WEkD0kEABp6mlFbnDw67LnmubWH+3x n98k31JdrfnE4TaCr3/5i3K8jdKRDLqhTEKN4q8LlkQNb5cYiAWWgmruDzpRw8v+QLED T3KzOIl3btLCXpo1nReC4G8e1AebFTmJNhaJ2jj1Kyh3lBHifgLJvGRWnO8aOetpnYzc rMrZEykPYYiswLHlK26qs8RwEVb3Y+4LIV6nBLsVoUonq2lohnSyAoVPqw7nmjihA09D 6aASvwwYk0XCmzrXC71Tgzwml6tcvGUXxPocTu2xGyw6G1jl1wwgvv3yWEw3G06nlm5y cJ0w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=vmware.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s132-v6si12876906pgs.492.2018.11.10.22.36.43; Sat, 10 Nov 2018 22:37:19 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=vmware.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727747AbeKKQXG (ORCPT + 99 others); Sun, 11 Nov 2018 11:23:06 -0500 Received: from ex13-edg-ou-001.vmware.com ([208.91.0.189]:25452 "EHLO EX13-EDG-OU-001.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727568AbeKKQXG (ORCPT ); Sun, 11 Nov 2018 11:23:06 -0500 Received: from sc9-mailhost3.vmware.com (10.113.161.73) by EX13-EDG-OU-001.vmware.com (10.113.208.155) with Microsoft SMTP Server id 15.0.1156.6; Sat, 10 Nov 2018 22:35:01 -0800 Received: from sc2-haas01-esx0118.eng.vmware.com (sc2-haas01-esx0118.eng.vmware.com [10.172.44.118]) by sc9-mailhost3.vmware.com (Postfix) with ESMTP id 5D65E40456; Sat, 10 Nov 2018 22:35:24 -0800 (PST) From: Nadav Amit To: Ingo Molnar CC: , , "H. Peter Anvin" , Thomas Gleixner , Borislav Petkov , Dave Hansen , Nadav Amit , Kees Cook , Peter Zijlstra , Dave Hansen Subject: [PATCH v4 05/10] x86/alternative: initializing temporary mm for patching Date: Sat, 10 Nov 2018 15:17:27 -0800 Message-ID: <20181110231732.15060-6-namit@vmware.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181110231732.15060-1-namit@vmware.com> References: <20181110231732.15060-1-namit@vmware.com> MIME-Version: 1.0 Content-Type: text/plain Received-SPF: None (EX13-EDG-OU-001.vmware.com: namit@vmware.com does not designate permitted sender hosts) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To prevent improper use of the PTEs that are used for text patching, we want to use a temporary mm struct. We initailize it by copying the init mm. The address that will be used for patching is taken from the lower area that is usually used for the task memory. Doing so prevents the need to frequently synchronize the temporary-mm (e.g., when BPF programs are installed), since different PGDs are used for the task memory. Finally, we randomize the address of the PTEs to harden against exploits that use these PTEs. Cc: Kees Cook Cc: Peter Zijlstra Cc: Dave Hansen Reviewed-by: Masami Hiramatsu Tested-by: Masami Hiramatsu Suggested-by: Andy Lutomirski Signed-off-by: Nadav Amit --- arch/x86/include/asm/pgtable.h | 3 +++ arch/x86/include/asm/text-patching.h | 2 ++ arch/x86/kernel/alternative.c | 3 +++ arch/x86/mm/init_64.c | 39 ++++++++++++++++++++++++++++ init/main.c | 3 +++ 5 files changed, 50 insertions(+) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 40616e805292..e8f630d9a2ed 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1021,6 +1021,9 @@ static inline void __meminit init_trampoline_default(void) /* Default trampoline pgd value */ trampoline_pgd_entry = init_top_pgt[pgd_index(__PAGE_OFFSET)]; } + +void __init poking_init(void); + # ifdef CONFIG_RANDOMIZE_MEMORY void __meminit init_trampoline(void); # else diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h index 5a2600370763..e5716ef9a721 100644 --- a/arch/x86/include/asm/text-patching.h +++ b/arch/x86/include/asm/text-patching.h @@ -39,5 +39,7 @@ extern int text_poke_kgdb(void *addr, const void *opcode, size_t len); extern int poke_int3_handler(struct pt_regs *regs); extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); extern int after_bootmem; +extern __ro_after_init struct mm_struct *poking_mm; +extern __ro_after_init unsigned long poking_addr; #endif /* _ASM_X86_TEXT_PATCHING_H */ diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ebe9210dc92e..d3ae5c26e5a0 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -678,6 +678,9 @@ void *__init_or_module text_poke_early(void *addr, const void *opcode, return addr; } +__ro_after_init struct mm_struct *poking_mm; +__ro_after_init unsigned long poking_addr; + static int __text_poke(void *addr, const void *opcode, size_t len) { unsigned long flags; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 5fab264948c2..56d56d77aa66 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "mm_internal.h" @@ -1388,6 +1389,44 @@ unsigned long memory_block_size_bytes(void) return memory_block_size_probed; } +/* + * Initialize an mm_struct to be used during poking and a pointer to be used + * during patching. If anything fails during initialization, poking will be done + * using the fixmap, which is unsafe, so warn the user about it. + */ +void __init poking_init(void) +{ + spinlock_t *ptl; + pte_t *ptep; + + poking_mm = copy_init_mm(); + if (!poking_mm) { + pr_err("x86/mm: error setting a separate poking address space"); + return; + } + + /* + * Randomize the poking address, but make sure that the following page + * will be mapped at the same PMD. We need 2 pages, so find space for 3, + * and adjust the address if the PMD ends after the first one. + */ + poking_addr = TASK_UNMAPPED_BASE + + (kaslr_get_random_long("Poking") & PAGE_MASK) % + (TASK_SIZE - TASK_UNMAPPED_BASE - 3 * PAGE_SIZE); + + if (((poking_addr + PAGE_SIZE) & ~PMD_MASK) == 0) + poking_addr += PAGE_SIZE; + + /* + * We need to trigger the allocation of the page-tables that will be + * needed for poking now. Later, poking may be performed in an atomic + * section, which might cause allocation to fail. + */ + ptep = get_locked_pte(poking_mm, poking_addr, &ptl); + if (!WARN_ON(!ptep)) + pte_unmap_unlock(ptep, ptl); +} + #ifdef CONFIG_SPARSEMEM_VMEMMAP /* * Initialise the sparsemem vmemmap using huge-pages at the PMD level. diff --git a/init/main.c b/init/main.c index ee147103ba1b..a461150adfb1 100644 --- a/init/main.c +++ b/init/main.c @@ -497,6 +497,8 @@ void __init __weak thread_stack_cache_init(void) void __init __weak mem_encrypt_init(void) { } +void __init __weak poking_init(void) { } + bool initcall_debug; core_param(initcall_debug, initcall_debug, bool, 0644); @@ -731,6 +733,7 @@ asmlinkage __visible void __init start_kernel(void) taskstats_init_early(); delayacct_init(); + poking_init(); check_bugs(); acpi_subsystem_init(); -- 2.17.1