From: liubo liubo254@huawei.com
euleros inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GN7K CVE: NA
-------------------------------- In the do_swapcache_reclaim interface, there is a slab-out-of-bounds kasan problem;
The reason for the problem is that when list_for_each_entry_safe_reverse_from traverses the LRU linked list, it does not consider that next may be equal to the head address, which may lead to the head address being accessed as the page address, causing problems.
In response to the above problems, add a judgment about whether pos is head.
Signed-off-by: liubo liubo254@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: wangkefeng wangkefeng.wang@huawei.com Signed-off-by: Laibin Qiu qiulaibin@huawei.com --- mm/vmscan.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c index 42f24473756b..011827f666cc 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4555,7 +4555,6 @@ EXPORT_SYMBOL_GPL(get_page_from_vaddr); static int add_page_for_reclaim_swapcache(struct page *page, struct list_head *pagelist, struct lruvec *lruvec, enum lru_list lru) { - struct list_head *src = &lruvec->lists[lru]; struct page *head;
/* If the page is mapped by more than one process, do not swap it */ @@ -4574,7 +4573,6 @@ static int add_page_for_reclaim_swapcache(struct page *page, reliable_lru_add(lru, head, -hpage_nr_pages(head)); break; case -EBUSY: - list_move(&head->lru, src); return -1; default: break; @@ -4744,7 +4742,7 @@ int do_swapcache_reclaim(unsigned long *swapcache_watermark, * check if pos page is been released or not in LRU list, if true, * cancel the subsequent page scanning of the current node. */ - if (!pos) { + if (!pos || &pos->lru == src) { spin_unlock_irq(&pgdat->lru_lock); continue; }
From: liubo liubo254@huawei.com
euleros inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GN7K CVE: NA
-------------------------------- In the do_swapcache_reclaim interface, there are the following local variables.
unsigned long nr[MAX_NUMNODES], unsigned long nr_to_reclaim[MAX_NUMNODES], struct list_head swapcache_list[MAX_NUMNODES],
In the kernel, MAX_NUMNODES is defined as follows:
Under the x86_64 architecture, CONFIG_NODES_SHIFT is defined as follows: CONFIG_NODES_SHIFT=10
Therefore, under the X86_64 architecture, local variables may cause kernel stack overflow.
Modify the above variable acquisition method and change it to dynamic application.
Signed-off-by: liubo liubo254@huawei.com Reviewed-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: wangkefeng wangkefeng.wang@huawei.com Signed-off-by: Laibin Qiu qiulaibin@huawei.com --- mm/vmscan.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c index 011827f666cc..f5671facdc51 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4670,12 +4670,12 @@ int do_swapcache_reclaim(unsigned long *swapcache_watermark, int err = -EINVAL; unsigned long swapcache_to_reclaim = 0; unsigned long nr_reclaimed = 0; - unsigned long nr[MAX_NUMNODES] = {0}; - unsigned long nr_to_reclaim[MAX_NUMNODES] = {0}; unsigned long swapcache_total_reclaimable = 0; unsigned long reclaim_page_count = 0;
- struct list_head swapcache_list[MAX_NUMNODES]; + unsigned long *nr = NULL; + unsigned long *nr_to_reclaim = NULL; + struct list_head *swapcache_list = NULL;
int nid = 0; struct lruvec *lruvec = NULL; @@ -4702,6 +4702,25 @@ int do_swapcache_reclaim(unsigned long *swapcache_watermark, if (swapcache_to_reclaim <= 0) return err;
+ nr = kcalloc(MAX_NUMNODES, sizeof(unsigned long), GFP_KERNEL); + if (nr == NULL) + return -ENOMEM; + + nr_to_reclaim = kcalloc(MAX_NUMNODES, sizeof(unsigned long), + GFP_KERNEL); + if (nr_to_reclaim == NULL) { + kfree(nr); + return -ENOMEM; + } + + swapcache_list = kcalloc(MAX_NUMNODES, sizeof(struct list_head), + GFP_KERNEL); + if (swapcache_list == NULL) { + kfree(nr); + kfree(nr_to_reclaim); + return -ENOMEM; + } + /* * scan the LRU linked list of each memory node to obtain the * swapcache pages that can be reclaimd. @@ -4829,6 +4848,10 @@ int do_swapcache_reclaim(unsigned long *swapcache_watermark, nid_num++; }
+ kfree(nr); + kfree(nr_to_reclaim); + kfree(swapcache_list); + return 0; } EXPORT_SYMBOL_GPL(do_swapcache_reclaim);