diff --git a/MAINTAINERS b/MAINTAINERS index 7341667e7313..d76c9aa1d38a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3743,7 +3743,7 @@ F: include/linux/platform_data/b53.h BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE M: Nicolas Saenz Julienne -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@ -3758,7 +3758,7 @@ BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE M: Florian Fainelli M: Ray Jui M: Scott Branden -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team S: Maintained T: git git://github.com/broadcom/mach-bcm F: arch/arm/mach-bcm/ @@ -3778,7 +3778,7 @@ F: arch/mips/include/asm/mach-bcm47xx/* BROADCOM BCM4908 ETHERNET DRIVER M: Rafał Miłecki -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml @@ -3787,7 +3787,7 @@ F: drivers/net/ethernet/broadcom/unimac.h BROADCOM BCM4908 PINMUX DRIVER M: Rafał Miłecki -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-gpio@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/pinctrl/brcm,bcm4908-pinctrl.yaml @@ -3797,7 +3797,7 @@ BROADCOM BCM5301X ARM ARCHITECTURE M: Florian Fainelli M: Hauke Mehrtens M: Rafał Miłecki -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/bcm470* @@ -3808,7 +3808,7 @@ F: arch/arm/mach-bcm/bcm_5301x.c BROADCOM BCM53573 ARM ARCHITECTURE M: Florian Fainelli M: Rafał Miłecki -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/bcm47189* @@ -3816,7 +3816,7 @@ F: arch/arm/boot/dts/bcm53573* BROADCOM BCM63XX ARM ARCHITECTURE M: Florian Fainelli -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/broadcom/stblinux.git @@ -3830,7 +3830,7 @@ F: drivers/usb/gadget/udc/bcm63xx_udc.* BROADCOM BCM7XXX ARM ARCHITECTURE M: Florian Fainelli -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/broadcom/stblinux.git @@ -3848,21 +3848,21 @@ N: bcm7120 BROADCOM BDC DRIVER M: Al Cooper L: linux-usb@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team S: Maintained F: Documentation/devicetree/bindings/usb/brcm,bdc.yaml F: drivers/usb/gadget/udc/bdc/ BROADCOM BMIPS CPUFREQ DRIVER M: Markus Mayer -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-pm@vger.kernel.org S: Maintained F: drivers/cpufreq/bmips-cpufreq.c BROADCOM BMIPS MIPS ARCHITECTURE M: Florian Fainelli -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-mips@vger.kernel.org S: Maintained T: git git://github.com/broadcom/stblinux.git @@ -3928,53 +3928,53 @@ F: drivers/net/wireless/broadcom/brcm80211/ BROADCOM BRCMSTB GPIO DRIVER M: Doug Berger M: Florian Fainelli -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team S: Supported F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.yaml F: drivers/gpio/gpio-brcmstb.c BROADCOM BRCMSTB I2C DRIVER M: Kamal Dasu +R: Broadcom Kernel Team L: linux-i2c@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com S: Supported F: Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml F: drivers/i2c/busses/i2c-brcmstb.c BROADCOM BRCMSTB UART DRIVER M: Al Cooper +R: Broadcom Kernel Team L: linux-serial@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com S: Maintained F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml F: drivers/tty/serial/8250/8250_bcm7271.c BROADCOM BRCMSTB USB EHCI DRIVER M: Al Cooper +R: Broadcom Kernel Team L: linux-usb@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com S: Maintained F: Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml F: drivers/usb/host/ehci-brcm.* BROADCOM BRCMSTB USB PIN MAP DRIVER M: Al Cooper +R: Broadcom Kernel Team L: linux-usb@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com S: Maintained F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml F: drivers/usb/misc/brcmstb-usb-pinmap.c BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER M: Al Cooper +R: Broadcom Kernel Team L: linux-kernel@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com S: Maintained F: drivers/phy/broadcom/phy-brcm-usb* BROADCOM ETHERNET PHY DRIVERS M: Florian Fainelli -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: netdev@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/net/broadcom-bcm87xx.txt @@ -3985,7 +3985,7 @@ F: include/linux/brcmphy.h BROADCOM GENET ETHERNET DRIVER M: Doug Berger M: Florian Fainelli -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: netdev@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml @@ -3999,7 +3999,7 @@ F: include/linux/platform_data/mdio-bcm-unimac.h BROADCOM IPROC ARM ARCHITECTURE M: Ray Jui M: Scott Branden -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/broadcom/stblinux.git @@ -4027,7 +4027,7 @@ N: stingray BROADCOM IPROC GBIT ETHERNET DRIVER M: Rafał Miłecki -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/brcm,amac.yaml @@ -4036,7 +4036,7 @@ F: drivers/net/ethernet/broadcom/unimac.h BROADCOM KONA GPIO DRIVER M: Ray Jui -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team S: Supported F: Documentation/devicetree/bindings/gpio/brcm,kona-gpio.txt F: drivers/gpio/gpio-bcm-kona.c @@ -4069,7 +4069,7 @@ F: drivers/firmware/broadcom/* BROADCOM PMB (POWER MANAGEMENT BUS) DRIVER M: Rafał Miłecki M: Florian Fainelli -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-pm@vger.kernel.org S: Maintained T: git git://github.com/broadcom/stblinux.git @@ -4085,7 +4085,7 @@ F: include/linux/bcma/ BROADCOM SPI DRIVER M: Kamal Dasu -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team S: Maintained F: Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml F: drivers/spi/spi-bcm-qspi.* @@ -4094,7 +4094,7 @@ F: drivers/spi/spi-iproc-qspi.c BROADCOM STB AVS CPUFREQ DRIVER M: Markus Mayer -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-pm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt @@ -4102,7 +4102,7 @@ F: drivers/cpufreq/brcmstb* BROADCOM STB AVS TMON DRIVER M: Markus Mayer -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-pm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/thermal/brcm,avs-tmon.yaml @@ -4110,7 +4110,7 @@ F: drivers/thermal/broadcom/brcmstb* BROADCOM STB DPFE DRIVER M: Markus Mayer -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/memory-controllers/brcm,dpfe-cpu.yaml @@ -4119,8 +4119,8 @@ F: drivers/memory/brcmstb_dpfe.c BROADCOM STB NAND FLASH DRIVER M: Brian Norris M: Kamal Dasu +R: Broadcom Kernel Team L: linux-mtd@lists.infradead.org -L: bcm-kernel-feedback-list@broadcom.com S: Maintained F: drivers/mtd/nand/raw/brcmnand/ F: include/linux/platform_data/brcmnand.h @@ -4129,7 +4129,7 @@ BROADCOM STB PCIE DRIVER M: Jim Quinlan M: Nicolas Saenz Julienne M: Florian Fainelli -M: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: linux-pci@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml @@ -4137,7 +4137,7 @@ F: drivers/pci/controller/pcie-brcmstb.c BROADCOM SYSTEMPORT ETHERNET DRIVER M: Florian Fainelli -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/broadcom/bcmsysport.* @@ -4154,7 +4154,7 @@ F: drivers/net/ethernet/broadcom/tg3.* BROADCOM VK DRIVER M: Scott Branden -L: bcm-kernel-feedback-list@broadcom.com +R: Broadcom Kernel Team S: Supported F: drivers/misc/bcm-vk/ F: include/uapi/linux/misc/bcm_vk.h @@ -17648,8 +17648,8 @@ K: \bTIF_SECCOMP\b SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) Broadcom BRCMSTB DRIVER M: Al Cooper +R: Broadcom Kernel Team L: linux-mmc@vger.kernel.org -L: bcm-kernel-feedback-list@broadcom.com S: Maintained F: drivers/mmc/host/sdhci-brcmstb* diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index f6d91ecb8026..e9736af126b2 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -210,8 +210,6 @@ void __iomem *ioremap(resource_size_t offset, unsigned long size); extern void iounmap(volatile void __iomem *addr); #define iounmap iounmap -extern void set_iounmap_nonlazy(void); - #ifdef __KERNEL__ void memcpy_fromio(void *, const volatile void __iomem *, size_t); diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index a7f617a3981d..97529552dd24 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -37,7 +37,6 @@ static ssize_t __copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, } else memcpy(buf, vaddr + offset, csize); - set_iounmap_nonlazy(); iounmap((void __iomem *)vaddr); return csize; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6556e13ed95f..63c7ebb0da89 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1117,11 +1117,11 @@ out_free_interp: * independently randomized mmap region (0 load_bias * without MAP_FIXED nor MAP_FIXED_NOREPLACE). */ - alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); - if (interpreter || alignment > ELF_MIN_ALIGN) { + if (interpreter) { load_bias = ELF_ET_DYN_BASE; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); + alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); if (alignment) load_bias &= ~(alignment - 1); elf_flags |= MAP_FIXED_NOREPLACE; diff --git a/include/linux/kfence.h b/include/linux/kfence.h index f49e64222628..726857a4b680 100644 --- a/include/linux/kfence.h +++ b/include/linux/kfence.h @@ -204,6 +204,22 @@ static __always_inline __must_check bool kfence_free(void *addr) */ bool __must_check kfence_handle_page_fault(unsigned long addr, bool is_write, struct pt_regs *regs); +#ifdef CONFIG_PRINTK +struct kmem_obj_info; +/** + * __kfence_obj_info() - fill kmem_obj_info struct + * @kpp: kmem_obj_info to be filled + * @object: the object + * + * Return: + * * false - not a KFENCE object + * * true - a KFENCE object, filled @kpp + * + * Copies information to @kpp for KFENCE objects. + */ +bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab); +#endif + #else /* CONFIG_KFENCE */ static inline bool is_kfence_address(const void *addr) { return false; } @@ -221,6 +237,14 @@ static inline bool __must_check kfence_handle_page_fault(unsigned long addr, boo return false; } +#ifdef CONFIG_PRINTK +struct kmem_obj_info; +static inline bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) +{ + return false; +} +#endif + #endif #endif /* _LINUX_KFENCE_H */ diff --git a/kernel/irq_work.c b/kernel/irq_work.c index f7df715ec28e..7afa40fe5cc4 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -137,7 +137,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu) if (!irq_work_claim(work)) return false; - kasan_record_aux_stack(work); + kasan_record_aux_stack_noalloc(work); preempt_disable(); if (cpu != smp_processor_id()) { diff --git a/mm/compaction.c b/mm/compaction.c index c3e37aa9ff9e..fe915db6149b 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -26,6 +26,11 @@ #include "internal.h" #ifdef CONFIG_COMPACTION +/* + * Fragmentation score check interval for proactive compaction purposes. + */ +#define HPAGE_FRAG_CHECK_INTERVAL_MSEC (500) + static inline void count_compact_event(enum vm_event_item item) { count_vm_event(item); @@ -50,11 +55,6 @@ static inline void count_compact_events(enum vm_event_item item, long delta) #define pageblock_start_pfn(pfn) block_start_pfn(pfn, pageblock_order) #define pageblock_end_pfn(pfn) block_end_pfn(pfn, pageblock_order) -/* - * Fragmentation score check interval for proactive compaction purposes. - */ -static const unsigned int HPAGE_FRAG_CHECK_INTERVAL_MSEC = 500; - /* * Page order with-respect-to which proactive compaction * calculates external fragmentation, which is used as diff --git a/mm/filemap.c b/mm/filemap.c index 3a5ffb5587cd..9a1eef6c5d35 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1063,12 +1063,6 @@ void __init pagecache_init(void) init_waitqueue_head(&folio_wait_table[i]); page_writeback_init(); - - /* - * tmpfs uses the ZERO_PAGE for reading holes: it is up-to-date, - * and splice's page_cache_pipe_buf_confirm() needs to see that. - */ - SetPageUptodate(ZERO_PAGE(0)); } /* diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b34f50156f7e..f8ca7cca3c1a 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3475,7 +3475,6 @@ static int demote_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed) { int nr_nodes, node; struct page *page; - int rc = 0; lockdep_assert_held(&hugetlb_lock); @@ -3486,15 +3485,19 @@ static int demote_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed) } for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) { - if (!list_empty(&h->hugepage_freelists[node])) { - page = list_entry(h->hugepage_freelists[node].next, - struct page, lru); - rc = demote_free_huge_page(h, page); - break; + list_for_each_entry(page, &h->hugepage_freelists[node], lru) { + if (PageHWPoison(page)) + continue; + + return demote_free_huge_page(h, page); } } - return rc; + /* + * Only way to get here is if all pages on free lists are poisoned. + * Return -EBUSY so that caller will not retry. + */ + return -EBUSY; } #define HSTATE_ATTR_RO(_name) \ diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c index 07a76c46daa5..9e1b6544bfa8 100644 --- a/mm/kasan/hw_tags.c +++ b/mm/kasan/hw_tags.c @@ -336,8 +336,6 @@ void __kasan_poison_vmalloc(const void *start, unsigned long size) #endif -#if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) - void kasan_enable_tagging(void) { if (kasan_arg_mode == KASAN_ARG_MODE_ASYNC) @@ -347,6 +345,9 @@ void kasan_enable_tagging(void) else hw_enable_tagging_sync(); } + +#if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) + EXPORT_SYMBOL_GPL(kasan_enable_tagging); void kasan_force_async_fault(void) diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index d79b83d673b1..b01b4bbe0409 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -355,25 +355,27 @@ static inline const void *arch_kasan_set_tag(const void *addr, u8 tag) #define hw_set_mem_tag_range(addr, size, tag, init) \ arch_set_mem_tag_range((addr), (size), (tag), (init)) +void kasan_enable_tagging(void); + #else /* CONFIG_KASAN_HW_TAGS */ #define hw_enable_tagging_sync() #define hw_enable_tagging_async() #define hw_enable_tagging_asymm() +static inline void kasan_enable_tagging(void) { } + #endif /* CONFIG_KASAN_HW_TAGS */ #if defined(CONFIG_KASAN_HW_TAGS) && IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) -void kasan_enable_tagging(void); void kasan_force_async_fault(void); -#else /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */ +#else /* CONFIG_KASAN_HW_TAGS && CONFIG_KASAN_KUNIT_TEST */ -static inline void kasan_enable_tagging(void) { } static inline void kasan_force_async_fault(void) { } -#endif /* CONFIG_KASAN_HW_TAGS || CONFIG_KASAN_KUNIT_TEST */ +#endif /* CONFIG_KASAN_HW_TAGS && CONFIG_KASAN_KUNIT_TEST */ #ifdef CONFIG_KASAN_SW_TAGS u8 kasan_random_tag(void); diff --git a/mm/kfence/core.c b/mm/kfence/core.c index a203747ad2c0..9b2b5f56f4ae 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -231,27 +231,6 @@ static bool kfence_unprotect(unsigned long addr) return !KFENCE_WARN_ON(!kfence_protect_page(ALIGN_DOWN(addr, PAGE_SIZE), false)); } -static inline struct kfence_metadata *addr_to_metadata(unsigned long addr) -{ - long index; - - /* The checks do not affect performance; only called from slow-paths. */ - - if (!is_kfence_address((void *)addr)) - return NULL; - - /* - * May be an invalid index if called with an address at the edge of - * __kfence_pool, in which case we would report an "invalid access" - * error. - */ - index = (addr - (unsigned long)__kfence_pool) / (PAGE_SIZE * 2) - 1; - if (index < 0 || index >= CONFIG_KFENCE_NUM_OBJECTS) - return NULL; - - return &kfence_metadata[index]; -} - static inline unsigned long metadata_to_pageaddr(const struct kfence_metadata *meta) { unsigned long offset = (meta - kfence_metadata + 1) * PAGE_SIZE * 2; diff --git a/mm/kfence/kfence.h b/mm/kfence/kfence.h index 9a6c4b1b12a8..600f2e2431d6 100644 --- a/mm/kfence/kfence.h +++ b/mm/kfence/kfence.h @@ -96,6 +96,27 @@ struct kfence_metadata { extern struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS]; +static inline struct kfence_metadata *addr_to_metadata(unsigned long addr) +{ + long index; + + /* The checks do not affect performance; only called from slow-paths. */ + + if (!is_kfence_address((void *)addr)) + return NULL; + + /* + * May be an invalid index if called with an address at the edge of + * __kfence_pool, in which case we would report an "invalid access" + * error. + */ + index = (addr - (unsigned long)__kfence_pool) / (PAGE_SIZE * 2) - 1; + if (index < 0 || index >= CONFIG_KFENCE_NUM_OBJECTS) + return NULL; + + return &kfence_metadata[index]; +} + /* KFENCE error types for report generation. */ enum kfence_error_type { KFENCE_ERROR_OOB, /* Detected a out-of-bounds access. */ diff --git a/mm/kfence/report.c b/mm/kfence/report.c index f93a7b2a338b..f5a6d8ba3e21 100644 --- a/mm/kfence/report.c +++ b/mm/kfence/report.c @@ -273,3 +273,50 @@ void kfence_report_error(unsigned long address, bool is_write, struct pt_regs *r /* We encountered a memory safety error, taint the kernel! */ add_taint(TAINT_BAD_PAGE, LOCKDEP_STILL_OK); } + +#ifdef CONFIG_PRINTK +static void kfence_to_kp_stack(const struct kfence_track *track, void **kp_stack) +{ + int i, j; + + i = get_stack_skipnr(track->stack_entries, track->num_stack_entries, NULL); + for (j = 0; i < track->num_stack_entries && j < KS_ADDRS_COUNT; ++i, ++j) + kp_stack[j] = (void *)track->stack_entries[i]; + if (j < KS_ADDRS_COUNT) + kp_stack[j] = NULL; +} + +bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) +{ + struct kfence_metadata *meta = addr_to_metadata((unsigned long)object); + unsigned long flags; + + if (!meta) + return false; + + /* + * If state is UNUSED at least show the pointer requested; the rest + * would be garbage data. + */ + kpp->kp_ptr = object; + + /* Requesting info an a never-used object is almost certainly a bug. */ + if (WARN_ON(meta->state == KFENCE_OBJECT_UNUSED)) + return true; + + raw_spin_lock_irqsave(&meta->lock, flags); + + kpp->kp_slab = slab; + kpp->kp_slab_cache = meta->cache; + kpp->kp_objp = (void *)meta->addr; + kfence_to_kp_stack(&meta->alloc_track, kpp->kp_stack); + if (meta->state == KFENCE_OBJECT_FREED) + kfence_to_kp_stack(&meta->free_track, kpp->kp_free_stack); + /* get_stack_skipnr() ensures the first entry is outside allocator. */ + kpp->kp_ret = kpp->kp_stack[0]; + + raw_spin_unlock_irqrestore(&meta->lock, flags); + + return true; +} +#endif diff --git a/mm/kmemleak.c b/mm/kmemleak.c index acd7cbb82e16..a182f5ddaf68 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1132,7 +1132,7 @@ EXPORT_SYMBOL(kmemleak_no_scan); void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count, gfp_t gfp) { - if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) kmemleak_alloc(__va(phys), size, min_count, gfp); } EXPORT_SYMBOL(kmemleak_alloc_phys); @@ -1146,7 +1146,7 @@ EXPORT_SYMBOL(kmemleak_alloc_phys); */ void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size) { - if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) kmemleak_free_part(__va(phys), size); } EXPORT_SYMBOL(kmemleak_free_part_phys); @@ -1158,7 +1158,7 @@ EXPORT_SYMBOL(kmemleak_free_part_phys); */ void __ref kmemleak_not_leak_phys(phys_addr_t phys) { - if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) kmemleak_not_leak(__va(phys)); } EXPORT_SYMBOL(kmemleak_not_leak_phys); @@ -1170,7 +1170,7 @@ EXPORT_SYMBOL(kmemleak_not_leak_phys); */ void __ref kmemleak_ignore_phys(phys_addr_t phys) { - if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + if (PHYS_PFN(phys) >= min_low_pfn && PHYS_PFN(phys) < max_low_pfn) kmemleak_ignore(__va(phys)); } EXPORT_SYMBOL(kmemleak_ignore_phys); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6e5b4488a0c5..33ca8cab21e6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6131,7 +6131,7 @@ static int build_zonerefs_node(pg_data_t *pgdat, struct zoneref *zonerefs) do { zone_type--; zone = pgdat->node_zones + zone_type; - if (managed_zone(zone)) { + if (populated_zone(zone)) { zoneref_set_zone(zone, &zonerefs[nr_zones++]); check_highest_zone(zone_type); } diff --git a/mm/page_io.c b/mm/page_io.c index b417f000b49e..89fbf3cae30f 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -51,54 +51,6 @@ void end_swap_bio_write(struct bio *bio) bio_put(bio); } -static void swap_slot_free_notify(struct page *page) -{ - struct swap_info_struct *sis; - struct gendisk *disk; - swp_entry_t entry; - - /* - * There is no guarantee that the page is in swap cache - the software - * suspend code (at least) uses end_swap_bio_read() against a non- - * swapcache page. So we must check PG_swapcache before proceeding with - * this optimization. - */ - if (unlikely(!PageSwapCache(page))) - return; - - sis = page_swap_info(page); - if (data_race(!(sis->flags & SWP_BLKDEV))) - return; - - /* - * The swap subsystem performs lazy swap slot freeing, - * expecting that the page will be swapped out again. - * So we can avoid an unnecessary write if the page - * isn't redirtied. - * This is good for real swap storage because we can - * reduce unnecessary I/O and enhance wear-leveling - * if an SSD is used as the as swap device. - * But if in-memory swap device (eg zram) is used, - * this causes a duplicated copy between uncompressed - * data in VM-owned memory and compressed data in - * zram-owned memory. So let's free zram-owned memory - * and make the VM-owned decompressed page *dirty*, - * so the page should be swapped out somewhere again if - * we again wish to reclaim it. - */ - disk = sis->bdev->bd_disk; - entry.val = page_private(page); - if (disk->fops->swap_slot_free_notify && __swap_count(entry) == 1) { - unsigned long offset; - - offset = swp_offset(entry); - - SetPageDirty(page); - disk->fops->swap_slot_free_notify(sis->bdev, - offset); - } -} - static void end_swap_bio_read(struct bio *bio) { struct page *page = bio_first_page_all(bio); @@ -114,7 +66,6 @@ static void end_swap_bio_read(struct bio *bio) } SetPageUptodate(page); - swap_slot_free_notify(page); out: unlock_page(page); WRITE_ONCE(bio->bi_private, NULL); @@ -394,11 +345,6 @@ int swap_readpage(struct page *page, bool synchronous) if (sis->flags & SWP_SYNCHRONOUS_IO) { ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); if (!ret) { - if (trylock_page(page)) { - swap_slot_free_notify(page); - unlock_page(page); - } - count_vm_event(PSWPIN); goto out; } diff --git a/mm/secretmem.c b/mm/secretmem.c index 098638d3b8a4..3b3cf2892b6a 100644 --- a/mm/secretmem.c +++ b/mm/secretmem.c @@ -158,6 +158,22 @@ const struct address_space_operations secretmem_aops = { .isolate_page = secretmem_isolate_page, }; +static int secretmem_setattr(struct user_namespace *mnt_userns, + struct dentry *dentry, struct iattr *iattr) +{ + struct inode *inode = d_inode(dentry); + unsigned int ia_valid = iattr->ia_valid; + + if ((ia_valid & ATTR_SIZE) && inode->i_size) + return -EINVAL; + + return simple_setattr(mnt_userns, dentry, iattr); +} + +static const struct inode_operations secretmem_iops = { + .setattr = secretmem_setattr, +}; + static struct vfsmount *secretmem_mnt; static struct file *secretmem_file_create(unsigned long flags) @@ -177,6 +193,7 @@ static struct file *secretmem_file_create(unsigned long flags) mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER); mapping_set_unevictable(inode->i_mapping); + inode->i_op = &secretmem_iops; inode->i_mapping->a_ops = &secretmem_aops; /* pretend we are a normal file with zero size */ diff --git a/mm/shmem.c b/mm/shmem.c index 529c9ad3e926..4b2fea33158e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2513,7 +2513,6 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to) pgoff_t end_index; unsigned long nr, ret; loff_t i_size = i_size_read(inode); - bool got_page; end_index = i_size >> PAGE_SHIFT; if (index > end_index) @@ -2570,24 +2569,34 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to) */ if (!offset) mark_page_accessed(page); - got_page = true; + /* + * Ok, we have the page, and it's up-to-date, so + * now we can copy it to user space... + */ + ret = copy_page_to_iter(page, offset, nr, to); + put_page(page); + + } else if (iter_is_iovec(to)) { + /* + * Copy to user tends to be so well optimized, but + * clear_user() not so much, that it is noticeably + * faster to copy the zero page instead of clearing. + */ + ret = copy_page_to_iter(ZERO_PAGE(0), offset, nr, to); } else { - page = ZERO_PAGE(0); - got_page = false; + /* + * But submitting the same page twice in a row to + * splice() - or others? - can result in confusion: + * so don't attempt that optimization on pipes etc. + */ + ret = iov_iter_zero(nr, to); } - /* - * Ok, we have the page, and it's up-to-date, so - * now we can copy it to user space... - */ - ret = copy_page_to_iter(page, offset, nr, to); retval += ret; offset += ret; index += offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; - if (got_page) - put_page(page); if (!iov_iter_count(to)) break; if (ret < nr) { diff --git a/mm/slab.c b/mm/slab.c index b04e40078bdf..0edb474edef1 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3665,7 +3665,7 @@ EXPORT_SYMBOL(__kmalloc_node_track_caller); #endif /* CONFIG_NUMA */ #ifdef CONFIG_PRINTK -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) { struct kmem_cache *cachep; unsigned int objnr; diff --git a/mm/slab.h b/mm/slab.h index fd7ae2024897..95eb34174c1b 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -868,7 +868,7 @@ struct kmem_obj_info { void *kp_stack[KS_ADDRS_COUNT]; void *kp_free_stack[KS_ADDRS_COUNT]; }; -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab); +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab); #endif #ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR diff --git a/mm/slab_common.c b/mm/slab_common.c index 6ee64d6208b3..2b3206a2c3b5 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -555,6 +555,13 @@ bool kmem_valid_obj(void *object) } EXPORT_SYMBOL_GPL(kmem_valid_obj); +static void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) +{ + if (__kfence_obj_info(kpp, object, slab)) + return; + __kmem_obj_info(kpp, object, slab); +} + /** * kmem_dump_obj - Print available slab provenance information * @object: slab object for which to find provenance information. @@ -590,6 +597,8 @@ void kmem_dump_obj(void *object) pr_cont(" slab%s %s", cp, kp.kp_slab_cache->name); else pr_cont(" slab%s", cp); + if (is_kfence_address(object)) + pr_cont(" (kfence)"); if (kp.kp_objp) pr_cont(" start %px", kp.kp_objp); if (kp.kp_data_offset) diff --git a/mm/slob.c b/mm/slob.c index dfa6808dff36..40ea6e2d4ccd 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -463,7 +463,7 @@ out: } #ifdef CONFIG_PRINTK -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) { kpp->kp_ptr = object; kpp->kp_slab = slab; diff --git a/mm/slub.c b/mm/slub.c index 74d92aa4a3a2..ed5c2c03a47a 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4312,7 +4312,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s) } #ifdef CONFIG_PRINTK -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *slab) { void *base; int __maybe_unused i; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index e163372d3967..0b17498a34f1 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1671,17 +1671,6 @@ static DEFINE_MUTEX(vmap_purge_lock); /* for per-CPU blocks */ static void purge_fragmented_blocks_allcpus(void); -#ifdef CONFIG_X86_64 -/* - * called before a call to iounmap() if the caller wants vm_area_struct's - * immediately freed. - */ -void set_iounmap_nonlazy(void) -{ - atomic_long_set(&vmap_lazy_nr, lazy_max_pages()+1); -} -#endif /* CONFIG_X86_64 */ - /* * Purges all lazily-freed vmap areas. */