hulk inclusion category: bugfix bugzilla: 51349 CVE: NA
-------------------------------------------------
This patchset https://patchwork.kernel.org/project/linux-block/cover/20190826111627.7505-1... will cause perfmance regression, so revert it and use another way to fix the warning introduced by fix CVE-2021-27365.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/slab_common.c | 4 ++-- mm/slub.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/mm/slab_common.c b/mm/slab_common.c index b8b0df81bece3..321a9abed5d9d 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1259,8 +1259,8 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) page = alloc_pages(flags, order); if (likely(page)) { ret = page_address(page); - mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE, - PAGE_SIZE << order); + mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, + 1 << order); } kmemleak_alloc(ret, size, 1, flags); kasan_kmalloc_large(ret, size, flags); diff --git a/mm/slub.c b/mm/slub.c index 12f23ceab1177..0d69d5b3ceefe 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3799,8 +3799,8 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node) page = alloc_pages_node(node, flags, order); if (page) { ptr = page_address(page); - mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE, - PAGE_SIZE << order); + mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, + 1 << order); }
kmalloc_large_node_hook(ptr, size, flags); @@ -3940,8 +3940,8 @@ void kfree(const void *x)
BUG_ON(!PageCompound(page)); kfree_hook(object); - mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE, - -(PAGE_SIZE << order)); + mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, + -(1 << order)); __free_pages(page, order); return; }
hulk inclusion category: bugfix bugzilla: 51349 CVE: NA
-------------------------------------------------
This patchset https://patchwork.kernel.org/project/linux-block/cover/20190826111627.7505-1... will cause perfmance regression, so revert it and use another way to fix the warning introduced by fix CVE-2021-27365.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/slab_common.c | 8 ++------ mm/slob.c | 20 ++++---------------- mm/slub.c | 14 +++----------- 3 files changed, 9 insertions(+), 33 deletions(-)
diff --git a/mm/slab_common.c b/mm/slab_common.c index 321a9abed5d9d..6b1cbf89a6861 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1252,16 +1252,12 @@ void __init create_kmalloc_caches(slab_flags_t flags) */ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) { - void *ret = NULL; + void *ret; struct page *page;
flags |= __GFP_COMP; page = alloc_pages(flags, order); - if (likely(page)) { - ret = page_address(page); - mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, - 1 << order); - } + ret = page ? page_address(page) : NULL; kmemleak_alloc(ret, size, 1, flags); kasan_kmalloc_large(ret, size, flags); return ret; diff --git a/mm/slob.c b/mm/slob.c index 8165d90db1adc..fdf284009be92 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -190,7 +190,7 @@ static int slob_last(slob_t *s)
static void *slob_new_pages(gfp_t gfp, int order, int node) { - struct page *page; + void *page;
#ifdef CONFIG_NUMA if (node != NUMA_NO_NODE) @@ -202,21 +202,14 @@ static void *slob_new_pages(gfp_t gfp, int order, int node) if (!page) return NULL;
- mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, - 1 << order); return page_address(page); }
static void slob_free_pages(void *b, int order) { - struct page *sp = virt_to_page(b); - if (current->reclaim_state) current->reclaim_state->reclaimed_slab += 1 << order; - - mod_node_page_state(page_pgdat(sp), NR_SLAB_UNRECLAIMABLE, - -(1 << order)); - __free_pages(sp, order); + free_pages((unsigned long)b, order); }
/* @@ -524,13 +517,8 @@ void kfree(const void *block) int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); - } else { - unsigned int order = compound_order(sp); - mod_node_page_state(page_pgdat(sp), NR_SLAB_UNRECLAIMABLE, - -(1 << order)); - __free_pages(sp, order); - - } + } else + __free_pages(sp, compound_order(sp)); } EXPORT_SYMBOL(kfree);
diff --git a/mm/slub.c b/mm/slub.c index 0d69d5b3ceefe..af7343a744091 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3793,15 +3793,11 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node) { struct page *page; void *ptr = NULL; - unsigned int order = get_order(size);
flags |= __GFP_COMP; - page = alloc_pages_node(node, flags, order); - if (page) { + page = alloc_pages_node(node, flags, get_order(size)); + if (page) ptr = page_address(page); - mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, - 1 << order); - }
kmalloc_large_node_hook(ptr, size, flags); return ptr; @@ -3936,13 +3932,9 @@ void kfree(const void *x)
page = virt_to_head_page(x); if (unlikely(!PageSlab(page))) { - unsigned int order = compound_order(page); - BUG_ON(!PageCompound(page)); kfree_hook(object); - mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE, - -(1 << order)); - __free_pages(page, order); + __free_pages(page, compound_order(page)); return; } slab_free(page->slab_cache, page, object, NULL, 1, _RET_IP_);
hulk inclusion category: bugfix bugzilla: 51349 CVE: NA
-------------------------------------------------
This patchset https://patchwork.kernel.org/project/linux-block/cover/20190826111627.7505-1... will cause perfmance regression, so revert it and use another way to fix the warning introduced by fix CVE-2021-27365.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/slab.h | 4 ---- mm/slab_common.c | 11 +---------- mm/slob.c | 41 +++++++++++------------------------------ 3 files changed, 12 insertions(+), 44 deletions(-)
diff --git a/include/linux/slab.h b/include/linux/slab.h index 5785b836e9fd7..788f04a7ca766 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -492,10 +492,6 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags) * kmalloc is the normal method of allocating memory * for objects smaller than page size in the kernel. * - * The allocated object address is aligned to at least ARCH_KMALLOC_MINALIGN - * bytes. For @size of power of two bytes, the alignment is also guaranteed - * to be at least to the size. - * * The @flags argument may be one of: * * %GFP_USER - Allocate memory on behalf of user. May sleep. diff --git a/mm/slab_common.c b/mm/slab_common.c index 6b1cbf89a6861..d208b47e01a8e 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -999,19 +999,10 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, unsigned int useroffset, unsigned int usersize) { int err; - unsigned int align = ARCH_KMALLOC_MINALIGN;
s->name = name; s->size = s->object_size = size; - - /* - * For power of two sizes, guarantee natural alignment for kmalloc - * caches, regardless of SL*B debugging options. - */ - if (is_power_of_2(size)) - align = max(align, size); - s->align = calculate_alignment(flags, align, size); - + s->align = calculate_alignment(flags, ARCH_KMALLOC_MINALIGN, size); s->useroffset = useroffset; s->usersize = usersize;
diff --git a/mm/slob.c b/mm/slob.c index fdf284009be92..307c2c9feb441 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -215,7 +215,7 @@ static void slob_free_pages(void *b, int order) /* * Allocate a slob block within a given slob_page sp. */ -static void *slob_page_alloc(struct page *sp, size_t size, int align, int align_offset) +static void *slob_page_alloc(struct page *sp, size_t size, int align) { slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); @@ -223,17 +223,8 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align, int align_ for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { slobidx_t avail = slob_units(cur);
- /* - * 'aligned' will hold the address of the slob block so that the - * address 'aligned'+'align_offset' is aligned according to the - * 'align' parameter. This is for kmalloc() which prepends the - * allocated block with its size, so that the block itself is - * aligned when needed. - */ if (align) { - aligned = (slob_t *) - (ALIGN((unsigned long)cur + align_offset, align) - - align_offset); + aligned = (slob_t *)ALIGN((unsigned long)cur, align); delta = aligned - cur; } if (avail >= units + delta) { /* room enough? */ @@ -275,8 +266,7 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align, int align_ /* * slob_alloc: entry point into the slob allocator. */ -static void *slob_alloc(size_t size, gfp_t gfp, int align, int node, - int align_offset) +static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { struct page *sp; struct list_head *prev; @@ -308,7 +298,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node,
/* Attempt to alloc */ prev = sp->lru.prev; - b = slob_page_alloc(sp, size, align, align_offset); + b = slob_page_alloc(sp, size, align); if (!b) continue;
@@ -336,7 +326,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node, INIT_LIST_HEAD(&sp->lru); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); - b = slob_page_alloc(sp, size, align, align_offset); + b = slob_page_alloc(sp, size, align); BUG_ON(!b); spin_unlock_irqrestore(&slob_lock, flags); } @@ -438,7 +428,7 @@ static __always_inline void * __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) { unsigned int *m; - int minalign = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); void *ret;
gfp &= gfp_allowed_mask; @@ -446,28 +436,19 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) fs_reclaim_acquire(gfp); fs_reclaim_release(gfp);
- if (size < PAGE_SIZE - minalign) { - int align = minalign; - - /* - * For power of two sizes, guarantee natural alignment for - * kmalloc()'d objects. - */ - if (is_power_of_2(size)) - align = max(minalign, (int) size); - + if (size < PAGE_SIZE - align) { if (!size) return ZERO_SIZE_PTR;
- m = slob_alloc(size + minalign, gfp, align, node, minalign); + m = slob_alloc(size + align, gfp, align, node);
if (!m) return NULL; *m = size; - ret = (void *)m + minalign; + ret = (void *)m + align;
trace_kmalloc_node(caller, ret, - size, size + minalign, gfp, node); + size, size + align, gfp, node); } else { unsigned int order = get_order(size);
@@ -563,7 +544,7 @@ static void *slob_alloc_node(struct kmem_cache *c, gfp_t flags, int node) fs_reclaim_release(flags);
if (c->size < PAGE_SIZE) { - b = slob_alloc(c->size, flags, c->align, node, 0); + b = slob_alloc(c->size, flags, c->align, node); trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, SLOB_UNITS(c->size) * SLOB_UNIT, flags, node);
From: Zheng Yejian zhengyejian1@huawei.com
hulk inclusion category: bugfix bugzilla: 51349 CVE: CVE-2021-27365 ---------------------------
sysfs_emit and sysfs_emit_at have a constraint that output buffer should be alignment with PAGE_SIZE, but currently we can not guarantee it since 59bb47985c1d ("mm, sl[aou]b: guarantee natural alignment for kmalloc(power-of-two)") is not merged.
This may lead to an unexpected warning when execute like: 'cat /sys/class/iscsi_transport/tcp/handle'.
As for the necessity of the address alignment constraint, Joe Perches (the code author) wrote that: > It's to make sure it's a PAGE_SIZE aligned buffer. > It's just so it would not be misused/abused in non-sysfs derived cases.
So we'll not need to introduce 59bb47985c1d ("mm, sl[aou]b: guarantee natural alignment for kmalloc(power-of-two)") but just remove the address alignment constraint.
For more discussions of the issue, see: https://www.spinics.net/lists/stable/msg455428.html
Signed-off-by: Zheng Yejian zhengyejian1@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/sysfs/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 74de104f8f33f..c678fd5f01bfb 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -574,7 +574,7 @@ int sysfs_emit(char *buf, const char *fmt, ...) va_list args; int len;
- if (WARN(!buf || offset_in_page(buf), + if (WARN(!buf, "invalid sysfs_emit: buf:%p\n", buf)) return 0;
@@ -602,7 +602,7 @@ int sysfs_emit_at(char *buf, int at, const char *fmt, ...) va_list args; int len;
- if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE, + if (WARN(!buf || at < 0 || at >= PAGE_SIZE, "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at)) return 0;
From: Zhou Guanghui zhouguanghui1@huawei.com
ascend inclusion category: feature bugzilla: NA CVE: NA
-------------------------------------------------------
In the share pool scenario, when the shared memory is applied for, the do_mm_populate function is performed at the same time, that is, the corresponding pages are allocated. In the current share pool implementation, the memory is charged to the memcg of the first task added to this share pool group.
This is unreasonable and may cause memcg of first task oom. So, we should charge the pages to the memcg of current task.
Signed-off-by: Zhou Guanghui zhouguanghui1@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/shmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c index 8a41ab86152c5..bd20f3c601bd6 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -36,6 +36,7 @@ #include <linux/uio.h> #include <linux/khugepaged.h> #include <linux/hugetlb.h> +#include <linux/share_pool.h>
#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */
@@ -1769,7 +1770,8 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, * bring it back from swap or allocate. */ sbinfo = SHMEM_SB(inode->i_sb); - charge_mm = vma ? vma->vm_mm : current->mm; + charge_mm = vma && !sp_check_vm_share_pool(vma->vm_flags) ? + vma->vm_mm : current->mm;
if (swap.val) { /* Look it up and read it in.. */