From: Greg Kroah-Hartman Date: Tue, 2 Jul 2024 09:56:30 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v4.19.317~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23199351549ef4f72e1f95352e757e4e58d3a5d6;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: efi-memmap-move-manipulation-routines-into-x86-arch-tree.patch efi-x86-free-efi-memory-map-only-when-installing-a-new-one.patch efi-xen-set-efi_paravirt-for-xen-dom0-boot-on-all-architectures.patch gfs2-fix-slab-use-after-free-in-gfs2_qd_dealloc.patch mm-page_alloc-separate-thp-pcp-into-movable-and-non-movable-categories.patch --- diff --git a/queue-6.1/efi-memmap-move-manipulation-routines-into-x86-arch-tree.patch b/queue-6.1/efi-memmap-move-manipulation-routines-into-x86-arch-tree.patch new file mode 100644 index 00000000000..3e539d08d0c --- /dev/null +++ b/queue-6.1/efi-memmap-move-manipulation-routines-into-x86-arch-tree.patch @@ -0,0 +1,588 @@ +From fdc6d38d64a20c542b1867ebeb8dd03b98829336 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Sat, 1 Oct 2022 19:09:24 +0200 +Subject: efi: memmap: Move manipulation routines into x86 arch tree + +From: Ard Biesheuvel + +commit fdc6d38d64a20c542b1867ebeb8dd03b98829336 upstream. + +The EFI memory map is a description of the memory layout as provided by +the firmware, and only x86 manipulates it in various different ways for +its own memory bookkeeping. So let's move the memmap routines that are +only used by x86 into the x86 arch tree. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/efi.h | 12 ++ + arch/x86/platform/efi/Makefile | 3 + arch/x86/platform/efi/memmap.c | 236 ++++++++++++++++++++++++++++++++++++++++ + drivers/firmware/efi/memmap.c | 240 +---------------------------------------- + include/linux/efi.h | 10 - + 5 files changed, 261 insertions(+), 240 deletions(-) + create mode 100644 arch/x86/platform/efi/memmap.c + +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -416,6 +416,18 @@ static inline void efi_fake_memmap_early + } + #endif + ++extern int __init efi_memmap_alloc(unsigned int num_entries, ++ struct efi_memory_map_data *data); ++extern void __efi_memmap_free(u64 phys, unsigned long size, ++ unsigned long flags); ++#define __efi_memmap_free __efi_memmap_free ++ ++extern int __init efi_memmap_install(struct efi_memory_map_data *data); ++extern int __init efi_memmap_split_count(efi_memory_desc_t *md, ++ struct range *range); ++extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap, ++ void *buf, struct efi_mem_range *mem); ++ + #define arch_ima_efi_boot_mode \ + ({ extern struct boot_params boot_params; boot_params.secure_boot; }) + +--- a/arch/x86/platform/efi/Makefile ++++ b/arch/x86/platform/efi/Makefile +@@ -2,5 +2,6 @@ + KASAN_SANITIZE := n + GCOV_PROFILE := n + +-obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o ++obj-$(CONFIG_EFI) += memmap.o quirks.o efi.o efi_$(BITS).o \ ++ efi_stub_$(BITS).o + obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o +--- /dev/null ++++ b/arch/x86/platform/efi/memmap.c +@@ -0,0 +1,236 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Common EFI memory map functions. ++ */ ++ ++#define pr_fmt(fmt) "efi: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) ++{ ++ return memblock_phys_alloc(size, SMP_CACHE_BYTES); ++} ++ ++static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) ++{ ++ unsigned int order = get_order(size); ++ struct page *p = alloc_pages(GFP_KERNEL, order); ++ ++ if (!p) ++ return 0; ++ ++ return PFN_PHYS(page_to_pfn(p)); ++} ++ ++void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags) ++{ ++ if (flags & EFI_MEMMAP_MEMBLOCK) { ++ if (slab_is_available()) ++ memblock_free_late(phys, size); ++ else ++ memblock_phys_free(phys, size); ++ } else if (flags & EFI_MEMMAP_SLAB) { ++ struct page *p = pfn_to_page(PHYS_PFN(phys)); ++ unsigned int order = get_order(size); ++ ++ free_pages((unsigned long) page_address(p), order); ++ } ++} ++ ++/** ++ * efi_memmap_alloc - Allocate memory for the EFI memory map ++ * @num_entries: Number of entries in the allocated map. ++ * @data: efi memmap installation parameters ++ * ++ * Depending on whether mm_init() has already been invoked or not, ++ * either memblock or "normal" page allocation is used. ++ * ++ * Returns zero on success, a negative error code on failure. ++ */ ++int __init efi_memmap_alloc(unsigned int num_entries, ++ struct efi_memory_map_data *data) ++{ ++ /* Expect allocation parameters are zero initialized */ ++ WARN_ON(data->phys_map || data->size); ++ ++ data->size = num_entries * efi.memmap.desc_size; ++ data->desc_version = efi.memmap.desc_version; ++ data->desc_size = efi.memmap.desc_size; ++ data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK); ++ data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE; ++ ++ if (slab_is_available()) { ++ data->flags |= EFI_MEMMAP_SLAB; ++ data->phys_map = __efi_memmap_alloc_late(data->size); ++ } else { ++ data->flags |= EFI_MEMMAP_MEMBLOCK; ++ data->phys_map = __efi_memmap_alloc_early(data->size); ++ } ++ ++ if (!data->phys_map) ++ return -ENOMEM; ++ return 0; ++} ++ ++/** ++ * efi_memmap_install - Install a new EFI memory map in efi.memmap ++ * @ctx: map allocation parameters (address, size, flags) ++ * ++ * Unlike efi_memmap_init_*(), this function does not allow the caller ++ * to switch from early to late mappings. It simply uses the existing ++ * mapping function and installs the new memmap. ++ * ++ * Returns zero on success, a negative error code on failure. ++ */ ++int __init efi_memmap_install(struct efi_memory_map_data *data) ++{ ++ efi_memmap_unmap(); ++ ++ return __efi_memmap_init(data); ++} ++ ++/** ++ * efi_memmap_split_count - Count number of additional EFI memmap entries ++ * @md: EFI memory descriptor to split ++ * @range: Address range (start, end) to split around ++ * ++ * Returns the number of additional EFI memmap entries required to ++ * accommodate @range. ++ */ ++int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range) ++{ ++ u64 m_start, m_end; ++ u64 start, end; ++ int count = 0; ++ ++ start = md->phys_addr; ++ end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; ++ ++ /* modifying range */ ++ m_start = range->start; ++ m_end = range->end; ++ ++ if (m_start <= start) { ++ /* split into 2 parts */ ++ if (start < m_end && m_end < end) ++ count++; ++ } ++ ++ if (start < m_start && m_start < end) { ++ /* split into 3 parts */ ++ if (m_end < end) ++ count += 2; ++ /* split into 2 parts */ ++ if (end <= m_end) ++ count++; ++ } ++ ++ return count; ++} ++ ++/** ++ * efi_memmap_insert - Insert a memory region in an EFI memmap ++ * @old_memmap: The existing EFI memory map structure ++ * @buf: Address of buffer to store new map ++ * @mem: Memory map entry to insert ++ * ++ * It is suggested that you call efi_memmap_split_count() first ++ * to see how large @buf needs to be. ++ */ ++void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf, ++ struct efi_mem_range *mem) ++{ ++ u64 m_start, m_end, m_attr; ++ efi_memory_desc_t *md; ++ u64 start, end; ++ void *old, *new; ++ ++ /* modifying range */ ++ m_start = mem->range.start; ++ m_end = mem->range.end; ++ m_attr = mem->attribute; ++ ++ /* ++ * The EFI memory map deals with regions in EFI_PAGE_SIZE ++ * units. Ensure that the region described by 'mem' is aligned ++ * correctly. ++ */ ++ if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) || ++ !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) { ++ WARN_ON(1); ++ return; ++ } ++ ++ for (old = old_memmap->map, new = buf; ++ old < old_memmap->map_end; ++ old += old_memmap->desc_size, new += old_memmap->desc_size) { ++ ++ /* copy original EFI memory descriptor */ ++ memcpy(new, old, old_memmap->desc_size); ++ md = new; ++ start = md->phys_addr; ++ end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; ++ ++ if (m_start <= start && end <= m_end) ++ md->attribute |= m_attr; ++ ++ if (m_start <= start && ++ (start < m_end && m_end < end)) { ++ /* first part */ ++ md->attribute |= m_attr; ++ md->num_pages = (m_end - md->phys_addr + 1) >> ++ EFI_PAGE_SHIFT; ++ /* latter part */ ++ new += old_memmap->desc_size; ++ memcpy(new, old, old_memmap->desc_size); ++ md = new; ++ md->phys_addr = m_end + 1; ++ md->num_pages = (end - md->phys_addr + 1) >> ++ EFI_PAGE_SHIFT; ++ } ++ ++ if ((start < m_start && m_start < end) && m_end < end) { ++ /* first part */ ++ md->num_pages = (m_start - md->phys_addr) >> ++ EFI_PAGE_SHIFT; ++ /* middle part */ ++ new += old_memmap->desc_size; ++ memcpy(new, old, old_memmap->desc_size); ++ md = new; ++ md->attribute |= m_attr; ++ md->phys_addr = m_start; ++ md->num_pages = (m_end - m_start + 1) >> ++ EFI_PAGE_SHIFT; ++ /* last part */ ++ new += old_memmap->desc_size; ++ memcpy(new, old, old_memmap->desc_size); ++ md = new; ++ md->phys_addr = m_end + 1; ++ md->num_pages = (end - m_end) >> ++ EFI_PAGE_SHIFT; ++ } ++ ++ if ((start < m_start && m_start < end) && ++ (end <= m_end)) { ++ /* first part */ ++ md->num_pages = (m_start - md->phys_addr) >> ++ EFI_PAGE_SHIFT; ++ /* latter part */ ++ new += old_memmap->desc_size; ++ memcpy(new, old, old_memmap->desc_size); ++ md = new; ++ md->phys_addr = m_start; ++ md->num_pages = (end - md->phys_addr + 1) >> ++ EFI_PAGE_SHIFT; ++ md->attribute |= m_attr; ++ } ++ } ++} +--- a/drivers/firmware/efi/memmap.c ++++ b/drivers/firmware/efi/memmap.c +@@ -9,82 +9,15 @@ + #include + #include + #include +-#include + #include + #include + +-static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) +-{ +- return memblock_phys_alloc(size, SMP_CACHE_BYTES); +-} +- +-static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) +-{ +- unsigned int order = get_order(size); +- struct page *p = alloc_pages(GFP_KERNEL, order); +- +- if (!p) +- return 0; +- +- return PFN_PHYS(page_to_pfn(p)); +-} +- +-void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags) +-{ +- if (flags & EFI_MEMMAP_MEMBLOCK) { +- if (slab_is_available()) +- memblock_free_late(phys, size); +- else +- memblock_phys_free(phys, size); +- } else if (flags & EFI_MEMMAP_SLAB) { +- struct page *p = pfn_to_page(PHYS_PFN(phys)); +- unsigned int order = get_order(size); +- +- free_pages((unsigned long) page_address(p), order); +- } +-} +- +-static void __init efi_memmap_free(void) +-{ +- __efi_memmap_free(efi.memmap.phys_map, +- efi.memmap.desc_size * efi.memmap.nr_map, +- efi.memmap.flags); +-} +- +-/** +- * efi_memmap_alloc - Allocate memory for the EFI memory map +- * @num_entries: Number of entries in the allocated map. +- * @data: efi memmap installation parameters +- * +- * Depending on whether mm_init() has already been invoked or not, +- * either memblock or "normal" page allocation is used. +- * +- * Returns zero on success, a negative error code on failure. +- */ +-int __init efi_memmap_alloc(unsigned int num_entries, +- struct efi_memory_map_data *data) +-{ +- /* Expect allocation parameters are zero initialized */ +- WARN_ON(data->phys_map || data->size); +- +- data->size = num_entries * efi.memmap.desc_size; +- data->desc_version = efi.memmap.desc_version; +- data->desc_size = efi.memmap.desc_size; +- data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK); +- data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE; +- +- if (slab_is_available()) { +- data->flags |= EFI_MEMMAP_SLAB; +- data->phys_map = __efi_memmap_alloc_late(data->size); +- } else { +- data->flags |= EFI_MEMMAP_MEMBLOCK; +- data->phys_map = __efi_memmap_alloc_early(data->size); +- } ++#include ++#include + +- if (!data->phys_map) +- return -ENOMEM; +- return 0; +-} ++#ifndef __efi_memmap_free ++#define __efi_memmap_free(phys, size, flags) do { } while (0) ++#endif + + /** + * __efi_memmap_init - Common code for mapping the EFI memory map +@@ -101,7 +34,7 @@ int __init efi_memmap_alloc(unsigned int + * + * Returns zero on success, a negative error code on failure. + */ +-static int __init __efi_memmap_init(struct efi_memory_map_data *data) ++int __init __efi_memmap_init(struct efi_memory_map_data *data) + { + struct efi_memory_map map; + phys_addr_t phys_map; +@@ -121,8 +54,10 @@ static int __init __efi_memmap_init(stru + return -ENOMEM; + } + +- /* NOP if data->flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB) == 0 */ +- efi_memmap_free(); ++ if (efi.memmap.flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB)) ++ __efi_memmap_free(efi.memmap.phys_map, ++ efi.memmap.desc_size * efi.memmap.nr_map, ++ efi.memmap.flags); + + map.phys_map = data->phys_map; + map.nr_map = data->size / data->desc_size; +@@ -220,158 +155,3 @@ int __init efi_memmap_init_late(phys_add + + return __efi_memmap_init(&data); + } +- +-/** +- * efi_memmap_install - Install a new EFI memory map in efi.memmap +- * @ctx: map allocation parameters (address, size, flags) +- * +- * Unlike efi_memmap_init_*(), this function does not allow the caller +- * to switch from early to late mappings. It simply uses the existing +- * mapping function and installs the new memmap. +- * +- * Returns zero on success, a negative error code on failure. +- */ +-int __init efi_memmap_install(struct efi_memory_map_data *data) +-{ +- efi_memmap_unmap(); +- +- return __efi_memmap_init(data); +-} +- +-/** +- * efi_memmap_split_count - Count number of additional EFI memmap entries +- * @md: EFI memory descriptor to split +- * @range: Address range (start, end) to split around +- * +- * Returns the number of additional EFI memmap entries required to +- * accommodate @range. +- */ +-int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range) +-{ +- u64 m_start, m_end; +- u64 start, end; +- int count = 0; +- +- start = md->phys_addr; +- end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; +- +- /* modifying range */ +- m_start = range->start; +- m_end = range->end; +- +- if (m_start <= start) { +- /* split into 2 parts */ +- if (start < m_end && m_end < end) +- count++; +- } +- +- if (start < m_start && m_start < end) { +- /* split into 3 parts */ +- if (m_end < end) +- count += 2; +- /* split into 2 parts */ +- if (end <= m_end) +- count++; +- } +- +- return count; +-} +- +-/** +- * efi_memmap_insert - Insert a memory region in an EFI memmap +- * @old_memmap: The existing EFI memory map structure +- * @buf: Address of buffer to store new map +- * @mem: Memory map entry to insert +- * +- * It is suggested that you call efi_memmap_split_count() first +- * to see how large @buf needs to be. +- */ +-void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf, +- struct efi_mem_range *mem) +-{ +- u64 m_start, m_end, m_attr; +- efi_memory_desc_t *md; +- u64 start, end; +- void *old, *new; +- +- /* modifying range */ +- m_start = mem->range.start; +- m_end = mem->range.end; +- m_attr = mem->attribute; +- +- /* +- * The EFI memory map deals with regions in EFI_PAGE_SIZE +- * units. Ensure that the region described by 'mem' is aligned +- * correctly. +- */ +- if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) || +- !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) { +- WARN_ON(1); +- return; +- } +- +- for (old = old_memmap->map, new = buf; +- old < old_memmap->map_end; +- old += old_memmap->desc_size, new += old_memmap->desc_size) { +- +- /* copy original EFI memory descriptor */ +- memcpy(new, old, old_memmap->desc_size); +- md = new; +- start = md->phys_addr; +- end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; +- +- if (m_start <= start && end <= m_end) +- md->attribute |= m_attr; +- +- if (m_start <= start && +- (start < m_end && m_end < end)) { +- /* first part */ +- md->attribute |= m_attr; +- md->num_pages = (m_end - md->phys_addr + 1) >> +- EFI_PAGE_SHIFT; +- /* latter part */ +- new += old_memmap->desc_size; +- memcpy(new, old, old_memmap->desc_size); +- md = new; +- md->phys_addr = m_end + 1; +- md->num_pages = (end - md->phys_addr + 1) >> +- EFI_PAGE_SHIFT; +- } +- +- if ((start < m_start && m_start < end) && m_end < end) { +- /* first part */ +- md->num_pages = (m_start - md->phys_addr) >> +- EFI_PAGE_SHIFT; +- /* middle part */ +- new += old_memmap->desc_size; +- memcpy(new, old, old_memmap->desc_size); +- md = new; +- md->attribute |= m_attr; +- md->phys_addr = m_start; +- md->num_pages = (m_end - m_start + 1) >> +- EFI_PAGE_SHIFT; +- /* last part */ +- new += old_memmap->desc_size; +- memcpy(new, old, old_memmap->desc_size); +- md = new; +- md->phys_addr = m_end + 1; +- md->num_pages = (end - m_end) >> +- EFI_PAGE_SHIFT; +- } +- +- if ((start < m_start && m_start < end) && +- (end <= m_end)) { +- /* first part */ +- md->num_pages = (m_start - md->phys_addr) >> +- EFI_PAGE_SHIFT; +- /* latter part */ +- new += old_memmap->desc_size; +- memcpy(new, old, old_memmap->desc_size); +- md = new; +- md->phys_addr = m_start; +- md->num_pages = (end - md->phys_addr + 1) >> +- EFI_PAGE_SHIFT; +- md->attribute |= m_attr; +- } +- } +-} +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -709,18 +709,10 @@ static inline efi_status_t efi_query_var + #endif + extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); + +-extern int __init efi_memmap_alloc(unsigned int num_entries, +- struct efi_memory_map_data *data); +-extern void __efi_memmap_free(u64 phys, unsigned long size, +- unsigned long flags); ++extern int __init __efi_memmap_init(struct efi_memory_map_data *data); + extern int __init efi_memmap_init_early(struct efi_memory_map_data *data); + extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size); + extern void __init efi_memmap_unmap(void); +-extern int __init efi_memmap_install(struct efi_memory_map_data *data); +-extern int __init efi_memmap_split_count(efi_memory_desc_t *md, +- struct range *range); +-extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap, +- void *buf, struct efi_mem_range *mem); + + #ifdef CONFIG_EFI_ESRT + extern void __init efi_esrt_init(void); diff --git a/queue-6.1/efi-x86-free-efi-memory-map-only-when-installing-a-new-one.patch b/queue-6.1/efi-x86-free-efi-memory-map-only-when-installing-a-new-one.patch new file mode 100644 index 00000000000..ef3d1e49f5e --- /dev/null +++ b/queue-6.1/efi-x86-free-efi-memory-map-only-when-installing-a-new-one.patch @@ -0,0 +1,109 @@ +From 75dde792d6f6c2d0af50278bd374bf0c512fe196 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 10 Jun 2024 16:02:13 +0200 +Subject: efi/x86: Free EFI memory map only when installing a new one. + +From: Ard Biesheuvel + +commit 75dde792d6f6c2d0af50278bd374bf0c512fe196 upstream. + +The logic in __efi_memmap_init() is shared between two different +execution flows: +- mapping the EFI memory map early or late into the kernel VA space, so + that its entries can be accessed; +- the x86 specific cloning of the EFI memory map in order to insert new + entries that are created as a result of making a memory reservation + via a call to efi_mem_reserve(). + +In the former case, the underlying memory containing the kernel's view +of the EFI memory map (which may be heavily modified by the kernel +itself on x86) is not modified at all, and the only thing that changes +is the virtual mapping of this memory, which is different between early +and late boot. + +In the latter case, an entirely new allocation is created that carries a +new, updated version of the kernel's view of the EFI memory map. When +installing this new version, the old version will no longer be +referenced, and if the memory was allocated by the kernel, it will leak +unless it gets freed. + +The logic that implements this freeing currently lives on the code path +that is shared between these two use cases, but it should only apply to +the latter. So move it to the correct spot. + +While at it, drop the dummy definition for non-x86 architectures, as +that is no longer needed. + +Cc: +Fixes: f0ef6523475f ("efi: Fix efi_memmap_alloc() leaks") +Tested-by: Ashish Kalra +Link: https://lore.kernel.org/all/36ad5079-4326-45ed-85f6-928ff76483d3@amd.com +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/efi.h | 1 - + arch/x86/platform/efi/memmap.c | 12 +++++++++++- + drivers/firmware/efi/memmap.c | 9 --------- + 3 files changed, 11 insertions(+), 11 deletions(-) + +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -420,7 +420,6 @@ extern int __init efi_memmap_alloc(unsig + struct efi_memory_map_data *data); + extern void __efi_memmap_free(u64 phys, unsigned long size, + unsigned long flags); +-#define __efi_memmap_free __efi_memmap_free + + extern int __init efi_memmap_install(struct efi_memory_map_data *data); + extern int __init efi_memmap_split_count(efi_memory_desc_t *md, +--- a/arch/x86/platform/efi/memmap.c ++++ b/arch/x86/platform/efi/memmap.c +@@ -92,12 +92,22 @@ int __init efi_memmap_alloc(unsigned int + */ + int __init efi_memmap_install(struct efi_memory_map_data *data) + { ++ unsigned long size = efi.memmap.desc_size * efi.memmap.nr_map; ++ unsigned long flags = efi.memmap.flags; ++ u64 phys = efi.memmap.phys_map; ++ int ret; ++ + efi_memmap_unmap(); + + if (efi_enabled(EFI_PARAVIRT)) + return 0; + +- return __efi_memmap_init(data); ++ ret = __efi_memmap_init(data); ++ if (ret) ++ return ret; ++ ++ __efi_memmap_free(phys, size, flags); ++ return 0; + } + + /** +--- a/drivers/firmware/efi/memmap.c ++++ b/drivers/firmware/efi/memmap.c +@@ -15,10 +15,6 @@ + #include + #include + +-#ifndef __efi_memmap_free +-#define __efi_memmap_free(phys, size, flags) do { } while (0) +-#endif +- + /** + * __efi_memmap_init - Common code for mapping the EFI memory map + * @data: EFI memory map data +@@ -51,11 +47,6 @@ int __init __efi_memmap_init(struct efi_ + return -ENOMEM; + } + +- if (efi.memmap.flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB)) +- __efi_memmap_free(efi.memmap.phys_map, +- efi.memmap.desc_size * efi.memmap.nr_map, +- efi.memmap.flags); +- + map.phys_map = data->phys_map; + map.nr_map = data->size / data->desc_size; + map.map_end = map.map + data->size; diff --git a/queue-6.1/efi-xen-set-efi_paravirt-for-xen-dom0-boot-on-all-architectures.patch b/queue-6.1/efi-xen-set-efi_paravirt-for-xen-dom0-boot-on-all-architectures.patch new file mode 100644 index 00000000000..6ed43329977 --- /dev/null +++ b/queue-6.1/efi-xen-set-efi_paravirt-for-xen-dom0-boot-on-all-architectures.patch @@ -0,0 +1,95 @@ +From d85e3e34940788578eeffd94e8b7e1d28e7278e9 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Sat, 1 Oct 2022 17:17:36 +0200 +Subject: efi: xen: Set EFI_PARAVIRT for Xen dom0 boot on all architectures + +From: Ard Biesheuvel + +commit d85e3e34940788578eeffd94e8b7e1d28e7278e9 upstream. + +Currently, the EFI_PARAVIRT flag is only used by Xen dom0 boot on x86, +even though other architectures also support pseudo-EFI boot, where the +core kernel is invoked directly and provided with a set of data tables +that resemble the ones constructed by the EFI stub, which never actually +runs in that case. + +Let's fix this inconsistency, and always set this flag when booting dom0 +via the EFI boot path. Note that Xen on x86 does not provide the EFI +memory map in this case, whereas other architectures do, so move the +associated EFI_PARAVIRT check into the x86 platform code. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/platform/efi/efi.c | 8 +++++--- + arch/x86/platform/efi/memmap.c | 3 +++ + drivers/firmware/efi/fdtparams.c | 4 ++++ + drivers/firmware/efi/memmap.c | 3 --- + 4 files changed, 12 insertions(+), 6 deletions(-) + +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -214,9 +214,11 @@ int __init efi_memblock_x86_reserve_rang + data.desc_size = e->efi_memdesc_size; + data.desc_version = e->efi_memdesc_version; + +- rv = efi_memmap_init_early(&data); +- if (rv) +- return rv; ++ if (!efi_enabled(EFI_PARAVIRT)) { ++ rv = efi_memmap_init_early(&data); ++ if (rv) ++ return rv; ++ } + + if (add_efi_memmap || do_efi_soft_reserve()) + do_add_efi_memmap(); +--- a/arch/x86/platform/efi/memmap.c ++++ b/arch/x86/platform/efi/memmap.c +@@ -94,6 +94,9 @@ int __init efi_memmap_install(struct efi + { + efi_memmap_unmap(); + ++ if (efi_enabled(EFI_PARAVIRT)) ++ return 0; ++ + return __efi_memmap_init(data); + } + +--- a/drivers/firmware/efi/fdtparams.c ++++ b/drivers/firmware/efi/fdtparams.c +@@ -30,11 +30,13 @@ static __initconst const char name[][22] + + static __initconst const struct { + const char path[17]; ++ u8 paravirt; + const char params[PARAMCOUNT][26]; + } dt_params[] = { + { + #ifdef CONFIG_XEN // <-------17------> + .path = "/hypervisor/uefi", ++ .paravirt = 1, + .params = { + [SYSTAB] = "xen,uefi-system-table", + [MMBASE] = "xen,uefi-mmap-start", +@@ -121,6 +123,8 @@ u64 __init efi_get_fdt_params(struct efi + pr_err("Can't find property '%s' in DT!\n", pname); + return 0; + } ++ if (dt_params[i].paravirt) ++ set_bit(EFI_PARAVIRT, &efi.flags); + return systab; + } + notfound: +--- a/drivers/firmware/efi/memmap.c ++++ b/drivers/firmware/efi/memmap.c +@@ -39,9 +39,6 @@ int __init __efi_memmap_init(struct efi_ + struct efi_memory_map map; + phys_addr_t phys_map; + +- if (efi_enabled(EFI_PARAVIRT)) +- return 0; +- + phys_map = data->phys_map; + + if (data->flags & EFI_MEMMAP_LATE) diff --git a/queue-6.1/gfs2-fix-slab-use-after-free-in-gfs2_qd_dealloc.patch b/queue-6.1/gfs2-fix-slab-use-after-free-in-gfs2_qd_dealloc.patch new file mode 100644 index 00000000000..a20b2a4f3c9 --- /dev/null +++ b/queue-6.1/gfs2-fix-slab-use-after-free-in-gfs2_qd_dealloc.patch @@ -0,0 +1,42 @@ +From bdcb8aa434c6d36b5c215d02a9ef07551be25a37 Mon Sep 17 00:00:00 2001 +From: Juntong Deng +Date: Mon, 30 Oct 2023 05:10:06 +0800 +Subject: gfs2: Fix slab-use-after-free in gfs2_qd_dealloc + +From: Juntong Deng + +commit bdcb8aa434c6d36b5c215d02a9ef07551be25a37 upstream. + +In gfs2_put_super(), whether withdrawn or not, the quota should +be cleaned up by gfs2_quota_cleanup(). + +Otherwise, struct gfs2_sbd will be freed before gfs2_qd_dealloc (rcu +callback) has run for all gfs2_quota_data objects, resulting in +use-after-free. + +Also, gfs2_destroy_threads() and gfs2_quota_cleanup() is already called +by gfs2_make_fs_ro(), so in gfs2_put_super(), after calling +gfs2_make_fs_ro(), there is no need to call them again. + +Reported-by: syzbot+29c47e9e51895928698c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=29c47e9e51895928698c +Signed-off-by: Juntong Deng +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Clayton Casciato + +--- + fs/gfs2/super.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -591,6 +591,8 @@ restart: + + if (!sb_rdonly(sb)) { + gfs2_make_fs_ro(sdp); ++ } else { ++ gfs2_quota_cleanup(sdp); + } + WARN_ON(gfs2_withdrawing(sdp)); + diff --git a/queue-6.1/mm-page_alloc-separate-thp-pcp-into-movable-and-non-movable-categories.patch b/queue-6.1/mm-page_alloc-separate-thp-pcp-into-movable-and-non-movable-categories.patch new file mode 100644 index 00000000000..2677c2a156b --- /dev/null +++ b/queue-6.1/mm-page_alloc-separate-thp-pcp-into-movable-and-non-movable-categories.patch @@ -0,0 +1,110 @@ +From bf14ed81f571f8dba31cd72ab2e50fbcc877cc31 Mon Sep 17 00:00:00 2001 +From: yangge +Date: Thu, 20 Jun 2024 08:59:50 +0800 +Subject: mm/page_alloc: Separate THP PCP into movable and non-movable categories + +From: yangge + +commit bf14ed81f571f8dba31cd72ab2e50fbcc877cc31 upstream. + +Since commit 5d0a661d808f ("mm/page_alloc: use only one PCP list for +THP-sized allocations") no longer differentiates the migration type of +pages in THP-sized PCP list, it's possible that non-movable allocation +requests may get a CMA page from the list, in some cases, it's not +acceptable. + +If a large number of CMA memory are configured in system (for example, the +CMA memory accounts for 50% of the system memory), starting a virtual +machine with device passthrough will get stuck. During starting the +virtual machine, it will call pin_user_pages_remote(..., FOLL_LONGTERM, +...) to pin memory. Normally if a page is present and in CMA area, +pin_user_pages_remote() will migrate the page from CMA area to non-CMA +area because of FOLL_LONGTERM flag. But if non-movable allocation +requests return CMA memory, migrate_longterm_unpinnable_pages() will +migrate a CMA page to another CMA page, which will fail to pass the check +in check_and_migrate_movable_pages() and cause migration endless. + +Call trace: +pin_user_pages_remote +--__gup_longterm_locked // endless loops in this function +----_get_user_pages_locked +----check_and_migrate_movable_pages +------migrate_longterm_unpinnable_pages +--------alloc_migration_target + +This problem will also have a negative impact on CMA itself. For example, +when CMA is borrowed by THP, and we need to reclaim it through cma_alloc() +or dma_alloc_coherent(), we must move those pages out to ensure CMA's +users can retrieve that contigous memory. Currently, CMA's memory is +occupied by non-movable pages, meaning we can't relocate them. As a +result, cma_alloc() is more likely to fail. + +To fix the problem above, we add one PCP list for THP, which will not +introduce a new cacheline for struct per_cpu_pages. THP will have 2 PCP +lists, one PCP list is used by MOVABLE allocation, and the other PCP list +is used by UNMOVABLE allocation. MOVABLE allocation contains GPF_MOVABLE, +and UNMOVABLE allocation contains GFP_UNMOVABLE and GFP_RECLAIMABLE. + +Link: https://lkml.kernel.org/r/1718845190-4456-1-git-send-email-yangge1116@126.com +Fixes: 5d0a661d808f ("mm/page_alloc: use only one PCP list for THP-sized allocations") +Signed-off-by: yangge +Cc: Baolin Wang +Cc: Barry Song <21cnbao@gmail.com> +Cc: Mel Gorman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/mmzone.h | 9 ++++----- + mm/page_alloc.c | 8 ++++++-- + 2 files changed, 10 insertions(+), 7 deletions(-) + +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -552,13 +552,12 @@ enum zone_watermarks { + }; + + /* +- * One per migratetype for each PAGE_ALLOC_COSTLY_ORDER. One additional list +- * for THP which will usually be GFP_MOVABLE. Even if it is another type, +- * it should not contribute to serious fragmentation causing THP allocation +- * failures. ++ * One per migratetype for each PAGE_ALLOC_COSTLY_ORDER. Two additional lists ++ * are added for THP. One PCP list is used by GPF_MOVABLE, and the other PCP list ++ * is used by GFP_UNMOVABLE and GFP_RECLAIMABLE. + */ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +-#define NR_PCP_THP 1 ++#define NR_PCP_THP 2 + #else + #define NR_PCP_THP 0 + #endif +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -705,12 +705,16 @@ out: + + static inline unsigned int order_to_pindex(int migratetype, int order) + { ++ bool __maybe_unused movable; + int base = order; + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (order > PAGE_ALLOC_COSTLY_ORDER) { + VM_BUG_ON(order != pageblock_order); +- return NR_LOWORDER_PCP_LISTS; ++ ++ movable = migratetype == MIGRATE_MOVABLE; ++ ++ return NR_LOWORDER_PCP_LISTS + movable; + } + #else + VM_BUG_ON(order > PAGE_ALLOC_COSTLY_ORDER); +@@ -724,7 +728,7 @@ static inline int pindex_to_order(unsign + int order = pindex / MIGRATE_PCPTYPES; + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +- if (pindex == NR_LOWORDER_PCP_LISTS) ++ if (pindex >= NR_LOWORDER_PCP_LISTS) + order = pageblock_order; + #else + VM_BUG_ON(order > PAGE_ALLOC_COSTLY_ORDER); diff --git a/queue-6.1/series b/queue-6.1/series index 10f6a2d9b48..1b4f0c55080 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -118,3 +118,8 @@ syscalls-fix-compat_sys_io_pgetevents_time64-usage.patch syscalls-fix-sys_fanotify_mark-prototype.patch pwm-stm32-refuse-too-small-period-requests.patch revert-cpufreq-amd-pstate-fix-the-inconsistency-in-max-frequency-units.patch +mm-page_alloc-separate-thp-pcp-into-movable-and-non-movable-categories.patch +gfs2-fix-slab-use-after-free-in-gfs2_qd_dealloc.patch +efi-memmap-move-manipulation-routines-into-x86-arch-tree.patch +efi-xen-set-efi_paravirt-for-xen-dom0-boot-on-all-architectures.patch +efi-x86-free-efi-memory-map-only-when-installing-a-new-one.patch