From patchwork Thu Mar 30 11:49:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kirill A. Shutemov" X-Patchwork-Id: 13194070 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DD8AC761A6 for ; Thu, 30 Mar 2023 11:50:41 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7E3986B007D; Thu, 30 Mar 2023 07:50:37 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6F5856B007E; Thu, 30 Mar 2023 07:50:37 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 570326B0080; Thu, 30 Mar 2023 07:50:37 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 498626B007D for ; Thu, 30 Mar 2023 07:50:37 -0400 (EDT) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 26144C0EB9 for ; Thu, 30 Mar 2023 11:50:37 +0000 (UTC) X-FDA: 80625397314.25.99DB0E3 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by imf03.hostedemail.com (Postfix) with ESMTP id E36DE20013 for ; Thu, 30 Mar 2023 11:50:34 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=cMDkRYFL; dmarc=pass (policy=none) header.from=intel.com; spf=none (imf03.hostedemail.com: domain of kirill.shutemov@linux.intel.com has no SPF policy when checking 134.134.136.24) smtp.mailfrom=kirill.shutemov@linux.intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1680177035; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=sJ0jWyXBmb0hmPD/qh9m7QTKFLzmCPwA0IjlFxXM8+0=; b=f/8OQvKtA/trFt4OOD1/EFPwe97UeM+kQcCZGS6We/nNXar7kf7A78f8j6yJDVT56RuO2T 0fibG9Ii1l11vYZ6fV1uO2xYwl2ORGqbDanxb1F6YV2L9VRsRWeQIa8vMWj/NU8zwbj7QJ HT2I8qUX02WHDdq68NZn0pjZ4+UQ2w0= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=cMDkRYFL; dmarc=pass (policy=none) header.from=intel.com; spf=none (imf03.hostedemail.com: domain of kirill.shutemov@linux.intel.com has no SPF policy when checking 134.134.136.24) smtp.mailfrom=kirill.shutemov@linux.intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1680177035; a=rsa-sha256; cv=none; b=BiBlsYwCO0oRmdrB9klTyB9sg8A8APOmXXWEX99kZH8H+bBE/d46VtYR8JVu5RHk8siqQ4 cw/6I2vll5079W+gu6SQXyME2vgUcdfs+JbDZSV9cCmfWeTa5P4kySAgyocIrKss1WpLAj yj0lBBUZRf9fQLHTQbykcW4ZKFEmTUs= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1680177035; x=1711713035; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=d4/KfDFRLyY7sMUS/zMPpAEAi7ubl+P+2mX+6hzyiNg=; b=cMDkRYFLqg5j606YT775ZoLz4l/T6gZVOcTFhrIACwt3eFvp9jWLvAGz DEiC7OktV7/z9gBO4z4A7wiysxG6xZE7NMWOfpvvoBve77zGGqcllqrMv HjS7sZDiSSOUHMw5TLIHzMxNnIUdA3AkkRyCNvC4WTcdvCDa5rS45ZF0Y WZ3xaRTA7s61ad4QMiR7NJADGqqK47YvYH2isCe/xPnhrLigiITPVT+z2 MBdNNVZeLoQ9O3wGRT4XtIFdN/XPlKF6qqQ1bHns3D/hbsbad7HS2k09H 9hoFjFrQy8D4jZuKLk+h4HJJ9+piF4NKvqIlc0pgXs5uhpeuepI43QmtZ w==; X-IronPort-AV: E=McAfee;i="6600,9927,10664"; a="342756780" X-IronPort-AV: E=Sophos;i="5.98,303,1673942400"; d="scan'208";a="342756780" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Mar 2023 04:50:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10664"; a="634856504" X-IronPort-AV: E=Sophos;i="5.98,303,1673942400"; d="scan'208";a="634856504" Received: from ngreburx-mobl.ger.corp.intel.com (HELO box.shutemov.name) ([10.251.209.91]) by orsmga003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Mar 2023 04:50:16 -0700 Received: by box.shutemov.name (Postfix, from userid 1000) id 3E8F41044F3; Thu, 30 Mar 2023 14:50:00 +0300 (+03) From: "Kirill A. Shutemov" To: Borislav Petkov , Andy Lutomirski , Sean Christopherson , Andrew Morton , Joerg Roedel , Ard Biesheuvel Cc: Andi Kleen , Kuppuswamy Sathyanarayanan , David Rientjes , Vlastimil Babka , Tom Lendacky , Thomas Gleixner , Peter Zijlstra , Paolo Bonzini , Ingo Molnar , Dario Faggioli , Dave Hansen , Mike Rapoport , David Hildenbrand , Mel Gorman , marcelo.cerri@canonical.com, tim.gardner@canonical.com, khalid.elmously@canonical.com, philip.cox@canonical.com, aarcange@redhat.com, peterx@redhat.com, x86@kernel.org, linux-mm@kvack.org, linux-coco@lists.linux.dev, linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org, "Kirill A. Shutemov" Subject: [PATCHv9 08/14] x86/boot/compressed: Handle unaccepted memory Date: Thu, 30 Mar 2023 14:49:50 +0300 Message-Id: <20230330114956.20342-9-kirill.shutemov@linux.intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230330114956.20342-1-kirill.shutemov@linux.intel.com> References: <20230330114956.20342-1-kirill.shutemov@linux.intel.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: E36DE20013 X-Rspamd-Server: rspam09 X-Rspam-User: X-Stat-Signature: r99fcxxayqqhyfwr8j6a14exkpocthe9 X-HE-Tag: 1680177034-372919 X-HE-Meta: U2FsdGVkX1+CqChN7bqNWmrtmBxr8sHUacCmyJanLvwY8vkMznzyl/wNunW6xLC+yJhTD/MIyRKQ4CSLldzGdpFF7GP6ugrqIJmofZ55k0dVOTVo/HOp0snhOl9TESg1rbfS7Cu5W38IqOFr6Qv9ByaIPiFwrZeMEMx/3R5oEfuualYLuJS70zDZY7ES7eVboH2ddHimQc+krW2IxpftJHaWAsOrXpa5ttAQwWXu1PE2tjj0lRov8loY+9Lx1Kp2z8SEkiPqeYRWIVPoVC0ghrzGZF8TyrBukkOX2eOGKmxD22wbupR3nXY+n3HZTj+XLT9nmu4R0n1pcORY5rg+pnqD/nEGSVD2Yvrh7ymbJ+xiJkHMncbKgx9wSysZhVr/dQAW7MU3yoalKPu1lYJyat5KRZqXfTiWQlJnncYBX2auVYAglXv6HxEWTM7EwIniWjT/b3o5sueeRYki5zI+aMjrX/arkuUu3x3TpiBXhF21kIgbvoKbaklbOkWuVcwkRe0kIDbbmOKQCrU1sWIRzmTdvQIOOYIHL25j5UHfgytNlZjCLDzyWbk6nRLMbQIygBn4lCRCqemgu7nEB9Q4K9p3nRzPei5V8GhCFjgz8w3uIimGyQ1sQXwdIxlLV7+ivVDoOCcxLCST22yysmyqMZOQpvD55VpUmtwv4A8ci/AkmAWQS8PeU/M3Y7ppPBOSAv4bmga5GheWMpb9SwWsPyebh1kKo5jOsvTLw8sY7zBEc9co39/kXWR+AivIu//jj24e2BgpmBrerfjx9DV4vuy6mlHTFjypdvkQDU5RAC4+BSGV8cOZz5Hferz3GxbfiUzXC3WPUq7G37UE+G4VkvGsP412FvTGlcWCcG66iLvjkYFFUFeUuWhF1z2a3f1SfjneNZ9bSTQ92tBo7f/yb7jV5CkQCoyZ85NgxnEtvSgpkEpALvonBm+8KSKE0POGu0k6NxvyWD/sako4+xd gwcI6G7K mw3bJNp9zAZz6xWB+Pje7Q31Tu5lKWKOi6o3tXCHKJxLddIBZnzVzmhNqN+sy4N1GO2HyBQHoKDfZa2+p6szbPculr7eJr7nm9UDXotu+mUD3dP9JLWPJovP6yY845KexykjvntJ5LR4kGAhTGuTj5+EwFwWD++F5u335 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: The firmware will pre-accept the memory used to run the stub. But, the stub is responsible for accepting the memory into which it decompresses the main kernel. Accept memory just before decompression starts. The stub is also responsible for choosing a physical address in which to place the decompressed kernel image. The KASLR mechanism will randomize this physical address. Since the unaccepted memory region is relatively small, KASLR would be quite ineffective if it only used the pre-accepted area (EFI_CONVENTIONAL_MEMORY). Ensure that KASLR randomizes among the entire physical address space by also including EFI_UNACCEPTED_MEMORY. Signed-off-by: Kirill A. Shutemov --- arch/x86/boot/compressed/Makefile | 2 +- arch/x86/boot/compressed/efi.h | 1 + arch/x86/boot/compressed/kaslr.c | 35 ++++++++++++++++-------- arch/x86/boot/compressed/mem.c | 18 ++++++++++++ arch/x86/boot/compressed/misc.c | 6 ++++ arch/x86/boot/compressed/misc.h | 6 ++++ arch/x86/include/asm/unaccepted_memory.h | 2 ++ 7 files changed, 57 insertions(+), 13 deletions(-) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index f62c02348f9a..74f7adee46ad 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -107,7 +107,7 @@ endif vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o -vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/bitmap.o $(obj)/mem.o +vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/bitmap.o $(obj)/find.o $(obj)/mem.o vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o diff --git a/arch/x86/boot/compressed/efi.h b/arch/x86/boot/compressed/efi.h index 7db2f41b54cd..cf475243b6d5 100644 --- a/arch/x86/boot/compressed/efi.h +++ b/arch/x86/boot/compressed/efi.h @@ -32,6 +32,7 @@ typedef struct { } efi_table_hdr_t; #define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNACCEPTED_MEMORY 15 #define EFI_MEMORY_MORE_RELIABLE \ ((u64)0x0000000000010000ULL) /* higher reliability */ diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 454757fbdfe5..749f0fe7e446 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -672,6 +672,28 @@ static bool process_mem_region(struct mem_vector *region, } #ifdef CONFIG_EFI + +/* + * Only EFI_CONVENTIONAL_MEMORY and EFI_UNACCEPTED_MEMORY (if supported) are + * guaranteed to be free. + * + * It is more conservative in picking free memory than the EFI spec allows: + * + * According to the spec, EFI_BOOT_SERVICES_{CODE|DATA} are also free memory + * and thus available to place the kernel image into, but in practice there's + * firmware where using that memory leads to crashes. + */ +static inline bool memory_type_is_free(efi_memory_desc_t *md) +{ + if (md->type == EFI_CONVENTIONAL_MEMORY) + return true; + + if (md->type == EFI_UNACCEPTED_MEMORY) + return IS_ENABLED(CONFIG_UNACCEPTED_MEMORY); + + return false; +} + /* * Returns true if we processed the EFI memmap, which we prefer over the E820 * table if it is available. @@ -716,18 +738,7 @@ process_efi_entries(unsigned long minimum, unsigned long image_size) for (i = 0; i < nr_desc; i++) { md = efi_early_memdesc_ptr(pmap, e->efi_memdesc_size, i); - /* - * Here we are more conservative in picking free memory than - * the EFI spec allows: - * - * According to the spec, EFI_BOOT_SERVICES_{CODE|DATA} are also - * free memory and thus available to place the kernel image into, - * but in practice there's firmware where using that memory leads - * to crashes. - * - * Only EFI_CONVENTIONAL_MEMORY is guaranteed to be free. - */ - if (md->type != EFI_CONVENTIONAL_MEMORY) + if (!memory_type_is_free(md)) continue; if (efi_soft_reserve_enabled() && diff --git a/arch/x86/boot/compressed/mem.c b/arch/x86/boot/compressed/mem.c index 6b15a0ed8b54..de858a5180b6 100644 --- a/arch/x86/boot/compressed/mem.c +++ b/arch/x86/boot/compressed/mem.c @@ -3,12 +3,15 @@ #include "../cpuflags.h" #include "bitmap.h" #include "error.h" +#include "find.h" #include "math.h" #define PMD_SHIFT 21 #define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE - 1)) +extern struct boot_params *boot_params; + static inline void __accept_memory(phys_addr_t start, phys_addr_t end) { /* Platform-specific memory-acceptance call goes here */ @@ -71,3 +74,18 @@ void process_unaccepted_memory(struct boot_params *params, u64 start, u64 end) bitmap_set((unsigned long *)params->unaccepted_memory, start / PMD_SIZE, (end - start) / PMD_SIZE); } + +void accept_memory(phys_addr_t start, phys_addr_t end) +{ + unsigned long range_start, range_end; + unsigned long *bitmap, bitmap_size; + + bitmap = (unsigned long *)boot_params->unaccepted_memory; + range_start = start / PMD_SIZE; + bitmap_size = DIV_ROUND_UP(end, PMD_SIZE); + + for_each_set_bitrange_from(range_start, range_end, bitmap, bitmap_size) { + __accept_memory(range_start * PMD_SIZE, range_end * PMD_SIZE); + bitmap_clear(bitmap, range_start, range_end - range_start); + } +} diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 014ff222bf4b..186bfd53e042 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -455,6 +455,12 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, #endif debug_putstr("\nDecompressing Linux... "); + + if (boot_params->unaccepted_memory) { + debug_putstr("Accepting memory... "); + accept_memory(__pa(output), __pa(output) + needed_size); + } + __decompress(input_data, input_len, NULL, NULL, output, output_len, NULL, error); entry_offset = parse_elf(output); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 2f155a0e3041..9663d1839f54 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -247,4 +247,10 @@ static inline unsigned long efi_find_vendor_table(struct boot_params *bp, } #endif /* CONFIG_EFI */ +#ifdef CONFIG_UNACCEPTED_MEMORY +void accept_memory(phys_addr_t start, phys_addr_t end); +#else +static inline void accept_memory(phys_addr_t start, phys_addr_t end) {} +#endif + #endif /* BOOT_COMPRESSED_MISC_H */ diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h index df0736d32858..41fbfc798100 100644 --- a/arch/x86/include/asm/unaccepted_memory.h +++ b/arch/x86/include/asm/unaccepted_memory.h @@ -7,4 +7,6 @@ struct boot_params; void process_unaccepted_memory(struct boot_params *params, u64 start, u64 num); +void accept_memory(phys_addr_t start, phys_addr_t end); + #endif