Skip to content

Commit f5731a7

Browse files
ctmarinasgregkh
authored andcommitted
arm64: mte: Avoid the racy walk of the vma list during core dump
commit 4f4c549 upstream. The MTE coredump code in arch/arm64/kernel/elfcore.c iterates over the vma list without the mmap_lock held. This can race with another process or userfaultfd concurrently modifying the vma list. Change the for_each_mte_vma macro and its callers to instead use the vma snapshot taken by dump_vma_snapshot() and stored in the cprm object. Fixes: 6dd8b1a ("arm64: mte: Dump the MTE tags in the core file") Cc: <[email protected]> # 5.18.x Signed-off-by: Catalin Marinas <[email protected]> Reported-by: Seth Jenkins <[email protected]> Suggested-by: Seth Jenkins <[email protected]> Cc: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 87b3a40 commit f5731a7

File tree

1 file changed

+26
-30
lines changed

1 file changed

+26
-30
lines changed

arch/arm64/kernel/elfcore.c

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,27 @@
88
#include <asm/cpufeature.h>
99
#include <asm/mte.h>
1010

11-
#define for_each_mte_vma(vmi, vma) \
11+
#define for_each_mte_vma(cprm, i, m) \
1212
if (system_supports_mte()) \
13-
for_each_vma(vmi, vma) \
14-
if (vma->vm_flags & VM_MTE)
13+
for (i = 0, m = cprm->vma_meta; \
14+
i < cprm->vma_count; \
15+
i++, m = cprm->vma_meta + i) \
16+
if (m->flags & VM_MTE)
1517

16-
static unsigned long mte_vma_tag_dump_size(struct vm_area_struct *vma)
18+
static unsigned long mte_vma_tag_dump_size(struct core_vma_metadata *m)
1719
{
18-
if (vma->vm_flags & VM_DONTDUMP)
19-
return 0;
20-
21-
return vma_pages(vma) * MTE_PAGE_TAG_STORAGE;
20+
return (m->dump_size >> PAGE_SHIFT) * MTE_PAGE_TAG_STORAGE;
2221
}
2322

2423
/* Derived from dump_user_range(); start/end must be page-aligned */
2524
static int mte_dump_tag_range(struct coredump_params *cprm,
26-
unsigned long start, unsigned long end)
25+
unsigned long start, unsigned long len)
2726
{
2827
int ret = 1;
2928
unsigned long addr;
3029
void *tags = NULL;
3130

32-
for (addr = start; addr < end; addr += PAGE_SIZE) {
31+
for (addr = start; addr < start + len; addr += PAGE_SIZE) {
3332
struct page *page = get_dump_page(addr);
3433

3534
/*
@@ -78,30 +77,30 @@ static int mte_dump_tag_range(struct coredump_params *cprm,
7877

7978
Elf_Half elf_core_extra_phdrs(void)
8079
{
81-
struct vm_area_struct *vma;
80+
int i;
81+
struct core_vma_metadata *m;
8282
int vma_count = 0;
83-
VMA_ITERATOR(vmi, current->mm, 0);
8483

85-
for_each_mte_vma(vmi, vma)
84+
for_each_mte_vma(cprm, i, m)
8685
vma_count++;
8786

8887
return vma_count;
8988
}
9089

9190
int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
9291
{
93-
struct vm_area_struct *vma;
94-
VMA_ITERATOR(vmi, current->mm, 0);
92+
int i;
93+
struct core_vma_metadata *m;
9594

96-
for_each_mte_vma(vmi, vma) {
95+
for_each_mte_vma(cprm, i, m) {
9796
struct elf_phdr phdr;
9897

9998
phdr.p_type = PT_AARCH64_MEMTAG_MTE;
10099
phdr.p_offset = offset;
101-
phdr.p_vaddr = vma->vm_start;
100+
phdr.p_vaddr = m->start;
102101
phdr.p_paddr = 0;
103-
phdr.p_filesz = mte_vma_tag_dump_size(vma);
104-
phdr.p_memsz = vma->vm_end - vma->vm_start;
102+
phdr.p_filesz = mte_vma_tag_dump_size(m);
103+
phdr.p_memsz = m->end - m->start;
105104
offset += phdr.p_filesz;
106105
phdr.p_flags = 0;
107106
phdr.p_align = 0;
@@ -115,26 +114,23 @@ int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
115114

116115
size_t elf_core_extra_data_size(void)
117116
{
118-
struct vm_area_struct *vma;
117+
int i;
118+
struct core_vma_metadata *m;
119119
size_t data_size = 0;
120-
VMA_ITERATOR(vmi, current->mm, 0);
121120

122-
for_each_mte_vma(vmi, vma)
123-
data_size += mte_vma_tag_dump_size(vma);
121+
for_each_mte_vma(cprm, i, m)
122+
data_size += mte_vma_tag_dump_size(m);
124123

125124
return data_size;
126125
}
127126

128127
int elf_core_write_extra_data(struct coredump_params *cprm)
129128
{
130-
struct vm_area_struct *vma;
131-
VMA_ITERATOR(vmi, current->mm, 0);
132-
133-
for_each_mte_vma(vmi, vma) {
134-
if (vma->vm_flags & VM_DONTDUMP)
135-
continue;
129+
int i;
130+
struct core_vma_metadata *m;
136131

137-
if (!mte_dump_tag_range(cprm, vma->vm_start, vma->vm_end))
132+
for_each_mte_vma(cprm, i, m) {
133+
if (!mte_dump_tag_range(cprm, m->start, m->dump_size))
138134
return 0;
139135
}
140136

0 commit comments

Comments
 (0)