Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'riscv-for-linus-6.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V fixes from Palmer Dabbelt:

- A fix to avoid ISA-disallowed privilege mappings that can result from
WRITE+EXEC mmap requests from userspace.

- A fix for kfence to handle the huge pages.

- A fix to avoid converting misaligned VAs to huge pages.

- ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE has been selected so kprobe
can understand user pointers.

* tag 'riscv-for-linus-6.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
riscv: fix kprobe __user string arg print fault issue
riscv: Check the virtual alignment before choosing a map size
riscv: Fix kfence now that the linear mapping can be backed by PUD/P4D/PGD
riscv: mm: Ensure prot of VM_WRITE and VM_EXEC must be readable

+39 -46
+1
arch/riscv/Kconfig
··· 26 26 select ARCH_HAS_GIGANTIC_PAGE 27 27 select ARCH_HAS_KCOV 28 28 select ARCH_HAS_MMIOWB 29 + select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 29 30 select ARCH_HAS_PMEM_API 30 31 select ARCH_HAS_PTE_SPECIAL 31 32 select ARCH_HAS_SET_DIRECT_MAP if MMU
-33
arch/riscv/include/asm/kfence.h
··· 8 8 #include <asm-generic/pgalloc.h> 9 9 #include <asm/pgtable.h> 10 10 11 - static inline int split_pmd_page(unsigned long addr) 12 - { 13 - int i; 14 - unsigned long pfn = PFN_DOWN(__pa((addr & PMD_MASK))); 15 - pmd_t *pmd = pmd_off_k(addr); 16 - pte_t *pte = pte_alloc_one_kernel(&init_mm); 17 - 18 - if (!pte) 19 - return -ENOMEM; 20 - 21 - for (i = 0; i < PTRS_PER_PTE; i++) 22 - set_pte(pte + i, pfn_pte(pfn + i, PAGE_KERNEL)); 23 - set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa(pte)), PAGE_TABLE)); 24 - 25 - flush_tlb_kernel_range(addr, addr + PMD_SIZE); 26 - return 0; 27 - } 28 - 29 11 static inline bool arch_kfence_init_pool(void) 30 12 { 31 - int ret; 32 - unsigned long addr; 33 - pmd_t *pmd; 34 - 35 - for (addr = (unsigned long)__kfence_pool; is_kfence_address((void *)addr); 36 - addr += PAGE_SIZE) { 37 - pmd = pmd_off_k(addr); 38 - 39 - if (pmd_leaf(*pmd)) { 40 - ret = split_pmd_page(addr); 41 - if (ret) 42 - return false; 43 - } 44 - } 45 - 46 13 return true; 47 14 } 48 15
+1 -2
arch/riscv/include/asm/pgtable.h
··· 165 165 _PAGE_EXEC | _PAGE_WRITE) 166 166 167 167 #define PAGE_COPY PAGE_READ 168 - #define PAGE_COPY_EXEC PAGE_EXEC 169 - #define PAGE_COPY_READ_EXEC PAGE_READ_EXEC 168 + #define PAGE_COPY_EXEC PAGE_READ_EXEC 170 169 #define PAGE_SHARED PAGE_WRITE 171 170 #define PAGE_SHARED_EXEC PAGE_WRITE_EXEC 172 171
+37 -11
arch/riscv/mm/init.c
··· 23 23 #ifdef CONFIG_RELOCATABLE 24 24 #include <linux/elf.h> 25 25 #endif 26 + #include <linux/kfence.h> 26 27 27 28 #include <asm/fixmap.h> 28 29 #include <asm/tlbflush.h> ··· 294 293 [VM_EXEC] = PAGE_EXEC, 295 294 [VM_EXEC | VM_READ] = PAGE_READ_EXEC, 296 295 [VM_EXEC | VM_WRITE] = PAGE_COPY_EXEC, 297 - [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_READ_EXEC, 296 + [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_EXEC, 298 297 [VM_SHARED] = PAGE_NONE, 299 298 [VM_SHARED | VM_READ] = PAGE_READ, 300 299 [VM_SHARED | VM_WRITE] = PAGE_SHARED, ··· 660 659 create_pgd_next_mapping(nextp, va, pa, sz, prot); 661 660 } 662 661 663 - static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) 662 + static uintptr_t __init best_map_size(phys_addr_t pa, uintptr_t va, 663 + phys_addr_t size) 664 664 { 665 - if (!(base & (PGDIR_SIZE - 1)) && size >= PGDIR_SIZE) 665 + if (!(pa & (PGDIR_SIZE - 1)) && !(va & (PGDIR_SIZE - 1)) && size >= PGDIR_SIZE) 666 666 return PGDIR_SIZE; 667 667 668 - if (!(base & (P4D_SIZE - 1)) && size >= P4D_SIZE) 668 + if (!(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE) 669 669 return P4D_SIZE; 670 670 671 - if (!(base & (PUD_SIZE - 1)) && size >= PUD_SIZE) 671 + if (!(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE) 672 672 return PUD_SIZE; 673 673 674 - if (!(base & (PMD_SIZE - 1)) && size >= PMD_SIZE) 674 + if (!(pa & (PMD_SIZE - 1)) && !(va & (PMD_SIZE - 1)) && size >= PMD_SIZE) 675 675 return PMD_SIZE; 676 676 677 677 return PAGE_SIZE; ··· 1169 1167 } 1170 1168 1171 1169 static void __init create_linear_mapping_range(phys_addr_t start, 1172 - phys_addr_t end) 1170 + phys_addr_t end, 1171 + uintptr_t fixed_map_size) 1173 1172 { 1174 1173 phys_addr_t pa; 1175 1174 uintptr_t va, map_size; 1176 1175 1177 1176 for (pa = start; pa < end; pa += map_size) { 1178 1177 va = (uintptr_t)__va(pa); 1179 - map_size = best_map_size(pa, end - pa); 1178 + map_size = fixed_map_size ? fixed_map_size : 1179 + best_map_size(pa, va, end - pa); 1180 1180 1181 1181 create_pgd_mapping(swapper_pg_dir, va, pa, map_size, 1182 1182 pgprot_from_va(va)); ··· 1188 1184 static void __init create_linear_mapping_page_table(void) 1189 1185 { 1190 1186 phys_addr_t start, end; 1187 + phys_addr_t kfence_pool __maybe_unused; 1191 1188 u64 i; 1192 1189 1193 1190 #ifdef CONFIG_STRICT_KERNEL_RWX ··· 1202 1197 memblock_mark_nomap(krodata_start, krodata_size); 1203 1198 #endif 1204 1199 1200 + #ifdef CONFIG_KFENCE 1201 + /* 1202 + * kfence pool must be backed by PAGE_SIZE mappings, so allocate it 1203 + * before we setup the linear mapping so that we avoid using hugepages 1204 + * for this region. 1205 + */ 1206 + kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE); 1207 + BUG_ON(!kfence_pool); 1208 + 1209 + memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE); 1210 + __kfence_pool = __va(kfence_pool); 1211 + #endif 1212 + 1205 1213 /* Map all memory banks in the linear mapping */ 1206 1214 for_each_mem_range(i, &start, &end) { 1207 1215 if (start >= end) ··· 1225 1207 if (end >= __pa(PAGE_OFFSET) + memory_limit) 1226 1208 end = __pa(PAGE_OFFSET) + memory_limit; 1227 1209 1228 - create_linear_mapping_range(start, end); 1210 + create_linear_mapping_range(start, end, 0); 1229 1211 } 1230 1212 1231 1213 #ifdef CONFIG_STRICT_KERNEL_RWX 1232 - create_linear_mapping_range(ktext_start, ktext_start + ktext_size); 1214 + create_linear_mapping_range(ktext_start, ktext_start + ktext_size, 0); 1233 1215 create_linear_mapping_range(krodata_start, 1234 - krodata_start + krodata_size); 1216 + krodata_start + krodata_size, 0); 1235 1217 1236 1218 memblock_clear_nomap(ktext_start, ktext_size); 1237 1219 memblock_clear_nomap(krodata_start, krodata_size); 1220 + #endif 1221 + 1222 + #ifdef CONFIG_KFENCE 1223 + create_linear_mapping_range(kfence_pool, 1224 + kfence_pool + KFENCE_POOL_SIZE, 1225 + PAGE_SIZE); 1226 + 1227 + memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE); 1238 1228 #endif 1239 1229 } 1240 1230