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

Pull arm64 fixes from Will Deacon:
"The main thing is a fix to our FUTEX_WAKE_OP implementation which was
unbelievably broken, but did actually work for the one scenario that
GLIBC used to use.

Summary:

- Fix stack unwinding so we ignore user stacks

- Fix ftrace module PLT trampoline initialisation checks

- Fix terminally broken implementation of FUTEX_WAKE_OP atomics"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: futex: Fix FUTEX_WAKE_OP atomic ops with non-zero result value
arm64: backtrace: Don't bother trying to unwind the userspace stack
arm64/ftrace: fix inadvertent BUG() in trampoline check

+23 -16
+8 -8
arch/arm64/include/asm/futex.h
··· 30 30 " prfm pstl1strm, %2\n" \ 31 31 "1: ldxr %w1, %2\n" \ 32 32 insn "\n" \ 33 - "2: stlxr %w3, %w0, %2\n" \ 34 - " cbnz %w3, 1b\n" \ 33 + "2: stlxr %w0, %w3, %2\n" \ 34 + " cbnz %w0, 1b\n" \ 35 35 " dmb ish\n" \ 36 36 "3:\n" \ 37 37 " .pushsection .fixup,\"ax\"\n" \ ··· 50 50 static inline int 51 51 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr) 52 52 { 53 - int oldval = 0, ret, tmp; 53 + int oldval, ret, tmp; 54 54 u32 __user *uaddr = __uaccess_mask_ptr(_uaddr); 55 55 56 56 pagefault_disable(); 57 57 58 58 switch (op) { 59 59 case FUTEX_OP_SET: 60 - __futex_atomic_op("mov %w0, %w4", 60 + __futex_atomic_op("mov %w3, %w4", 61 61 ret, oldval, uaddr, tmp, oparg); 62 62 break; 63 63 case FUTEX_OP_ADD: 64 - __futex_atomic_op("add %w0, %w1, %w4", 64 + __futex_atomic_op("add %w3, %w1, %w4", 65 65 ret, oldval, uaddr, tmp, oparg); 66 66 break; 67 67 case FUTEX_OP_OR: 68 - __futex_atomic_op("orr %w0, %w1, %w4", 68 + __futex_atomic_op("orr %w3, %w1, %w4", 69 69 ret, oldval, uaddr, tmp, oparg); 70 70 break; 71 71 case FUTEX_OP_ANDN: 72 - __futex_atomic_op("and %w0, %w1, %w4", 72 + __futex_atomic_op("and %w3, %w1, %w4", 73 73 ret, oldval, uaddr, tmp, ~oparg); 74 74 break; 75 75 case FUTEX_OP_XOR: 76 - __futex_atomic_op("eor %w0, %w1, %w4", 76 + __futex_atomic_op("eor %w3, %w1, %w4", 77 77 ret, oldval, uaddr, tmp, oparg); 78 78 break; 79 79 default:
+5
arch/arm64/include/asm/module.h
··· 73 73 struct plt_entry get_plt_entry(u64 dst, void *pc); 74 74 bool plt_entries_equal(const struct plt_entry *a, const struct plt_entry *b); 75 75 76 + static inline bool plt_entry_is_initialized(const struct plt_entry *e) 77 + { 78 + return e->adrp || e->add || e->br; 79 + } 80 + 76 81 #endif /* __ASM_MODULE_H */
+1 -2
arch/arm64/kernel/ftrace.c
··· 107 107 trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline); 108 108 if (!plt_entries_equal(mod->arch.ftrace_trampoline, 109 109 &trampoline)) { 110 - if (!plt_entries_equal(mod->arch.ftrace_trampoline, 111 - &(struct plt_entry){})) { 110 + if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) { 112 111 pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n"); 113 112 return -EINVAL; 114 113 }
+9 -6
arch/arm64/kernel/traps.c
··· 102 102 void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) 103 103 { 104 104 struct stackframe frame; 105 - int skip; 105 + int skip = 0; 106 106 107 107 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 108 + 109 + if (regs) { 110 + if (user_mode(regs)) 111 + return; 112 + skip = 1; 113 + } 108 114 109 115 if (!tsk) 110 116 tsk = current; ··· 132 126 frame.graph = 0; 133 127 #endif 134 128 135 - skip = !!regs; 136 129 printk("Call trace:\n"); 137 130 do { 138 131 /* skip until specified stack frame */ ··· 181 176 return ret; 182 177 183 178 print_modules(); 184 - __show_regs(regs); 185 179 pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", 186 180 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), 187 181 end_of_stack(tsk)); 182 + show_regs(regs); 188 183 189 - if (!user_mode(regs)) { 190 - dump_backtrace(regs, tsk); 184 + if (!user_mode(regs)) 191 185 dump_instr(KERN_EMERG, regs); 192 - } 193 186 194 187 return ret; 195 188 }