From: Cui GaoSheng cuigaosheng1@huawei.com
hulk inclusion category: bugfix bugzilla: 186383 https://gitee.com/openeuler/kernel/issues/I4X1AI?from=project-issue CVE: NA
--------------------------------
This reverts commit fcfdde9cfc503cfd191b7286f9c48077fb5bf420.
Signed-off-by: Cui GaoSheng cuigaosheng1@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/audit.c | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c index 21be62bc8205..2a38cbaf3ddb 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -732,8 +732,6 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, if (!sk) { if (err_hook) (*err_hook)(skb); - if (queue == &audit_hold_queue) - goto out; continue; }
@@ -750,8 +748,6 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, (*err_hook)(skb); if (rc == -EAGAIN) rc = 0; - if (queue == &audit_hold_queue) - goto out; /* continue to drain the queue */ continue; } else @@ -763,7 +759,6 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, } }
-out: return (rc >= 0 ? 0 : rc); }
From: Paul Moore paul@paul-moore.com
mainline inclusion from mainline-v5.17-rc3 commit f26d04331360d42dbd6b58448bd98e4edbfbe1c5 category: bugfix bugzilla: 186383 https://gitee.com/openeuler/kernel/issues/I4X1AI?from=project-issue CVE: NA
--------------------------------
When an admin enables audit at early boot via the "audit=1" kernel command line the audit queue behavior is slightly different; the audit subsystem goes to greater lengths to avoid dropping records, which unfortunately can result in problems when the audit daemon is forcibly stopped for an extended period of time.
This patch makes a number of changes designed to improve the audit queuing behavior so that leaving the audit daemon in a stopped state for an extended period does not cause a significant impact to the system.
- kauditd_send_queue() is now limited to looping through the passed queue only once per call. This not only prevents the function from looping indefinitely when records are returned to the current queue, it also allows any recovery handling in kauditd_thread() to take place when kauditd_send_queue() returns.
- Transient netlink send errors seen as -EAGAIN now cause the record to be returned to the retry queue instead of going to the hold queue. The intention of the hold queue is to store, perhaps for an extended period of time, the events which led up to the audit daemon going offline. The retry queue remains a temporary queue intended to protect against transient issues between the kernel and the audit daemon.
- The retry queue is now limited by the audit_backlog_limit setting, the same as the other queues. This allows admins to bound the size of all of the audit queues on the system.
- kauditd_rehold_skb() now returns records to the end of the hold queue to ensure ordering is preserved in the face of recent changes to kauditd_send_queue().
Cc: stable@vger.kernel.org Fixes: 5b52330bbfe63 ("audit: fix auditd/kernel connection state tracking") Fixes: f4b3ee3c85551 ("audit: improve robustness of the audit queue handling") Reported-by: Gaosheng Cui cuigaosheng1@huawei.com Tested-by: Gaosheng Cui cuigaosheng1@huawei.com Reviewed-by: Richard Guy Briggs rgb@redhat.com Signed-off-by: Paul Moore paul@paul-moore.com Signed-off-by: Cui GaoSheng cuigaosheng1@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/audit.c | 62 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 19 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c index 2a38cbaf3ddb..aeec86ed4708 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -541,20 +541,22 @@ static void kauditd_printk_skb(struct sk_buff *skb) /** * kauditd_rehold_skb - Handle a audit record send failure in the hold queue * @skb: audit record + * @error: error code (unused) * * Description: * This should only be used by the kauditd_thread when it fails to flush the * hold queue. */ -static void kauditd_rehold_skb(struct sk_buff *skb) +static void kauditd_rehold_skb(struct sk_buff *skb, __always_unused int error) { - /* put the record back in the queue at the same place */ - skb_queue_head(&audit_hold_queue, skb); + /* put the record back in the queue */ + skb_queue_tail(&audit_hold_queue, skb); }
/** * kauditd_hold_skb - Queue an audit record, waiting for auditd * @skb: audit record + * @error: error code * * Description: * Queue the audit record, waiting for an instance of auditd. When this @@ -564,19 +566,31 @@ static void kauditd_rehold_skb(struct sk_buff *skb) * and queue it, if we have room. If we want to hold on to the record, but we * don't have room, record a record lost message. */ -static void kauditd_hold_skb(struct sk_buff *skb) +static void kauditd_hold_skb(struct sk_buff *skb, int error) { /* at this point it is uncertain if we will ever send this to auditd so * try to send the message via printk before we go any further */ kauditd_printk_skb(skb);
/* can we just silently drop the message? */ - if (!audit_default) { - kfree_skb(skb); - return; + if (!audit_default) + goto drop; + + /* the hold queue is only for when the daemon goes away completely, + * not -EAGAIN failures; if we are in a -EAGAIN state requeue the + * record on the retry queue unless it's full, in which case drop it + */ + if (error == -EAGAIN) { + if (!audit_backlog_limit || + skb_queue_len(&audit_retry_queue) < audit_backlog_limit) { + skb_queue_tail(&audit_retry_queue, skb); + return; + } + audit_log_lost("kauditd retry queue overflow"); + goto drop; }
- /* if we have room, queue the message */ + /* if we have room in the hold queue, queue the message */ if (!audit_backlog_limit || skb_queue_len(&audit_hold_queue) < audit_backlog_limit) { skb_queue_tail(&audit_hold_queue, skb); @@ -585,24 +599,32 @@ static void kauditd_hold_skb(struct sk_buff *skb)
/* we have no other options - drop the message */ audit_log_lost("kauditd hold queue overflow"); +drop: kfree_skb(skb); }
/** * kauditd_retry_skb - Queue an audit record, attempt to send again to auditd * @skb: audit record + * @error: error code (unused) * * Description: * Not as serious as kauditd_hold_skb() as we still have a connected auditd, * but for some reason we are having problems sending it audit records so * queue the given record and attempt to resend. */ -static void kauditd_retry_skb(struct sk_buff *skb) +static void kauditd_retry_skb(struct sk_buff *skb, __always_unused int error) { - /* NOTE: because records should only live in the retry queue for a - * short period of time, before either being sent or moved to the hold - * queue, we don't currently enforce a limit on this queue */ - skb_queue_tail(&audit_retry_queue, skb); + if (!audit_backlog_limit || + skb_queue_len(&audit_retry_queue) < audit_backlog_limit) { + skb_queue_tail(&audit_retry_queue, skb); + return; + } + + /* we have to drop the record, send it via printk as a last effort */ + kauditd_printk_skb(skb); + audit_log_lost("kauditd retry queue overflow"); + kfree_skb(skb); }
/** @@ -640,7 +662,7 @@ static void auditd_reset(const struct auditd_connection *ac) /* flush the retry queue to the hold queue, but don't touch the main * queue since we need to process that normally for multicast */ while ((skb = skb_dequeue(&audit_retry_queue))) - kauditd_hold_skb(skb); + kauditd_hold_skb(skb, -ECONNREFUSED); }
/** @@ -714,16 +736,18 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, struct sk_buff_head *queue, unsigned int retry_limit, void (*skb_hook)(struct sk_buff *skb), - void (*err_hook)(struct sk_buff *skb)) + void (*err_hook)(struct sk_buff *skb, int error)) { int rc = 0; - struct sk_buff *skb; + struct sk_buff *skb = NULL; + struct sk_buff *skb_tail; unsigned int failed = 0;
/* NOTE: kauditd_thread takes care of all our locking, we just use * the netlink info passed to us (e.g. sk and portid) */
- while ((skb = skb_dequeue(queue))) { + skb_tail = skb_peek_tail(queue); + while ((skb != skb_tail) && (skb = skb_dequeue(queue))) { /* call the skb_hook for each skb we touch */ if (skb_hook) (*skb_hook)(skb); @@ -731,7 +755,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, /* can we send to anyone via unicast? */ if (!sk) { if (err_hook) - (*err_hook)(skb); + (*err_hook)(skb, -ECONNREFUSED); continue; }
@@ -745,7 +769,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, rc == -ECONNREFUSED || rc == -EPERM) { sk = NULL; if (err_hook) - (*err_hook)(skb); + (*err_hook)(skb, rc); if (rc == -EAGAIN) rc = 0; /* continue to drain the queue */
From: Peng Liu liupeng256@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4V388 CVE: NA
--------------------------------
Patch "kfence: Add a module parameter to adjust kfence objects" enable dynamic configuration of the number of KFENCE guarded objects, but the size of alloc_covered is not the same with the original kfence. This is because const_ilog2 is just valid for a constant, and KFENCE_NR_OBJECTS is not a constant when enabling dynamic configuration.
This difference between original kfence will lead to a confusion loggic in the process of skipping covered path. In a arm64 machine, the following panic is observed.
Call trace: __kfence_alloc+0x378/0x780 kmem_cache_alloc+0x204/0x614 getname_kernel+0x38/0xf4 filp_open+0x2c/0x6c populate_rootfs+0xcc/0x174 do_one_initcall+0xac/0x20c kernel_init_freeable+0x380/0x3c8 kernel_init+0x18/0xf0 ret_from_fork+0x10/0x18 Code: 54000080 a9400381 f9000420 f9000001 (f900039c) ---[ end trace 814fe40d608e1b74 ]--- Kernel panic - not syncing: TLB conflict abort: Fatal exception
To fix this, ilog2 is used to replace const_ilog2 when enable dynamic configuration of KFENCE guarded objects.
Fixes: 901b983c886b ("kfence: Add a module parameter to adjust kfence objects") Signed-off-by: Peng Liu liupeng256@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/kfence/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 3a559f0f282d..98f5317368be 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -146,6 +146,8 @@ module_param_cb(num_objects, &num_objects_param_ops, &kfence_num_objects, 0600); * backing pages (in __kfence_pool). */ #ifdef CONFIG_KFENCE_DYNAMIC_OBJECTS +#define ILOG2(x) (ilog2((x))) + struct kfence_metadata *kfence_metadata; static phys_addr_t metadata_size;
@@ -155,6 +157,8 @@ static inline bool kfence_metadata_valid(void) }
#else +#define ILOG2(x) (const_ilog2((x))) + static_assert(CONFIG_KFENCE_NUM_OBJECTS > 0); struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS];
@@ -185,7 +189,7 @@ atomic_t kfence_allocation_gate = ATOMIC_INIT(1); * P(alloc_traces) = (1 - e^(-HNUM * (alloc_traces / SIZE)) ^ HNUM */ #define ALLOC_COVERED_HNUM 2 -#define ALLOC_COVERED_ORDER (const_ilog2(KFENCE_NR_OBJECTS) + 2) +#define ALLOC_COVERED_ORDER (ILOG2(KFENCE_NR_OBJECTS) + 2) #define ALLOC_COVERED_SIZE (1 << ALLOC_COVERED_ORDER) #define ALLOC_COVERED_HNEXT(h) hash_32(h, ALLOC_COVERED_ORDER) #define ALLOC_COVERED_MASK (ALLOC_COVERED_SIZE - 1) @@ -831,7 +835,7 @@ static int __init kfence_dynamic_init(void) return -ENOMEM; }
- covered_size = sizeof(atomic_t) * KFENCE_NR_OBJECTS; + covered_size = sizeof(atomic_t) * ALLOC_COVERED_SIZE; alloc_covered = memblock_alloc(covered_size, PAGE_SIZE); if (!alloc_covered) { memblock_free((phys_addr_t)kfence_metadata, metadata_size);
From: Liu Shixin liushixin2@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4XWBS
--------------------------------
This reverts commit d3d0ca13f958d359c80c8719b23cd7367eb881f2
We found that this patch may lead to a TLB conflicts abort. This may results by the changes from block<->table mappings. This problem may have something to do with the Break-Before-Make sequence rule but not yet clear.
Signed-off-by: Liu Shixin liushixin2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/include/asm/kfence.h | 70 +-------------------------------- arch/arm64/mm/mmu.c | 6 ++- 2 files changed, 5 insertions(+), 71 deletions(-)
diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h index 322e95bc228d..d061176d57ea 100644 --- a/arch/arm64/include/asm/kfence.h +++ b/arch/arm64/include/asm/kfence.h @@ -8,77 +8,9 @@ #ifndef __ASM_KFENCE_H #define __ASM_KFENCE_H
-#include <linux/kfence.h> #include <asm/cacheflush.h> -#include <asm/pgalloc.h>
-static inline int split_pud_page(pud_t *pud, unsigned long addr) -{ - int i; - pmd_t *pmd = pmd_alloc_one(&init_mm, addr); - unsigned long pfn = PFN_DOWN(__pa(addr)); - - if (!pmd) - return -ENOMEM; - - for (i = 0; i < PTRS_PER_PMD; i++) - set_pmd(pmd + i, pmd_mkhuge(pfn_pmd(pfn + i * PTRS_PER_PTE, PAGE_KERNEL))); - - smp_wmb(); /* See comment in __pte_alloc */ - pud_populate(&init_mm, pud, pmd); - - flush_tlb_kernel_range(addr, addr + PUD_SIZE); - return 0; -} - -static inline int split_pmd_page(pmd_t *pmd, unsigned long addr) -{ - int i; - pte_t *pte = pte_alloc_one_kernel(&init_mm); - unsigned long pfn = PFN_DOWN(__pa(addr)); - - if (!pte) - return -ENOMEM; - - for (i = 0; i < PTRS_PER_PTE; i++) - set_pte(pte + i, pfn_pte(pfn + i, PAGE_KERNEL)); - - smp_wmb(); /* See comment in __pte_alloc */ - pmd_populate_kernel(&init_mm, pmd, pte); - - flush_tlb_kernel_range(addr, addr + PMD_SIZE); - return 0; -} - -static inline bool arch_kfence_init_pool(void) -{ - unsigned long addr; - pgd_t *pgd; - p4d_t *p4d; - pud_t *pud; - pmd_t *pmd; - - for (addr = (unsigned long)__kfence_pool; is_kfence_address((void *)addr); - addr += PAGE_SIZE) { - pgd = pgd_offset(&init_mm, addr); - if (pgd_leaf(*pgd)) - return false; - p4d = p4d_offset(pgd, addr); - if (p4d_leaf(*p4d)) - return false; - pud = pud_offset(p4d, addr); - if (pud_leaf(*pud)) { - if (split_pud_page(pud, addr & PUD_MASK)) - return false; - } - pmd = pmd_offset(pud, addr); - if (pmd_leaf(*pmd)) { - if (split_pmd_page(pmd, addr & PMD_MASK)) - return false; - } - } - return true; -} +static inline bool arch_kfence_init_pool(void) { return true; }
static inline bool kfence_protect_page(unsigned long addr, bool protect) { diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index a318b702805a..c193309ef8e5 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -492,7 +492,8 @@ static void __init map_mem(pgd_t *pgdp) int flags = 0; u64 i;
- if (rodata_full || crash_mem_map || debug_pagealloc_enabled()) + if (rodata_full || crash_mem_map || debug_pagealloc_enabled() || + IS_ENABLED(CONFIG_KFENCE)) flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
/* @@ -1457,7 +1458,8 @@ int arch_add_memory(int nid, u64 start, u64 size, * KFENCE requires linear map to be mapped at page granularity, so that * it is possible to protect/unprotect single pages in the KFENCE pool. */ - if (rodata_full || debug_pagealloc_enabled()) + if (rodata_full || debug_pagealloc_enabled() || + IS_ENABLED(CONFIG_KFENCE)) flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
From: Jisheng Zhang Jisheng.Zhang@synaptics.com
maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4XWBS
Reference: https://lore.kernel.org/all/20210524172433.015b3b6b@xhacker.debian/
--------------------------------
Jisheng Zhang has another way of saving memory, we combine his two patches into one and made some adaptations with dynamic kfence objects.
Description of the original patch:
Some architectures may want to allocate the __kfence_pool differently for example, allocate the __kfence_pool earlier before paging_init(). We also delay the memset() to kfence_init_pool().
KFENCE requires linear map to be mapped at page granularity, so that it is possible to protect/unprotect single pages in the KFENCE pool. Currently if KFENCE is enabled, arm64 maps all pages at page granularity, it seems overkilled. In fact, we only need to map the pages in KFENCE pool itself at page granularity. We acchieve this goal by allocating KFENCE pool before paging_init() so we know the KFENCE pool address, then we take care to map the pool at page granularity during map_mem().
Signed-off-by: Jisheng Zhang Jisheng.Zhang@synaptics.com Signed-off-by: Liu Shixin liushixin2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/include/asm/kfence.h | 8 +++++++- arch/arm64/kernel/setup.c | 3 +++ arch/arm64/mm/mmu.c | 34 +++++++++++++++++++++++++-------- include/linux/kfence.h | 2 ++ mm/kfence/core.c | 22 +++++++++++++++++++-- 5 files changed, 58 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h index d061176d57ea..64d7cbfe067b 100644 --- a/arch/arm64/include/asm/kfence.h +++ b/arch/arm64/include/asm/kfence.h @@ -8,9 +8,15 @@ #ifndef __ASM_KFENCE_H #define __ASM_KFENCE_H
+#include <linux/kfence.h> #include <asm/cacheflush.h>
-static inline bool arch_kfence_init_pool(void) { return true; } +static inline bool arch_kfence_init_pool(void) +{ + memset(__kfence_pool, 0, KFENCE_POOL_SIZE); + + return true; +}
static inline bool kfence_protect_page(unsigned long addr, bool protect) { diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 3c834d7c299a..08198b824846 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -18,6 +18,7 @@ #include <linux/screen_info.h> #include <linux/init.h> #include <linux/kexec.h> +#include <linux/kfence.h> #include <linux/root_dev.h> #include <linux/cpu.h> #include <linux/interrupt.h> @@ -387,6 +388,8 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
arm64_memblock_init();
+ kfence_early_alloc_pool(); + efi_fake_memmap(); efi_find_mirror();
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index c193309ef8e5..c01dc4bb6faa 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/kexec.h> +#include <linux/kfence.h> #include <linux/libfdt.h> #include <linux/mman.h> #include <linux/nodemask.h> @@ -492,10 +493,19 @@ static void __init map_mem(pgd_t *pgdp) int flags = 0; u64 i;
- if (rodata_full || crash_mem_map || debug_pagealloc_enabled() || - IS_ENABLED(CONFIG_KFENCE)) + if (rodata_full || crash_mem_map || debug_pagealloc_enabled()) flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
+#ifdef CONFIG_KFENCE + /* + * KFENCE requires linear map to be mapped at page granularity, so + * temporarily skip mapping for __kfence_pool in the following + * for-loop + */ + if (__kfence_pool) + memblock_mark_nomap(__pa(__kfence_pool), KFENCE_POOL_SIZE); +#endif + /* * Take care not to create a writable alias for the * read-only text and rodata sections of the kernel image. @@ -530,6 +540,19 @@ static void __init map_mem(pgd_t *pgdp) __map_memblock(pgdp, kernel_start, kernel_end, PAGE_KERNEL, NO_CONT_MAPPINGS); memblock_clear_nomap(kernel_start, kernel_end - kernel_start); + +#ifdef CONFIG_KFENCE + /* + * Map the __kfence_pool at page granularity now. + */ + if (__kfence_pool) { + __map_memblock(pgdp, __pa(__kfence_pool), + __pa(__kfence_pool + KFENCE_POOL_SIZE), + pgprot_tagged(PAGE_KERNEL), + NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS); + memblock_clear_nomap(__pa(__kfence_pool), KFENCE_POOL_SIZE); + } +#endif }
void mark_rodata_ro(void) @@ -1454,12 +1477,7 @@ int arch_add_memory(int nid, u64 start, u64 size, }
- /* - * KFENCE requires linear map to be mapped at page granularity, so that - * it is possible to protect/unprotect single pages in the KFENCE pool. - */ - if (rodata_full || debug_pagealloc_enabled() || - IS_ENABLED(CONFIG_KFENCE)) + if (rodata_full || debug_pagealloc_enabled()) flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start), diff --git a/include/linux/kfence.h b/include/linux/kfence.h index f77b0e4de937..6486c3dcac36 100644 --- a/include/linux/kfence.h +++ b/include/linux/kfence.h @@ -65,6 +65,7 @@ static __always_inline bool is_kfence_address(const void *addr) return unlikely((unsigned long)((char *)addr - __kfence_pool) < KFENCE_POOL_SIZE && __kfence_pool); }
+void __init kfence_early_alloc_pool(void); /** * kfence_alloc_pool() - allocate the KFENCE pool via memblock */ @@ -214,6 +215,7 @@ bool __must_check kfence_handle_page_fault(unsigned long addr, bool is_write, st #else /* CONFIG_KFENCE */
static inline bool is_kfence_address(const void *addr) { return false; } +static inline void kfence_early_alloc_pool(void) { } static inline void kfence_alloc_pool(void) { } static inline void kfence_init(void) { } static inline void kfence_shutdown_cache(struct kmem_cache *s) { } diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 98f5317368be..2454b1c57fb1 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -860,16 +860,34 @@ static void __init kfence_dynamic_destroy(void) { } #endif
/* === Public interface ===================================================== */ +void __init kfence_early_alloc_pool(void) +{ + if (!kfence_sample_interval) + return; + + __kfence_pool = memblock_alloc_raw(KFENCE_POOL_SIZE, PAGE_SIZE); + + if (!__kfence_pool) { + kfence_sample_interval = 0; + pr_err("failed to early allocate pool, disable KFENCE\n"); + } +}
void __init kfence_alloc_pool(void) { if (!kfence_sample_interval) return;
- if (kfence_dynamic_init()) + if (kfence_dynamic_init()) { + if (__kfence_pool) { + memblock_free(__pa(__kfence_pool), KFENCE_POOL_SIZE); + __kfence_pool = NULL; + } return; + }
- __kfence_pool = memblock_alloc(KFENCE_POOL_SIZE, PAGE_SIZE); + if (!__kfence_pool) + __kfence_pool = memblock_alloc(KFENCE_POOL_SIZE, PAGE_SIZE); if (!__kfence_pool) { pr_err("failed to allocate pool\n"); kfence_dynamic_destroy();
From: Arnaldo Carvalho de Melo acme@redhat.com
mainline inclusion from mainline-v5.14-rc2 commit d08c84e01afa7a7eee6badab25d5420fa847f783 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4Y3D0
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------
In fedora rawhide the PTHREAD_STACK_MIN define may end up expanded to a sysconf() call, and that will return 'long int', breaking the build:
45 fedora:rawhide : FAIL gcc version 11.1.1 20210623 (Red Hat 11.1.1-6) (GCC) builtin-sched.c: In function 'create_tasks': /git/perf-5.14.0-rc1/tools/include/linux/kernel.h:43:24: error: comparison of distinct pointer types lacks a cast [-Werror] 43 | (void) (&_max1 == &_max2); \ | ^~ builtin-sched.c:673:34: note: in expansion of macro 'max' 673 | (size_t) max(16 * 1024, PTHREAD_STACK_MIN)); | ^~~ cc1: all warnings being treated as errors
$ grep __sysconf /usr/include/*/*.h /usr/include/bits/pthread_stack_min-dynamic.h:extern long int __sysconf (int __name) __THROW; /usr/include/bits/pthread_stack_min-dynamic.h:# define PTHREAD_STACK_MIN __sysconf (__SC_THREAD_STACK_MIN_VALUE) /usr/include/bits/time.h:extern long int __sysconf (int); /usr/include/bits/time.h:# define CLK_TCK ((__clock_t) __sysconf (2)) /* 2 is _SC_CLK_TCK */ $
So cast it to int to cope with that.
Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zou Wei zou_wei@huawei.com Reviewed-by: Yang Jihong yangjihong1@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- tools/perf/builtin-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index d3b5f5faf8c1..02e5774cabb6 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -670,7 +670,7 @@ static void create_tasks(struct perf_sched *sched) err = pthread_attr_init(&attr); BUG_ON(err); err = pthread_attr_setstacksize(&attr, - (size_t) max(16 * 1024, PTHREAD_STACK_MIN)); + (size_t) max(16 * 1024, (int)PTHREAD_STACK_MIN)); BUG_ON(err); err = pthread_mutex_lock(&sched->start_work_mutex); BUG_ON(err);
From: Chengguang Xu cgxu519@mykernel.net
mainline inclusion from mainline-v5.11-rc1 commit c11faf32599fee59f33896c8d59f9b3c17ca76fc category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4Y3CE?from=project-issue CVE: NA
--------------------------------
In metacopy case, we should use ovl_inode_realdata() instead of ovl_inode_real() to get real inode which has data, so that we can get correct information of extentes in ->fiemap operation.
Signed-off-by: Chengguang Xu cgxu519@mykernel.net Reviewed-by: Amir Goldstein amir73il@gmail.com Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Zheng Liang zhengliang6@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/overlayfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 4fadafd8bdc1..d7a410d83743 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -478,7 +478,7 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { int err; - struct inode *realinode = ovl_inode_real(inode); + struct inode *realinode = ovl_inode_realdata(inode); const struct cred *old_cred;
if (!realinode->i_op->fiemap)
From: Lakshmi Ramasubramanian nramas@linux.microsoft.com
mainline inclusion from mainline-v5.16-rc6 commit 9c5d89bc10551f1aecd768b00fca3339a7b8c8ee category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4Y3UC
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Since commit ac10be5cdbfa ("arm64: Use common of_kexec_alloc_and_setup_fdt()"), smatch reports the following warning:
arch/arm64/kernel/machine_kexec_file.c:152 load_other_segments() warn: missing error code 'ret'
Return code is not set to an error code in load_other_segments() when of_kexec_alloc_and_setup_fdt() call returns a NULL dtb. This results in status success (return code set to 0) being returned from load_other_segments().
Set return code to -EINVAL if of_kexec_alloc_and_setup_fdt() returns NULL dtb.
Signed-off-by: Lakshmi Ramasubramanian nramas@linux.microsoft.com Reported-by: kernel test robot lkp@intel.com Reported-by: Dan Carpenter dan.carpenter@oracle.com Fixes: ac10be5cdbfa ("arm64: Use common of_kexec_alloc_and_setup_fdt()") Link: https://lore.kernel.org/r/20211210010121.101823-1-nramas@linux.microsoft.com Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Li Huafei lihuafei1@huawei.com Reviewed-by: Xu Kuohai xukuohai@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/kernel/machine_kexec_file.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c index 63634b4d72c1..59c648d51848 100644 --- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c @@ -149,6 +149,7 @@ int load_other_segments(struct kimage *image, initrd_len, cmdline, 0); if (!dtb) { pr_err("Preparing for new dtb failed\n"); + ret = -EINVAL; goto out_err; }
From: Ding Hui dinghui@sangfor.com.cn
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I3BNT6 CVE: NA
-----------------------------------------------
We can get a crash when disconnecting the iSCSI session, the call trace like this:
[ffff00002a00fb70] kfree at ffff00000830e224 [ffff00002a00fba0] ses_intf_remove at ffff000001f200e4 [ffff00002a00fbd0] device_del at ffff0000086b6a98 [ffff00002a00fc50] device_unregister at ffff0000086b6d58 [ffff00002a00fc70] __scsi_remove_device at ffff00000870608c [ffff00002a00fca0] scsi_remove_device at ffff000008706134 [ffff00002a00fcc0] __scsi_remove_target at ffff0000087062e4 [ffff00002a00fd10] scsi_remove_target at ffff0000087064c0 [ffff00002a00fd70] __iscsi_unbind_session at ffff000001c872c4 [ffff00002a00fdb0] process_one_work at ffff00000810f35c [ffff00002a00fe00] worker_thread at ffff00000810f648 [ffff00002a00fe70] kthread at ffff000008116e98
In ses_intf_add, components count could be 0, and kcalloc 0 size scomp, but not saved in edev->component[i].scratch
In this situation, edev->component[0].scratch is an invalid pointer, when kfree it in ses_intf_remove_enclosure, a crash like above would happen The call trace also could be other random cases when kfree cannot catch the invalid pointer
We should not use edev->component[] array when the components count is 0 We also need check index when use edev->component[] array in ses_enclosure_data_process
Another fix option is report error and do not attach in ses_intf_add if we meet a zero component enclosure
Tested-by: Zeng Zhicong timmyzeng@163.com Signed-off-by: Ding Hui dinghui@sangfor.com.cn Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/scsi/ses.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 0a1734f34587..119a51015643 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -491,9 +491,6 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev, int i; struct ses_component *scomp;
- if (!edev->component[0].scratch) - return 0; - for (i = 0; i < edev->components; i++) { scomp = edev->component[i].scratch; if (scomp->addr != efd->addr) @@ -579,8 +576,10 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, components++, type_ptr[0], name); - else + else if (components < edev->components) ecomp = &edev->component[components++]; + else + ecomp = ERR_PTR(-EINVAL);
if (!IS_ERR(ecomp)) { if (addl_desc_ptr) @@ -745,9 +744,11 @@ static int ses_intf_add(struct device *cdev, buf = NULL; } page2_not_supported: - scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); - if (!scomp) - goto err_free; + if (components > 0) { + scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); + if (!scomp) + goto err_free; + }
edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev), components, &ses_enclosure_callbacks); @@ -827,7 +828,8 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev) kfree(ses_dev->page2); kfree(ses_dev);
- kfree(edev->component[0].scratch); + if (edev->components > 0) + kfree(edev->component[0].scratch);
put_device(&edev->edev); enclosure_unregister(edev);