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 'x86_entry_for_5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 entry fixes from Borislav Petkov:
"This is the x86/entry urgent pile which has accumulated since the
merge window.

It is not the smallest but considering the almost complete entry core
rewrite, the amount of fixes to follow is somewhat higher than usual,
which is to be expected.

Peter Zijlstra says:
'These patches address a number of instrumentation issues that were
found after the x86/entry overhaul. When combined with rcu/urgent
and objtool/urgent, these patches make UBSAN/KASAN/KCSAN happy
again.

Part of making this all work is bumping the minimum GCC version for
KASAN builds to gcc-8.3, the reason for this is that the
__no_sanitize_address function attribute is broken in GCC releases
before that.

No known GCC version has a working __no_sanitize_undefined, however
because the only noinstr violation that results from this happens
when an UB is found, we treat it like WARN. That is, we allow it to
violate the noinstr rules in order to get the warning out'"

* tag 'x86_entry_for_5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/entry: Fix #UD vs WARN more
x86/entry: Increase entry_stack size to a full page
x86/entry: Fixup bad_iret vs noinstr
objtool: Don't consider vmlinux a C-file
kasan: Fix required compiler version
compiler_attributes.h: Support no_sanitize_undefined check with GCC 4
x86/entry, bug: Comment the instrumentation_begin() usage for WARN()
x86/entry, ubsan, objtool: Whitelist __ubsan_handle_*()
x86/entry, cpumask: Provide non-instrumented variant of cpu_is_offline()
compiler_types.h: Add __no_sanitize_{address,undefined} to noinstr
kasan: Bump required compiler version
x86, kcsan: Add __no_kcsan to noinstr
kcsan: Remove __no_kcsan_or_inline
x86, kcsan: Remove __no_kcsan_or_inline usage

