1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/coredump.h>
4 #include <linux/elfcore.h>
5 #include <linux/kernel.h>
8 #include <asm/cpufeature.h>
11 #define for_each_mte_vma(cprm, i, m) \
12 if (system_supports_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)
18 static unsigned long mte_vma_tag_dump_size(struct core_vma_metadata
*m
)
20 return (m
->dump_size
>> PAGE_SHIFT
) * MTE_PAGE_TAG_STORAGE
;
23 /* Derived from dump_user_range(); start/end must be page-aligned */
24 static int mte_dump_tag_range(struct coredump_params
*cprm
,
25 unsigned long start
, unsigned long len
)
31 for (addr
= start
; addr
< start
+ len
; addr
+= PAGE_SIZE
) {
32 struct page
*page
= get_dump_page(addr
);
35 * get_dump_page() returns NULL when encountering an empty
36 * page table entry that would otherwise have been filled with
37 * the zero page. Skip the equivalent tag dump which would
38 * have been all zeros.
41 dump_skip(cprm
, MTE_PAGE_TAG_STORAGE
);
46 * Pages mapped in user space as !pte_access_permitted() (e.g.
47 * PROT_EXEC only) may not have the PG_mte_tagged flag set.
49 if (!page_mte_tagged(page
)) {
51 dump_skip(cprm
, MTE_PAGE_TAG_STORAGE
);
56 tags
= mte_allocate_tag_storage();
64 mte_save_page_tags(page_address(page
), tags
);
66 if (!dump_emit(cprm
, tags
, MTE_PAGE_TAG_STORAGE
)) {
73 mte_free_tag_storage(tags
);
78 Elf_Half
elf_core_extra_phdrs(struct coredump_params
*cprm
)
81 struct core_vma_metadata
*m
;
84 for_each_mte_vma(cprm
, i
, m
)
90 int elf_core_write_extra_phdrs(struct coredump_params
*cprm
, loff_t offset
)
93 struct core_vma_metadata
*m
;
95 for_each_mte_vma(cprm
, i
, m
) {
98 phdr
.p_type
= PT_AARCH64_MEMTAG_MTE
;
99 phdr
.p_offset
= offset
;
100 phdr
.p_vaddr
= m
->start
;
102 phdr
.p_filesz
= mte_vma_tag_dump_size(m
);
103 phdr
.p_memsz
= m
->end
- m
->start
;
104 offset
+= phdr
.p_filesz
;
108 if (!dump_emit(cprm
, &phdr
, sizeof(phdr
)))
115 size_t elf_core_extra_data_size(struct coredump_params
*cprm
)
118 struct core_vma_metadata
*m
;
119 size_t data_size
= 0;
121 for_each_mte_vma(cprm
, i
, m
)
122 data_size
+= mte_vma_tag_dump_size(m
);
127 int elf_core_write_extra_data(struct coredump_params
*cprm
)
130 struct core_vma_metadata
*m
;
132 for_each_mte_vma(cprm
, i
, m
) {
133 if (!mte_dump_tag_range(cprm
, m
->start
, m
->dump_size
))