Skip to content

Commit b467192

Browse files
committed
Merge tag 'mm-hotfixes-stable-2022-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull more hotfixes from Andrew Morton: "Seventeen hotfixes. Mostly memory management things. Ten patches are cc:stable, addressing pre-6.0 issues" * tag 'mm-hotfixes-stable-2022-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: .mailmap: update Luca Ceresoli's e-mail address mm/mprotect: only reference swap pfn page if type match squashfs: don't call kmalloc in decompressors mm/damon/dbgfs: avoid duplicate context directory creation mailmap: update email address for Colin King asm-generic: sections: refactor memory_intersects bootmem: remove the vmemmap pages from kmemleak in put_page_bootmem ocfs2: fix freeing uninitialized resource on ocfs2_dlm_shutdown Revert "memcg: cleanup racy sum avoidance code" mm/zsmalloc: do not attempt to free IS_ERR handle binder_alloc: add missing mmap_lock calls when using the VMA mm: re-allow pinning of zero pfns (again) vmcoreinfo: add kallsyms_num_syms symbol mailmap: update Guilherme G. Piccoli's email addresses writeback: avoid use-after-free after removing device shmem: update folio if shmem_replace_page() updates the page mm/hugetlb: avoid corrupting page->mapping in hugetlb_mcopy_atomic_pte
2 parents 373eff5 + 0ebafe2 commit b467192

File tree

21 files changed

+108
-60
lines changed

21 files changed

+108
-60
lines changed

.mailmap

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ Christian Brauner <[email protected]> <[email protected]>
9898
Christian Marangi <[email protected]>
9999
Christophe Ricard <[email protected]>
100100
Christoph Hellwig <[email protected]>
101-
102-
101+
103102
Corey Minyard <[email protected]>
104103
Damian Hobson-Garcia <[email protected]>
105104
@@ -150,6 +149,8 @@ Greg Kroah-Hartman <[email protected]>
150149
Greg Kroah-Hartman <[email protected]>
151150
152151
152+
Guilherme G. Piccoli <[email protected]> <[email protected]>
153+
Guilherme G. Piccoli <[email protected]> <[email protected]>
153154
154155
155156
Gustavo Padovan <[email protected]>
@@ -253,6 +254,7 @@ Linus Lüssing <[email protected]> <[email protected]>
253254
254255
255256
257+
256258
257259
258260

drivers/android/binder_alloc.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -402,12 +402,15 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
402402
size_t size, data_offsets_size;
403403
int ret;
404404

405+
mmap_read_lock(alloc->vma_vm_mm);
405406
if (!binder_alloc_get_vma(alloc)) {
407+
mmap_read_unlock(alloc->vma_vm_mm);
406408
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
407409
"%d: binder_alloc_buf, no vma\n",
408410
alloc->pid);
409411
return ERR_PTR(-ESRCH);
410412
}
413+
mmap_read_unlock(alloc->vma_vm_mm);
411414

412415
data_offsets_size = ALIGN(data_size, sizeof(void *)) +
413416
ALIGN(offsets_size, sizeof(void *));
@@ -929,17 +932,25 @@ void binder_alloc_print_pages(struct seq_file *m,
929932
* Make sure the binder_alloc is fully initialized, otherwise we might
930933
* read inconsistent state.
931934
*/
932-
if (binder_alloc_get_vma(alloc) != NULL) {
933-
for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
934-
page = &alloc->pages[i];
935-
if (!page->page_ptr)
936-
free++;
937-
else if (list_empty(&page->lru))
938-
active++;
939-
else
940-
lru++;
941-
}
935+
936+
mmap_read_lock(alloc->vma_vm_mm);
937+
if (binder_alloc_get_vma(alloc) == NULL) {
938+
mmap_read_unlock(alloc->vma_vm_mm);
939+
goto uninitialized;
942940
}
941+
942+
mmap_read_unlock(alloc->vma_vm_mm);
943+
for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
944+
page = &alloc->pages[i];
945+
if (!page->page_ptr)
946+
free++;
947+
else if (list_empty(&page->lru))
948+
active++;
949+
else
950+
lru++;
951+
}
952+
953+
uninitialized:
943954
mutex_unlock(&alloc->mutex);
944955
seq_printf(m, " pages: %d:%d:%d\n", active, lru, free);
945956
seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high);