+127 -62
-6
Documentation/dev-tools/kcsan.rst
··· 114 114 To dynamically limit for which functions to generate reports, see the 115 115 `DebugFS interface`_ blacklist/whitelist feature. 116 116 117 - For ``__always_inline`` functions, replace ``__always_inline`` with 118 - ``__no_kcsan_or_inline`` (which implies ``__always_inline``):: 119 - 120 - static __no_kcsan_or_inline void foo(void) { 121 - ... 122 - 123 117 * To disable data race detection for a particular compilation unit, add to the 124 118 ``Makefile``:: 125 119
+1 -5
arch/x86/include/asm/bitops.h
··· 201 201 return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, c, "Ir", nr); 202 202 } 203 203 204 - static __no_kcsan_or_inline bool constant_test_bit(long nr, const volatile unsigned long *addr) 204 + static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr) 205 205 { 206 - /* 207 - * Because this is a plain access, we need to disable KCSAN here to 208 - * avoid double instrumentation via instrumented bitops. 209 - */ 210 206 return ((1UL << (nr & (BITS_PER_LONG-1))) & 211 207 (addr[nr >> _BITOPS_LONG_SHIFT])) != 0; 212 208 }
+6
arch/x86/include/asm/bug.h
··· 75 75 unreachable(); \ 76 76 } while (0) 77 77 78 + /* 79 + * This instrumentation_begin() is strictly speaking incorrect; but it 80 + * suppresses the complaints from WARN()s in noinstr code. If such a WARN() 81 + * were to trigger, we'd rather wreck the machine in an attempt to get the 82 + * message out than not know about it. 83 + */ 78 84 #define __WARN_FLAGS(flags) \ 79 85 do { \ 80 86 instrumentation_begin(); \
+18
arch/x86/include/asm/cpumask.h
··· 11 11 12 12 extern void setup_cpu_local_masks(void); 13 13 14 + /* 15 + * NMI and MCE exceptions need cpu_is_offline() _really_ early, 16 + * provide an arch_ special for them to avoid instrumentation. 17 + */ 18 + #if NR_CPUS > 1 19 + static __always_inline bool arch_cpu_online(int cpu) 20 + { 21 + return arch_test_bit(cpu, cpumask_bits(cpu_online_mask)); 22 + } 23 + #else 24 + static __always_inline bool arch_cpu_online(int cpu) 25 + { 26 + return cpu == 0; 27 + } 28 + #endif 29 + 30 + #define arch_cpu_is_offline(cpu) unlikely(!arch_cpu_online(cpu)) 31 + 14 32 #endif /* __ASSEMBLY__ */ 15 33 #endif /* _ASM_X86_CPUMASK_H */
+1 -1
arch/x86/include/asm/processor.h
··· 370 370 #define IO_BITMAP_OFFSET_INVALID (__KERNEL_TSS_LIMIT + 1) 371 371 372 372 struct entry_stack { 373 - unsigned long words[64]; 373 + char stack[PAGE_SIZE]; 374 374 }; 375 375 376 376 struct entry_stack_page {
+1 -1
arch/x86/kernel/cpu/mce/core.c
··· 1083 1083 { 1084 1084 unsigned int cpu = smp_processor_id(); 1085 1085 1086 - if (cpu_is_offline(cpu) || 1086 + if (arch_cpu_is_offline(cpu) || 1087 1087 (crashing_cpu != -1 && crashing_cpu != cpu)) { 1088 1088 u64 mcgstatus; 1089 1089
+1 -1
arch/x86/kernel/nmi.c
··· 478 478 479 479 DEFINE_IDTENTRY_RAW(exc_nmi) 480 480 { 481 - if (IS_ENABLED(CONFIG_SMP) && cpu_is_offline(smp_processor_id())) 481 + if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id())) 482 482 return; 483 483 484 484 if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
+42 -38
arch/x86/kernel/traps.c
··· 84 84 local_irq_disable(); 85 85 } 86 86 87 - int is_valid_bugaddr(unsigned long addr) 87 + __always_inline int is_valid_bugaddr(unsigned long addr) 88 88 { 89 - unsigned short ud; 90 - 91 89 if (addr < TASK_SIZE_MAX) 92 90 return 0; 93 91 94 - if (get_kernel_nofault(ud, (unsigned short *)addr)) 95 - return 0; 96 - 97 - return ud == INSN_UD0 || ud == INSN_UD2; 92 + /* 93 + * We got #UD, if the text isn't readable we'd have gotten 94 + * a different exception. 95 + */ 96 + return *(unsigned short *)addr == INSN_UD2; 98 97 } 99 98 100 99 static nokprobe_inline int ··· 215 216 ILL_ILLOPN, error_get_trap_addr(regs)); 216 217 } 217 218 219 + static noinstr bool handle_bug(struct pt_regs *regs) 220 + { 221 + bool handled = false; 222 + 223 + if (!is_valid_bugaddr(regs->ip)) 224 + return handled; 225 + 226 + /* 227 + * All lies, just get the WARN/BUG out. 228 + */ 229 + instrumentation_begin(); 230 + /* 231 + * Since we're emulating a CALL with exceptions, restore the interrupt 232 + * state to what it was at the exception site. 233 + */ 234 + if (regs->flags & X86_EFLAGS_IF) 235 + raw_local_irq_enable(); 236 + if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) { 237 + regs->ip += LEN_UD2; 238 + handled = true; 239 + } 240 + if (regs->flags & X86_EFLAGS_IF) 241 + raw_local_irq_disable(); 242 + instrumentation_end(); 243 + 244 + return handled; 245 + } 246 + 218 247 DEFINE_IDTENTRY_RAW(exc_invalid_op) 219 248 { 220 249 bool rcu_exit; 221 250 222 251 /* 223 - * Handle BUG/WARN like NMIs instead of like normal idtentries: 224 - * if we bugged/warned in a bad RCU context, for example, the last 225 - * thing we want is to BUG/WARN again in the idtentry code, ad 226 - * infinitum. 252 + * We use UD2 as a short encoding for 'CALL __WARN', as such 253 + * handle it before exception entry to avoid recursive WARN 254 + * in case exception entry is the one triggering WARNs. 227 255 */ 228 - if (!user_mode(regs) && is_valid_bugaddr(regs->ip)) { 229 - enum bug_trap_type type; 230 - 231 - nmi_enter(); 232 - instrumentation_begin(); 233 - trace_hardirqs_off_finish(); 234 - type = report_bug(regs->ip, regs); 235 - if (regs->flags & X86_EFLAGS_IF) 236 - trace_hardirqs_on_prepare(); 237 - instrumentation_end(); 238 - nmi_exit(); 239 - 240 - if (type == BUG_TRAP_TYPE_WARN) { 241 - /* Skip the ud2. */ 242 - regs->ip += LEN_UD2; 243 - return; 244 - } 245 - 246 - /* 247 - * Else, if this was a BUG and report_bug returns or if this 248 - * was just a normal #UD, we want to continue onward and 249 - * crash. 250 - */ 251 - } 256 + if (!user_mode(regs) && handle_bug(regs)) 257 + return; 252 258 253 259 rcu_exit = idtentry_enter_cond_rcu(regs); 254 260 instrumentation_begin(); ··· 695 691 (struct bad_iret_stack *)__this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1; 696 692 697 693 /* Copy the IRET target to the temporary storage. */ 698 - memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8); 694 + __memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8); 699 695 700 696 /* Copy the remainder of the stack from the current stack. */ 701 - memcpy(&tmp, s, offsetof(struct bad_iret_stack, regs.ip)); 697 + __memcpy(&tmp, s, offsetof(struct bad_iret_stack, regs.ip)); 702 698 703 699 /* Update the entry stack */ 704 - memcpy(new_stack, &tmp, sizeof(tmp)); 700 + __memcpy(new_stack, &tmp, sizeof(tmp)); 705 701 706 702 BUG_ON(!user_mode(&new_stack->regs)); 707 703 return new_stack;
+4
arch/x86/lib/memcpy_64.S
··· 8 8 #include <asm/alternative-asm.h> 9 9 #include <asm/export.h> 10 10 11 + .pushsection .noinstr.text, "ax" 12 + 11 13 /* 12 14 * We build a jump to memcpy_orig by default which gets NOPped out on 13 15 * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which ··· 185 183 .Lend: 186 184 retq 187 185 SYM_FUNC_END(memcpy_orig) 186 + 187 + .popsection 188 188 189 189 #ifndef CONFIG_UML 190 190
+8
include/linux/compiler-clang.h
··· 33 33 #define __no_sanitize_thread 34 34 #endif 35 35 36 + #if __has_feature(undefined_behavior_sanitizer) 37 + /* GCC does not have __SANITIZE_UNDEFINED__ */ 38 + #define __no_sanitize_undefined \ 39 + __attribute__((no_sanitize("undefined"))) 40 + #else 41 + #define __no_sanitize_undefined 42 + #endif 43 + 36 44 /* 37 45 * Not all versions of clang implement the the type-generic versions 38 46 * of the builtin overflow checkers. Fortunately, clang implements
+6
include/linux/compiler-gcc.h
··· 150 150 #define __no_sanitize_thread 151 151 #endif 152 152 153 + #if __has_attribute(__no_sanitize_undefined__) 154 + #define __no_sanitize_undefined __attribute__((no_sanitize_undefined)) 155 + #else 156 + #define __no_sanitize_undefined 157 + #endif 158 + 153 159 #if GCC_VERSION >= 50100 154 160 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 155 161 #endif
+1
include/linux/compiler_attributes.h
··· 40 40 # define __GCC4_has_attribute___noclone__ 1 41 41 # define __GCC4_has_attribute___nonstring__ 0 42 42 # define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8) 43 + # define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9) 43 44 # define __GCC4_has_attribute___fallthrough__ 0 44 45 #endif 45 46
+6 -8
include/linux/compiler_types.h
··· 118 118 #define notrace __attribute__((__no_instrument_function__)) 119 119 #endif 120 120 121 - /* Section for code which can't be instrumented at all */ 122 - #define noinstr \ 123 - noinline notrace __attribute((__section__(".noinstr.text"))) 124 - 125 121 /* 126 122 * it doesn't make sense on ARM (currently the only user of __naked) 127 123 * to trace naked functions because then mcount is called without ··· 189 193 190 194 #define __no_kcsan __no_sanitize_thread 191 195 #ifdef __SANITIZE_THREAD__ 192 - # define __no_kcsan_or_inline __no_kcsan notrace __maybe_unused 193 - # define __no_sanitize_or_inline __no_kcsan_or_inline 194 - #else 195 - # define __no_kcsan_or_inline __always_inline 196 + # define __no_sanitize_or_inline __no_kcsan notrace __maybe_unused 196 197 #endif 197 198 198 199 #ifndef __no_sanitize_or_inline 199 200 #define __no_sanitize_or_inline __always_inline 200 201 #endif 202 + 203 + /* Section for code which can't be instrumented at all */ 204 + #define noinstr \ 205 + noinline notrace __attribute((__section__(".noinstr.text"))) \ 206 + __no_kcsan __no_sanitize_address 201 207 202 208 #endif /* __KERNEL__ */ 203 209
+4
lib/Kconfig.kasan
··· 15 15 config CC_HAS_KASAN_SW_TAGS 16 16 def_bool $(cc-option, -fsanitize=kernel-hwaddress) 17 17 18 + config CC_HAS_WORKING_NOSANITIZE_ADDRESS 19 + def_bool !CC_IS_GCC || GCC_VERSION >= 80300 20 + 18 21 config KASAN 19 22 bool "KASAN: runtime memory debugger" 20 23 depends on (HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \ 21 24 (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS) 22 25 depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB) 26 + depends on CC_HAS_WORKING_NOSANITIZE_ADDRESS 23 27 help 24 28 Enables KASAN (KernelAddressSANitizer) - runtime memory debugger, 25 29 designed to find out-of-bounds accesses and use-after-free bugs.
+28 -2
tools/objtool/check.c
··· 2190 2190 return "{dynamic}"; 2191 2191 } 2192 2192 2193 + static inline bool noinstr_call_dest(struct symbol *func) 2194 + { 2195 + /* 2196 + * We can't deal with indirect function calls at present; 2197 + * assume they're instrumented. 2198 + */ 2199 + if (!func) 2200 + return false; 2201 + 2202 + /* 2203 + * If the symbol is from a noinstr section; we good. 2204 + */ 2205 + if (func->sec->noinstr) 2206 + return true; 2207 + 2208 + /* 2209 + * The __ubsan_handle_*() calls are like WARN(), they only happen when 2210 + * something 'BAD' happened. At the risk of taking the machine down, 2211 + * let them proceed to get the message out. 2212 + */ 2213 + if (!strncmp(func->name, "__ubsan_handle_", 15)) 2214 + return true; 2215 + 2216 + return false; 2217 + } 2218 + 2193 2219 static int validate_call(struct instruction *insn, struct insn_state *state) 2194 2220 { 2195 2221 if (state->noinstr && state->instr <= 0 && 2196 - (!insn->call_dest || !insn->call_dest->sec->noinstr)) { 2222 + !noinstr_call_dest(insn->call_dest)) { 2197 2223 WARN_FUNC("call to %s() leaves .noinstr.text section", 2198 2224 insn->sec, insn->offset, call_dest_name(insn)); 2199 2225 return 1; ··· 2772 2746 2773 2747 INIT_LIST_HEAD(&file.insn_list); 2774 2748 hash_init(file.insn_hash); 2775 - file.c_file = find_section_by_name(file.elf, ".comment"); 2749 + file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment"); 2776 2750 file.ignore_unreachables = no_unreachable; 2777 2751 file.hints = false; 2778 2752