From e007f5685f2594bb678d8e37840cd363a378b8f7 Mon Sep 17 00:00:00 2001 From: wangzhimin Date: Tue, 10 Sep 2024 16:17:04 +0800 Subject: [PATCH] duptext: export fault data structure, add mmu notifier when memory unmap and add an offset to heap segment Signed-off-by: wangzhimin1179@phytium.com.cn --- arch/arm64/mm/fault.c | 8 +++++--- arch/arm64/mm/mmu.c | 2 ++ fs/binfmt_elf.c | 14 ++++++++++++-- fs/compat_binfmt_elf.c | 5 +++++ include/linux/fs.h | 1 + mm/mmap.c | 10 ++++++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 046e776ae564..db2380d864af 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -48,7 +48,8 @@ struct fault_info { const char *name; }; -static const struct fault_info fault_info[]; +struct fault_info fault_info[]; +EXPORT_SYMBOL(fault_info); static struct fault_info debug_fault_info[]; static inline const struct fault_info *esr_to_fault_info(unsigned int esr) @@ -387,7 +388,7 @@ static void set_thread_esr(unsigned long address, unsigned int esr) current->thread.fault_code = esr; } -static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) +void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) { /* * If we are in kernel mode at this point, we have no context to @@ -403,6 +404,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re __do_kernel_fault(addr, esr, regs); } } +EXPORT_SYMBOL(do_bad_area); #define VM_FAULT_BADMAP 0x010000 #define VM_FAULT_BADACCESS 0x020000 @@ -1593,7 +1595,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) return 0; } -static const struct fault_info fault_info[] = { +struct fault_info fault_info[] = { { do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" }, { do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" }, { do_bad, SIGKILL, SI_KERNEL, "level 2 address size fault" }, diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index d48c683c9283..dd4fe5be03ad 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -75,6 +75,7 @@ void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) pgd_clear_fixmap(); spin_unlock(&swapper_pgdir_lock); } +EXPORT_SYMBOL(set_swapper_pgd); pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, pgprot_t vma_prot) @@ -694,6 +695,7 @@ void __init paging_init(void) memblock_allow_resize(); } +EXPORT_SYMBOL(swapper_pg_dir); /* * Check whether a kernel address is valid (derived from arch/x86/). diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 72cd871544ac..612b0b29df66 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -57,6 +57,13 @@ #define elf_check_fdpic(ex) false #endif +#ifndef CONFIG_COMPAT_BINFMT_ELF +unsigned long brk_offset = PMD_SIZE; +EXPORT_SYMBOL(brk_offset); +#endif + +extern struct static_key_false phytium_duptext_static_key; + static int load_elf_binary(struct linux_binprm *bprm); #ifdef CONFIG_USELIB @@ -1118,9 +1125,12 @@ out_free_interp: loc->elf_ex.e_type == ET_DYN && !interpreter) current->mm->brk = current->mm->start_brk = ELF_ET_DYN_BASE; + if (static_branch_unlikely(&phytium_duptext_static_key)) { + current->mm->brk = current->mm->start_brk = arch_randomize_brk(current->mm) + brk_offset; + } else { + current->mm->brk = current->mm->start_brk = arch_randomize_brk(current->mm); + } - current->mm->brk = current->mm->start_brk = - arch_randomize_brk(current->mm); #ifdef compat_brk_randomized current->brk_randomized = 1; #endif diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index 7f49b283c680..16432fb71417 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -130,4 +130,9 @@ /* * We share all the actual code with the native (64-bit) version. */ +#ifdef CONFIG_COMPAT_BINFMT_ELF +unsigned long brk_offset = PMD_SIZE; +EXPORT_SYMBOL(brk_offset); +#endif + #include "binfmt_elf.c" diff --git a/include/linux/fs.h b/include/linux/fs.h index d219e6fff862..d1f039afc2a8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -85,6 +85,7 @@ extern int sysctl_protected_hardlinks; extern int sysctl_protected_fifos; extern int sysctl_protected_regular; extern unsigned int sysctl_nvidia_smi_trap; +extern unsigned long brk_offset; typedef __kernel_rwf_t rwf_t; diff --git a/mm/mmap.c b/mm/mmap.c index 632f21c4117c..c67c0529dea1 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2640,6 +2640,9 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) validate_mm(mm); } +DEFINE_STATIC_KEY_FALSE(phytium_duptext_static_key); +EXPORT_SYMBOL(phytium_duptext_static_key); + /* * Get rid of page table information in the indicated region. * @@ -2649,6 +2652,7 @@ static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end) { + struct mmu_notifier_range range; struct vm_area_struct *next = prev ? prev->vm_next : mm->mmap; struct mmu_gather tlb; struct vm_area_struct *cur_vma; @@ -2675,6 +2679,12 @@ static void unmap_region(struct mm_struct *mm, free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, next ? next->vm_start : USER_PGTABLES_CEILING); + if (static_branch_unlikely(&phytium_duptext_static_key)) { + mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, vma->vm_mm, + start, end); + mmu_notifier_invalidate_range_start(&range); + mmu_notifier_invalidate_range_end(&range); + } tlb_finish_mmu(&tlb, start, end); }