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
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]>
  • Loading branch information
ctmarinas authored and willdeacon committed Jan 5, 2023
1 parent 19e183b commit 4f4c549
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(struct coredump_params *cprm)
{
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(struct coredump_params *cprm)
{
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 4f4c549

Please sign in to comment.