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 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull more arm64 updates from Catalin Marinas:

- Silence module allocation failures when CONFIG_ARM*_MODULE_PLTS is
enabled. This requires a check for __GFP_NOWARN in alloc_vmap_area()

- Improve/sanitise user tagged pointers handling in the kernel

- Inline asm fixes/cleanups

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: Silence first allocation with CONFIG_ARM64_MODULE_PLTS=y
ARM: Silence first allocation with CONFIG_ARM_MODULE_PLTS=y
mm: Silence vmap() allocation failures based on caller gfp_flags
arm64: uaccess: suppress spurious clang warning
arm64: atomic_lse: match asm register sizes
arm64: armv8_deprecated: ensure extension of addr
arm64: uaccess: ensure extension of access_ok() addr
arm64: ensure extension of smp_store_release value
arm64: xchg: hazard against entire exchange variable
arm64: documentation: document tagged pointer stack constraints
arm64: entry: improve data abort handling of tagged pointers
arm64: hw_breakpoint: fix watchpoint matching for tagged pointers
arm64: traps: fix userspace cache maintenance emulation on a tagged pointer

+107 -38
+47 -15
Documentation/arm64/tagged-pointers.txt
··· 11 11 The kernel configures the translation tables so that translations made 12 12 via TTBR0 (i.e. userspace mappings) have the top byte (bits 63:56) of 13 13 the virtual address ignored by the translation hardware. This frees up 14 - this byte for application use, with the following caveats: 14 + this byte for application use. 15 15 16 - (1) The kernel requires that all user addresses passed to EL1 17 - are tagged with tag 0x00. This means that any syscall 18 - parameters containing user virtual addresses *must* have 19 - their top byte cleared before trapping to the kernel. 20 16 21 - (2) Non-zero tags are not preserved when delivering signals. 22 - This means that signal handlers in applications making use 23 - of tags cannot rely on the tag information for user virtual 24 - addresses being maintained for fields inside siginfo_t. 25 - One exception to this rule is for signals raised in response 26 - to watchpoint debug exceptions, where the tag information 27 - will be preserved. 17 + Passing tagged addresses to the kernel 18 + -------------------------------------- 28 19 29 - (3) Special care should be taken when using tagged pointers, 30 - since it is likely that C compilers will not hazard two 31 - virtual addresses differing only in the upper byte. 20 + All interpretation of userspace memory addresses by the kernel assumes 21 + an address tag of 0x00. 22 + 23 + This includes, but is not limited to, addresses found in: 24 + 25 + - pointer arguments to system calls, including pointers in structures 26 + passed to system calls, 27 + 28 + - the stack pointer (sp), e.g. when interpreting it to deliver a 29 + signal, 30 + 31 + - the frame pointer (x29) and frame records, e.g. when interpreting 32 + them to generate a backtrace or call graph. 33 + 34 + Using non-zero address tags in any of these locations may result in an 35 + error code being returned, a (fatal) signal being raised, or other modes 36 + of failure. 37 + 38 + For these reasons, passing non-zero address tags to the kernel via 39 + system calls is forbidden, and using a non-zero address tag for sp is 40 + strongly discouraged. 41 + 42 + Programs maintaining a frame pointer and frame records that use non-zero 43 + address tags may suffer impaired or inaccurate debug and profiling 44 + visibility. 45 + 46 + 47 + Preserving tags 48 + --------------- 49 + 50 + Non-zero tags are not preserved when delivering signals. This means that 51 + signal handlers in applications making use of tags cannot rely on the 52 + tag information for user virtual addresses being maintained for fields 53 + inside siginfo_t. One exception to this rule is for signals raised in 54 + response to watchpoint debug exceptions, where the tag information will 55 + be preserved. 32 56 33 57 The architecture prevents the use of a tagged PC, so the upper byte will 34 58 be set to a sign-extension of bit 55 on exception return. 59 + 60 + 61 + Other considerations 62 + -------------------- 63 + 64 + Special care should be taken when using tagged pointers, since it is 65 + likely that C compilers will not hazard two virtual addresses differing 66 + only in the upper byte.
+9 -2
arch/arm/kernel/module.c
··· 40 40 #ifdef CONFIG_MMU 41 41 void *module_alloc(unsigned long size) 42 42 { 43 - void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, 44 - GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, 43 + gfp_t gfp_mask = GFP_KERNEL; 44 + void *p; 45 + 46 + /* Silence the initial allocation */ 47 + if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS)) 48 + gfp_mask |= __GFP_NOWARN; 49 + 50 + p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, 51 + gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, 45 52 __builtin_return_address(0)); 46 53 if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p) 47 54 return p;
+9
arch/arm64/include/asm/asm-uaccess.h
··· 62 62 alternative_else_nop_endif 63 63 .endm 64 64 65 + /* 66 + * Remove the address tag from a virtual address, if present. 67 + */ 68 + .macro clear_address_tag, dst, addr 69 + tst \addr, #(1 << 55) 70 + bic \dst, \addr, #(0xff << 56) 71 + csel \dst, \dst, \addr, eq 72 + .endm 73 + 65 74 #endif
+2 -2
arch/arm64/include/asm/atomic_lse.h
··· 322 322 #define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \ 323 323 static inline long atomic64_fetch_and##name(long i, atomic64_t *v) \ 324 324 { \ 325 - register long x0 asm ("w0") = i; \ 325 + register long x0 asm ("x0") = i; \ 326 326 register atomic64_t *x1 asm ("x1") = v; \ 327 327 \ 328 328 asm volatile(ARM64_LSE_ATOMIC_INSN( \ ··· 394 394 #define ATOMIC64_FETCH_OP_SUB(name, mb, cl...) \ 395 395 static inline long atomic64_fetch_sub##name(long i, atomic64_t *v) \ 396 396 { \ 397 - register long x0 asm ("w0") = i; \ 397 + register long x0 asm ("x0") = i; \ 398 398 register atomic64_t *x1 asm ("x1") = v; \ 399 399 \ 400 400 asm volatile(ARM64_LSE_ATOMIC_INSN( \
+15 -5
arch/arm64/include/asm/barrier.h
··· 42 42 #define __smp_rmb() dmb(ishld) 43 43 #define __smp_wmb() dmb(ishst) 44 44 45 - #define __smp_store_release(p, v) \ 45 + #define __smp_store_release(p, v) \ 46 46 do { \ 47 + union { typeof(*p) __val; char __c[1]; } __u = \ 48 + { .__val = (__force typeof(*p)) (v) }; \ 47 49 compiletime_assert_atomic_type(*p); \ 48 50 switch (sizeof(*p)) { \ 49 51 case 1: \ 50 52 asm volatile ("stlrb %w1, %0" \ 51 - : "=Q" (*p) : "r" (v) : "memory"); \ 53 + : "=Q" (*p) \ 54 + : "r" (*(__u8 *)__u.__c) \ 55 + : "memory"); \ 52 56 break; \ 53 57 case 2: \ 54 58 asm volatile ("stlrh %w1, %0" \ 55 - : "=Q" (*p) : "r" (v) : "memory"); \ 59 + : "=Q" (*p) \ 60 + : "r" (*(__u16 *)__u.__c) \ 61 + : "memory"); \ 56 62 break; \ 57 63 case 4: \ 58 64 asm volatile ("stlr %w1, %0" \ 59 - : "=Q" (*p) : "r" (v) : "memory"); \ 65 + : "=Q" (*p) \ 66 + : "r" (*(__u32 *)__u.__c) \ 67 + : "memory"); \ 60 68 break; \ 61 69 case 8: \ 62 70 asm volatile ("stlr %1, %0" \ 63 - : "=Q" (*p) : "r" (v) : "memory"); \ 71 + : "=Q" (*p) \ 72 + : "r" (*(__u64 *)__u.__c) \ 73 + : "memory"); \ 64 74 break; \ 65 75 } \ 66 76 } while (0)
+1 -1
arch/arm64/include/asm/cmpxchg.h
··· 46 46 " swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \ 47 47 __nops(3) \ 48 48 " " #nop_lse) \ 49 - : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) \ 49 + : "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr) \ 50 50 : "r" (x) \ 51 51 : cl); \ 52 52 \
+7 -6
arch/arm64/include/asm/uaccess.h
··· 69 69 */ 70 70 #define __range_ok(addr, size) \ 71 71 ({ \ 72 + unsigned long __addr = (unsigned long __force)(addr); \ 72 73 unsigned long flag, roksum; \ 73 74 __chk_user_ptr(addr); \ 74 75 asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ 75 76 : "=&r" (flag), "=&r" (roksum) \ 76 - : "1" (addr), "Ir" (size), \ 77 + : "1" (__addr), "Ir" (size), \ 77 78 "r" (current_thread_info()->addr_limit) \ 78 79 : "cc"); \ 79 80 flag; \ 80 81 }) 81 82 82 83 /* 83 - * When dealing with data aborts or instruction traps we may end up with 84 - * a tagged userland pointer. Clear the tag to get a sane pointer to pass 85 - * on to access_ok(), for instance. 84 + * When dealing with data aborts, watchpoints, or instruction traps we may end 85 + * up with a tagged userland pointer. Clear the tag to get a sane pointer to 86 + * pass on to access_ok(), for instance. 86 87 */ 87 88 #define untagged_addr(addr) sign_extend64(addr, 55) 88 89 ··· 231 230 (err), ARM64_HAS_UAO); \ 232 231 break; \ 233 232 case 8: \ 234 - __get_user_asm("ldr", "ldtr", "%", __gu_val, (ptr), \ 233 + __get_user_asm("ldr", "ldtr", "%x", __gu_val, (ptr), \ 235 234 (err), ARM64_HAS_UAO); \ 236 235 break; \ 237 236 default: \ ··· 298 297 (err), ARM64_HAS_UAO); \ 299 298 break; \ 300 299 case 8: \ 301 - __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \ 300 + __put_user_asm("str", "sttr", "%x", __pu_val, (ptr), \ 302 301 (err), ARM64_HAS_UAO); \ 303 302 break; \ 304 303 default: \
+2 -1
arch/arm64/kernel/armv8_deprecated.c
··· 306 306 _ASM_EXTABLE(0b, 4b) \ 307 307 _ASM_EXTABLE(1b, 4b) \ 308 308 : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \ 309 - : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \ 309 + : "r" ((unsigned long)addr), "i" (-EAGAIN), \ 310 + "i" (-EFAULT), \ 310 311 "i" (__SWP_LL_SC_LOOPS) \ 311 312 : "memory"); \ 312 313 uaccess_disable(); \
+3 -2
arch/arm64/kernel/entry.S
··· 428 428 /* 429 429 * Data abort handling 430 430 */ 431 - mrs x0, far_el1 431 + mrs x3, far_el1 432 432 enable_dbg 433 433 // re-enable interrupts if they were enabled in the aborted context 434 434 tbnz x23, #7, 1f // PSR_I_BIT 435 435 enable_irq 436 436 1: 437 + clear_address_tag x0, x3 437 438 mov x2, sp // struct pt_regs 438 439 bl do_mem_abort 439 440 ··· 595 594 // enable interrupts before calling the main handler 596 595 enable_dbg_and_irq 597 596 ct_user_exit 598 - bic x0, x26, #(0xff << 56) 597 + clear_address_tag x0, x26 599 598 mov x1, x25 600 599 mov x2, sp 601 600 bl do_mem_abort
+3
arch/arm64/kernel/hw_breakpoint.c
··· 36 36 #include <asm/traps.h> 37 37 #include <asm/cputype.h> 38 38 #include <asm/system_misc.h> 39 + #include <asm/uaccess.h> 39 40 40 41 /* Breakpoint currently in use for each BRP. */ 41 42 static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); ··· 721 720 { 722 721 u64 wp_low, wp_high; 723 722 u32 lens, lene; 723 + 724 + addr = untagged_addr(addr); 724 725 725 726 lens = __ffs(ctrl->len); 726 727 lene = __fls(ctrl->len);
+6 -1
arch/arm64/kernel/module.c
··· 32 32 33 33 void *module_alloc(unsigned long size) 34 34 { 35 + gfp_t gfp_mask = GFP_KERNEL; 35 36 void *p; 37 + 38 + /* Silence the initial allocation */ 39 + if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS)) 40 + gfp_mask |= __GFP_NOWARN; 36 41 37 42 p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, 38 43 module_alloc_base + MODULES_VSIZE, 39 - GFP_KERNEL, PAGE_KERNEL_EXEC, 0, 44 + gfp_mask, PAGE_KERNEL_EXEC, 0, 40 45 NUMA_NO_NODE, __builtin_return_address(0)); 41 46 42 47 if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
+2 -2
arch/arm64/kernel/traps.c
··· 443 443 } 444 444 445 445 #define __user_cache_maint(insn, address, res) \ 446 - if (untagged_addr(address) >= user_addr_max()) { \ 446 + if (address >= user_addr_max()) { \ 447 447 res = -EFAULT; \ 448 448 } else { \ 449 449 uaccess_ttbr0_enable(); \ ··· 469 469 int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT; 470 470 int ret = 0; 471 471 472 - address = pt_regs_read_reg(regs, rt); 472 + address = untagged_addr(pt_regs_read_reg(regs, rt)); 473 473 474 474 switch (crm) { 475 475 case ESR_ELx_SYS64_ISS_CRM_DC_CVAU: /* DC CVAU, gets promoted */
+1 -1
mm/vmalloc.c
··· 521 521 } 522 522 } 523 523 524 - if (printk_ratelimit()) 524 + if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit()) 525 525 pr_warn("vmap allocation for size %lu failed: use vmalloc=<size> to increase size\n", 526 526 size); 527 527 kfree(va);