fs/fs-writeback.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,10 @@ static bool inode_io_list_move_locked(struct inode *inode,
134134

135135
static void wb_wakeup(struct bdi_writeback *wb)
136136
{
137-
spin_lock_bh(&wb->work_lock);
137+
spin_lock_irq(&wb->work_lock);
138138
if (test_bit(WB_registered, &wb->state))
139139
mod_delayed_work(bdi_wq, &wb->dwork, 0);
140-
spin_unlock_bh(&wb->work_lock);
140+
spin_unlock_irq(&wb->work_lock);
141141
}
142142

143143
static void finish_writeback_work(struct bdi_writeback *wb,
@@ -164,15 +164,15 @@ static void wb_queue_work(struct bdi_writeback *wb,
164164
if (work->done)
165165
atomic_inc(&work->done->cnt);
166166

167-
spin_lock_bh(&wb->work_lock);
167+
spin_lock_irq(&wb->work_lock);
168168

169169
if (test_bit(WB_registered, &wb->state)) {
170170
list_add_tail(&work->list, &wb->work_list);
171171
mod_delayed_work(bdi_wq, &wb->dwork, 0);
172172
} else
173173
finish_writeback_work(wb, work);
174174

175-
spin_unlock_bh(&wb->work_lock);
175+
spin_unlock_irq(&wb->work_lock);
176176
}
177177

178178
/**
@@ -2082,13 +2082,13 @@ static struct wb_writeback_work *get_next_work_item(struct bdi_writeback *wb)
20822082
{
20832083
struct wb_writeback_work *work = NULL;
20842084

2085-
spin_lock_bh(&wb->work_lock);
2085+
spin_lock_irq(&wb->work_lock);
20862086
if (!list_empty(&wb->work_list)) {
20872087
work = list_entry(wb->work_list.next,
20882088
struct wb_writeback_work, list);
20892089
list_del_init(&work->list);
20902090
}
2091-
spin_unlock_bh(&wb->work_lock);
2091+
spin_unlock_irq(&wb->work_lock);
20922092
return work;
20932093
}
20942094

fs/ocfs2/dlmglue.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3403,10 +3403,12 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
34033403
ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres);
34043404
ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres);
34053405

3406-
ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
3407-
osb->cconn = NULL;
3406+
if (osb->cconn) {
3407+
ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
3408+
osb->cconn = NULL;
34083409

3409-
ocfs2_dlm_shutdown_debug(osb);
3410+
ocfs2_dlm_shutdown_debug(osb);
3411+
}
34103412
}
34113413

34123414
static int ocfs2_drop_lock(struct ocfs2_super *osb,

fs/ocfs2/super.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,8 +1914,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
19141914
!ocfs2_is_hard_readonly(osb))
19151915
hangup_needed = 1;
19161916

1917-
if (osb->cconn)
1918-
ocfs2_dlm_shutdown(osb, hangup_needed);
1917+
ocfs2_dlm_shutdown(osb, hangup_needed);
19191918

19201919
ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats);
19211920
debugfs_remove_recursive(osb->osb_debug_root);

fs/squashfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ static void squashfs_readahead(struct readahead_control *ractl)
593593

594594
res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
595595

596-
kfree(actor);
596+
squashfs_page_actor_free(actor);
597597

598598
if (res == expected) {
599599
int bytes;

fs/squashfs/file_direct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
7474
/* Decompress directly into the page cache buffers */
7575
res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
7676

77-
kfree(actor);
77+
squashfs_page_actor_free(actor);
7878

7979
if (res < 0)
8080
goto mark_errored;

fs/squashfs/page_actor.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
5252
actor->buffer = buffer;
5353
actor->pages = pages;
5454
actor->next_page = 0;
55+
actor->tmp_buffer = NULL;
5556
actor->squashfs_first_page = cache_first_page;
5657
actor->squashfs_next_page = cache_next_page;
5758
actor->squashfs_finish_page = cache_finish_page;
@@ -68,20 +69,9 @@ static void *handle_next_page(struct squashfs_page_actor *actor)
6869

6970
if ((actor->next_page == actor->pages) ||
7071
(actor->next_index != actor->page[actor->next_page]->index)) {
71-
if (actor->alloc_buffer) {
72-
void *tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
73-
74-
if (tmp_buffer) {
75-
actor->tmp_buffer = tmp_buffer;
76-
actor->next_index++;
77-
actor->returned_pages++;
78-
return tmp_buffer;
79-
}
80-
}
81-
8272
actor->next_index++;
8373
actor->returned_pages++;
84-
return ERR_PTR(-ENOMEM);
74+
return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
8575
}
8676

8777
actor->next_index++;
@@ -96,11 +86,10 @@ static void *direct_first_page(struct squashfs_page_actor *actor)
9686

9787
static void *direct_next_page(struct squashfs_page_actor *actor)
9888
{
99-
if (actor->pageaddr)
89+
if (actor->pageaddr) {
10090
kunmap_local(actor->pageaddr);
101-
102-
kfree(actor->tmp_buffer);
103-
actor->pageaddr = actor->tmp_buffer = NULL;
91+
actor->pageaddr = NULL;
92+
}
10493

10594
return handle_next_page(actor);
10695
}
@@ -109,8 +98,6 @@ static void direct_finish_page(struct squashfs_page_actor *actor)
10998
{
11099
if (actor->pageaddr)
111100
kunmap_local(actor->pageaddr);
112-
113-
kfree(actor->tmp_buffer);
114101
}
115102

116103
struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
@@ -121,14 +108,23 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
121108
if (actor == NULL)
122109
return NULL;
123110

111+
if (msblk->decompressor->alloc_buffer) {
112+
actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
113+
114+
if (actor->tmp_buffer == NULL) {
115+
kfree(actor);
116+
return NULL;
117+
}
118+
} else
119+
actor->tmp_buffer = NULL;
120+
124121
actor->length = length ? : pages * PAGE_SIZE;
125122
actor->page = page;
126123
actor->pages = pages;
127124
actor->next_page = 0;
128125
actor->returned_pages = 0;
129126
actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
130127
actor->pageaddr = NULL;
131-
actor->tmp_buffer = NULL;
132128
actor->alloc_buffer = msblk->decompressor->alloc_buffer;
133129
actor->squashfs_first_page = direct_first_page;
134130
actor->squashfs_next_page = direct_next_page;

fs/squashfs/page_actor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ extern struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
2929
extern struct squashfs_page_actor *squashfs_page_actor_init_special(
3030
struct squashfs_sb_info *msblk,
3131
struct page **page, int pages, int length);
32+
static inline void squashfs_page_actor_free(struct squashfs_page_actor *actor)
33+
{
34+
kfree(actor->tmp_buffer);
35+
kfree(actor);
36+
}
3237
static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
3338
{
3439
return actor->squashfs_first_page(actor);

include/asm-generic/sections.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static inline bool memory_contains(void *begin, void *end, void *virt,
9797
/**
9898
* memory_intersects - checks if the region occupied by an object intersects
9999
* with another memory region
100-
* @begin: virtual address of the beginning of the memory regien
100+
* @begin: virtual address of the beginning of the memory region
101101
* @end: virtual address of the end of the memory region
102102
* @virt: virtual address of the memory object
103103
* @size: size of the memory object
@@ -110,7 +110,10 @@ static inline bool memory_intersects(void *begin, void *end, void *virt,
110110
{
111111
void *vend = virt + size;
112112

113-
return (virt >= begin && virt < end) || (vend >= begin && vend < end);
113+
if (virt < end && vend > begin)
114+
return true;
115+
116+
return false;
114117
}
115118

116119
/**

include/linux/memcontrol.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -987,19 +987,30 @@ static inline void mod_memcg_page_state(struct page *page,
987987

988988
static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
989989
{
990-
return READ_ONCE(memcg->vmstats.state[idx]);
990+
long x = READ_ONCE(memcg->vmstats.state[idx]);
991+
#ifdef CONFIG_SMP
992+
if (x < 0)
993+
x = 0;
994+
#endif
995+
return x;
991996
}
992997

993998
static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
994999
enum node_stat_item idx)
9951000
{
9961001
struct mem_cgroup_per_node *pn;
1002+
long x;
9971003

9981004
if (mem_cgroup_disabled())
9991005
return node_page_state(lruvec_pgdat(lruvec), idx);
10001006

10011007
pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
1002-
return READ_ONCE(pn->lruvec_stats.state[idx]);
1008+
x = READ_ONCE(pn->lruvec_stats.state[idx]);
1009+
#ifdef CONFIG_SMP
1010+
if (x < 0)
1011+
x = 0;
1012+
#endif
1013+
return x;
10031014
}
10041015

10051016
static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,

include/linux/mm.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,9 +1544,16 @@ static inline bool is_longterm_pinnable_page(struct page *page)
15441544
if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE)
15451545
return false;
15461546
#endif
1547-
return !(is_device_coherent_page(page) ||
1548-
is_zone_movable_page(page) ||
1549-
is_zero_pfn(page_to_pfn(page)));
1547+
/* The zero page may always be pinned */
1548+
if (is_zero_pfn(page_to_pfn(page)))
1549+
return true;
1550+
1551+
/* Coherent device memory must always allow eviction. */
1552+
if (is_device_coherent_page(page))
1553+
return false;
1554+
1555+
/* Otherwise, non-movable zone pages can be pinned. */
1556+
return !is_zone_movable_page(page);
15501557
}
15511558
#else
15521559
static inline bool is_longterm_pinnable_page(struct page *page)

kernel/crash_core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ static int __init crash_save_vmcoreinfo_init(void)
494494

495495
#ifdef CONFIG_KALLSYMS
496496
VMCOREINFO_SYMBOL(kallsyms_names);
497+
VMCOREINFO_SYMBOL(kallsyms_num_syms);
497498
VMCOREINFO_SYMBOL(kallsyms_token_table);
498499
VMCOREINFO_SYMBOL(kallsyms_token_index);
499500
#ifdef CONFIG_KALLSYMS_BASE_RELATIVE

mm/backing-dev.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,10 @@ void wb_wakeup_delayed(struct bdi_writeback *wb)
260260
unsigned long timeout;
261261

262262
timeout = msecs_to_jiffies(dirty_writeback_interval * 10);
263-
spin_lock_bh(&wb->work_lock);
263+
spin_lock_irq(&wb->work_lock);
264264
if (test_bit(WB_registered, &wb->state))
265265
queue_delayed_work(bdi_wq, &wb->dwork, timeout);
266-
spin_unlock_bh(&wb->work_lock);
266+
spin_unlock_irq(&wb->work_lock);
267267
}
268268

269269
static void wb_update_bandwidth_workfn(struct work_struct *work)
@@ -334,12 +334,12 @@ static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb);
334334
static void wb_shutdown(struct bdi_writeback *wb)
335335
{
336336
/* Make sure nobody queues further work */
337-
spin_lock_bh(&wb->work_lock);
337+
spin_lock_irq(&wb->work_lock);
338338
if (!test_and_clear_bit(WB_registered, &wb->state)) {
339-
spin_unlock_bh(&wb->work_lock);
339+
spin_unlock_irq(&wb->work_lock);
340340
return;
341341
}
342-
spin_unlock_bh(&wb->work_lock);
342+
spin_unlock_irq(&wb->work_lock);
343343

344344
cgwb_remove_from_bdi_list(wb);
345345
/*

mm/bootmem_info.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/memblock.h>
1313
#include <linux/bootmem_info.h>
1414
#include <linux/memory_hotplug.h>
15+
#include <linux/kmemleak.h>
1516

1617
void get_page_bootmem(unsigned long info, struct page *page, unsigned long type)
1718
{
@@ -33,6 +34,7 @@ void put_page_bootmem(struct page *page)
3334
ClearPagePrivate(page);
3435
set_page_private(page, 0);
3536
INIT_LIST_HEAD(&page->lru);
37+
kmemleak_free_part(page_to_virt(page), PAGE_SIZE);
3638
free_reserved_page(page);
3739
}
3840
}

mm/damon/dbgfs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,9 @@ static int dbgfs_mk_context(char *name)
818818
return -ENOENT;
819819

820820
new_dir = debugfs_create_dir(name, root);
821+
/* Below check is required for a potential duplicated name case */
822+
if (IS_ERR(new_dir))
823+
return PTR_ERR(new_dir);
821824
dbgfs_dirs[dbgfs_nr_ctxs] = new_dir;
822825

823826
new_ctx = dbgfs_new_ctx();

0 commit comments

Comments
 (0)