Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp3270426imj; Mon, 11 Feb 2019 17:32:30 -0800 (PST) X-Google-Smtp-Source: AHgI3Ibfpo4HBARHo+aAVlfDiwgnLjo7fJiPrlWEEjWbPrBDtPwc0+Qwbc5pqWgSNkKW0Yqh0Axp X-Received: by 2002:a17:902:d83:: with SMTP id 3mr1299533plv.43.1549935150694; Mon, 11 Feb 2019 17:32:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549935150; cv=none; d=google.com; s=arc-20160816; b=SoGhhneZ6f+QWTC0uEq3yYVCHmeKl5gJxsqiuPlmj7fleB4dsCMctjv6cumzGiBG+G Rhd5jvnihGzYBG8IEZfyNddlvx1lX4aJjWlxa/eBHskr/mVhy3HNs+f+tz2+ciP2BVpl nnOpjggbeXE3uVl1FfLKX9Zw9A+bq1omasrVEgslYdrAYNV+al2eMLsfD7FIXeCLrR1f mECZxicw0wkTajQdpeGmmDiGv/iCYlK0FnxPOpp3bCw3OStZopl2UrWDFaLsaLLSBLwc QjAsFyXPdiY349HImZUC+KGt25WTTI9lT9NpCAEZY3sfxZ5ZPBc1N74Ie0pCeAwjdc9B wqIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature; bh=se8DIhls4Mz2GTWYcHX5tB6yt7Dg/EP+UTRelAdQmeQ=; b=Sg0ttP3tTHcxY8HGv2/vPJ3xMnDPES+b7A/M0o6sp1UJiGVpM2jSxF1HoNoVe235fn 1/xxdB72abGjEuJ4nuxkrXjRBkKX0ICeUcuq4SYfcQpxqTtuoUkvumQP/RZre/yuMv1M /SEVHSsMfkJDp5Tp39WT0VBFBOdwkF2tj6GeQ4+p0Bf6eJIDp+L42surtilfxqwvaO5m jQ+HD1/O7vEDA+aqDlp2LDbrLjmhyK4vXliUiujh4DDcqnFbSE8c8Jy130IigtkBf8oq z4j+D8Y+gjGo7TEHeZzxhuqgYgS19Xp/5sA56IW5fa1RrTxDccXAvY/7hvXW8wB8IEY5 vg4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=FUpiRDkU; 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=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i12si10186328pgq.466.2019.02.11.17.32.13; Mon, 11 Feb 2019 17:32:30 -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; dkim=pass header.i=@gmail.com header.s=20161025 header.b=FUpiRDkU; 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=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726892AbfBLBb2 (ORCPT + 99 others); Mon, 11 Feb 2019 20:31:28 -0500 Received: from mail-qt1-f194.google.com ([209.85.160.194]:35853 "EHLO mail-qt1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726300AbfBLBb2 (ORCPT ); Mon, 11 Feb 2019 20:31:28 -0500 Received: by mail-qt1-f194.google.com with SMTP id r9so1162205qtt.3 for ; Mon, 11 Feb 2019 17:31:27 -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; bh=se8DIhls4Mz2GTWYcHX5tB6yt7Dg/EP+UTRelAdQmeQ=; b=FUpiRDkU87J/DOUJGnvx4h9zW/uT7VlJL3L8G8uUKIWPVZzxYUbFhiWtxc6lDUZzzh BPgBtWbP5ihwFjR+3L/mYwIuvGMKqTCNFhe+72MLzB2CRqUBmZVztSSdQtGQ4w3NDqpe BOthZzZPuRvlrQxhll8VnSFsVC1z3lGW+HEVM94QDD5p6VugKY82UVttw+DgIhMINBln uuFmSFTWAcSZzzfnsPfQbjQ0Qom/Nk1yRya0OPE0s6ZQHq26yCFWnlMoUW4QQw2L0ZxR I4ff3czYtyaorte54d9wd+NMTK/534utmwXpjZ27/OaoexZAu42YURCrf3GQM0AIbOe3 KWLg== 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; bh=se8DIhls4Mz2GTWYcHX5tB6yt7Dg/EP+UTRelAdQmeQ=; b=ipb191zslBWAJ9o12bi0RvJKgfl++RmcNgyjxSAW2qFgSsmTHXVEd7aW1K1gK+cm4J u9sgn6+ePOCaMUh8M0MswP+fWyUrOZOED36uquhLgDhomZKKGBcEs4xO4kJ0m8JmlvZ4 Ga5MxoSL3PDfAbk7Tg6UHnv55yQUKuizNmbFi1JxHb9iIU2hH1IfB0mG/hUaPVARJ4hL Xqs8rp7VRUxpIddGjBzeV2/VlcjjyIRXCH8Do5gXAz82sDMNCbMJGKfssO2aNym2XJyC PbR4xFREqGU8MVStwKZy2+nir2TYK8Ch6+N+xp2nCNN+llZKX288ew/r1c0j0kkexm1P PNuA== X-Gm-Message-State: AHQUAubn4o1bXwGRE215E4IlmMeBBKxUIOjguJaPkaSQgmAobyEnOMQP JIf+WVgsHqrN1wlfawoiuw== X-Received: by 2002:ac8:38fc:: with SMTP id g57mr909411qtc.39.1549935086872; Mon, 11 Feb 2019 17:31:26 -0800 (PST) Received: from gabell.redhat.com (209-6-122-159.s2973.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [209.6.122.159]) by smtp.gmail.com with ESMTPSA id g189sm13072950qkb.3.2019.02.11.17.31.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Feb 2019 17:31:25 -0800 (PST) From: Masayoshi Mizuma To: Borislav Petkov , "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , Baoquan He , x86@kernel.org Cc: Masayoshi Mizuma , Masayoshi Mizuma , linux-kernel@vger.kernel.org, Chao Fan Subject: [PATCH v2] x86/mm: Adjust the padding size for KASLR Date: Mon, 11 Feb 2019 20:31:18 -0500 Message-Id: <20190212013118.28203-1-msys.mizuma@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Masayoshi Mizuma The system sometimes crashes while memory hot-adding on KASLR enabled system. The crash happens because the regions pointed by kaslr_regions[].base are overwritten by the hot-added memory. It happens because of the padding size for kaslr_regions[].base isn't enough for the system whose physical memory layout has huge space for memory hotplug. kaslr_regions[].base points "actual installed memory size + padding" or higher address. So, if the "actual + padding" is lower address than the maximum memory address, which means the memory address reachable by memory hot-add, kaslr_regions[].base is destroyed by the overwritten. address ^ |------- maximum memory address (Hotplug) | ^ |------- kaslr_regions[0].base | Hotadd-able region | ^ | | | padding | | V V |------- actual memory address (Installed on boot) | Fix it by getting the maximum memory address from SRAT and store the value in boot_param, then set the padding size while kaslr initializing if the default padding size isn't enough. Signed-off-by: Masayoshi Mizuma --- Documentation/x86/zero-page.txt | 4 ++++ arch/x86/boot/compressed/acpi.c | 30 ++++++++++++++++++++------- arch/x86/include/uapi/asm/bootparam.h | 2 +- arch/x86/mm/kaslr.c | 29 +++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt index 68aed077f..6c107816c 100644 --- a/Documentation/x86/zero-page.txt +++ b/Documentation/x86/zero-page.txt @@ -15,6 +15,7 @@ Offset Proto Name Meaning 058/008 ALL tboot_addr Physical address of tboot shared page 060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information (struct ist_info) +078/010 ALL max_addr The possible maximum physical memory address[*]. 080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!! 090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!! 0A0/010 ALL sys_desc_table System description table (struct sys_desc_table), @@ -38,3 +39,6 @@ Offset Proto Name Meaning 2D0/A00 ALL e820_table E820 memory map table (array of struct e820_entry) D00/1EC ALL eddbuf EDD data (array of struct edd_info) + +[*]: max_addr shows the maximum memory address to be reachable by memory + hot-add. max_addr is set by parsing ACPI SRAT. diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c index c5a949335..3247c7153 100644 --- a/arch/x86/boot/compressed/acpi.c +++ b/arch/x86/boot/compressed/acpi.c @@ -272,6 +272,26 @@ static unsigned long get_acpi_srat_table(void) return 0; } +static void subtable_parse(struct acpi_subtable_header *sub_table, int *num, + unsigned long *max_addr) +{ + struct acpi_srat_mem_affinity *ma; + unsigned long addr; + + ma = (struct acpi_srat_mem_affinity *)sub_table; + if (ma->length) { + if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) { + addr = ma->base_address + ma->length; + if (addr > *max_addr) + *max_addr = addr; + } else { + immovable_mem[*num].start = ma->base_address; + immovable_mem[*num].size = ma->length; + (*num)++; + } + } +} + /** * count_immovable_mem_regions - Parse SRAT and cache the immovable * memory regions into the immovable_mem array. @@ -288,6 +308,7 @@ int count_immovable_mem_regions(void) struct acpi_subtable_header *sub_table; struct acpi_table_header *table_header; char arg[MAX_ACPI_ARG_LENGTH]; + unsigned long max_addr = 0; int num = 0; if (cmdline_find_option("acpi", arg, sizeof(arg)) == 3 && @@ -305,14 +326,8 @@ int count_immovable_mem_regions(void) while (table + sizeof(struct acpi_subtable_header) < table_end) { sub_table = (struct acpi_subtable_header *)table; if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) { - struct acpi_srat_mem_affinity *ma; - ma = (struct acpi_srat_mem_affinity *)sub_table; - if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) { - immovable_mem[num].start = ma->base_address; - immovable_mem[num].size = ma->length; - num++; - } + subtable_parse(sub_table, &num, &max_addr); if (num >= MAX_NUMNODES*2) { debug_putstr("Too many immovable memory regions, aborting.\n"); @@ -321,6 +336,7 @@ int count_immovable_mem_regions(void) } table += sub_table->length; } + boot_params->max_addr = max_addr; return num; } #endif /* CONFIG_RANDOMIZE_BASE && CONFIG_MEMORY_HOTREMOVE */ diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index 60733f137..d4882e171 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -156,7 +156,7 @@ struct boot_params { __u64 tboot_addr; /* 0x058 */ struct ist_info ist_info; /* 0x060 */ __u64 acpi_rsdp_addr; /* 0x070 */ - __u8 _pad3[8]; /* 0x078 */ + __u64 max_addr; /* 0x078 */ __u8 hd0_info[16]; /* obsolete! */ /* 0x080 */ __u8 hd1_info[16]; /* obsolete! */ /* 0x090 */ struct sys_desc_table sys_desc_table; /* obsolete! */ /* 0x0a0 */ diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c index 3f452ffed..f44ebfcb7 100644 --- a/arch/x86/mm/kaslr.c +++ b/arch/x86/mm/kaslr.c @@ -70,6 +70,33 @@ static inline bool kaslr_memory_enabled(void) return kaslr_enabled() && !IS_ENABLED(CONFIG_KASAN); } +/* + * The padding size should set to get for kaslr_regions[].base bigger address + * than the maximum memory address the system can have. + * kaslr_regions[].base points "actual size + padding" or higher address. + * If "actual size + padding" points the lower address than the maximum + * memory size, fix the padding size. + */ +static unsigned long __init kaslr_padding(void) +{ + unsigned long padding = CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING; +#ifdef CONFIG_MEMORY_HOTPLUG + unsigned long actual, maximum, base; + + if (!boot_params.max_addr) + goto out; + + actual = roundup(PFN_PHYS(max_pfn), 1UL << TB_SHIFT); + maximum = roundup(boot_params.max_addr, 1UL << TB_SHIFT); + base = actual + (padding << TB_SHIFT); + + if (maximum > base) + padding = (maximum - actual) >> TB_SHIFT; +out: +#endif + return padding; +} + /* Initialize base and padding for each memory region randomized with KASLR */ void __init kernel_randomize_memory(void) { @@ -103,7 +130,7 @@ void __init kernel_randomize_memory(void) */ BUG_ON(kaslr_regions[0].base != &page_offset_base); memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) + - CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING; + kaslr_padding(); /* Adapt phyiscal memory region size based on available memory */ if (memory_tb < kaslr_regions[0].size_tb) -- 2.20.1