Skip to content

Commit

Permalink
arm64: mte: Avoid the racy walk of the vma list during core dump
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ctmarinas authored and gregkh committed Jan 18, 2023
1 parent 87b3a40 commit f5731a7
Showing 1 changed file with 26 additions and 30 deletions.
56 changes: 26 additions & 30 deletions arch/arm64/kernel/elfcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,27 @@
#include <asm/cpufeature.h>
#include <asm/mte.h>

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

static unsigned long mte_vma_tag_dump_size(struct vm_area_struct *vma)
static unsigned long mte_vma_tag_dump_size(struct core_vma_metadata *m)
{
if (vma->vm_flags & VM_DONTDUMP)
return 0;

return vma_pages(vma) * MTE_PAGE_TAG_STORAGE;
return (m->dump_size >> PAGE_SHIFT) * MTE_PAGE_TAG_STORAGE;
}

/* Derived from dump_user_range(); start/end must be page-aligned */
static int mte_dump_tag_range(struct coredump_params *cprm,
unsigned long start, unsigned long end)
unsigned long start, unsigned long len)
{
int ret = 1;
unsigned long addr;
void *tags = NULL;

for (addr = start; addr < end; addr += PAGE_SIZE) {
for (addr = start; addr < start + len; addr += PAGE_SIZE) {
struct page *page = get_dump_page(addr);

/*
Expand Down Expand Up @@ -78,30 +77,30 @@ static int mte_dump_tag_range(struct coredump_params *cprm,

Elf_Half elf_core_extra_phdrs(void)
{
struct vm_area_struct *vma;
int i;
struct core_vma_metadata *m;
int vma_count = 0;
VMA_ITERATOR(vmi, current->mm, 0);

for_each_mte_vma(vmi, vma)
for_each_mte_vma(cprm, i, m)
vma_count++;

return vma_count;
}

int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
{
struct vm_area_struct *vma;
VMA_ITERATOR(vmi, current->mm, 0);
int i;
struct core_vma_metadata *m;

for_each_mte_vma(vmi, vma) {
for_each_mte_vma(cprm, i, m) {
struct elf_phdr phdr;

phdr.p_type = PT_AARCH64_MEMTAG_MTE;
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_vaddr = m->start;
phdr.p_paddr = 0;
phdr.p_filesz = mte_vma_tag_dump_size(vma);
phdr.p_memsz = vma->vm_end - vma->vm_start;
phdr.p_filesz = mte_vma_tag_dump_size(m);
phdr.p_memsz = m->end - m->start;
offset += phdr.p_filesz;
phdr.p_flags = 0;
phdr.p_align = 0;
Expand All @@ -115,26 +114,23 @@ int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)

size_t elf_core_extra_data_size(void)
{
struct vm_area_struct *vma;
int i;
struct core_vma_metadata *m;
size_t data_size = 0;
VMA_ITERATOR(vmi, current->mm, 0);

for_each_mte_vma(vmi, vma)
data_size += mte_vma_tag_dump_size(vma);
for_each_mte_vma(cprm, i, m)
data_size += mte_vma_tag_dump_size(m);

return data_size;
}

int elf_core_write_extra_data(struct coredump_params *cprm)
{
struct vm_area_struct *vma;
VMA_ITERATOR(vmi, current->mm, 0);

for_each_mte_vma(vmi, vma) {
if (vma->vm_flags & VM_DONTDUMP)
continue;
int i;
struct core_vma_metadata *m;

if (!mte_dump_tag_range(cprm, vma->vm_start, vma->vm_end))
for_each_mte_vma(cprm, i, m) {
if (!mte_dump_tag_range(cprm, m->start, m->dump_size))
return 0;
}

Expand Down

0 comments on commit f5731a7

Please sign in to comment.