Skip to content

Commit

Permalink
Merge tag 'objtool-core-2025-01-20' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/tip/tip

Pull objtool updates from Ingo Molnar:

 - Introduce the generic section-based annotation infrastructure a.k.a.
   ASM_ANNOTATE/ANNOTATE (Peter Zijlstra)

 - Convert various facilities to ASM_ANNOTATE/ANNOTATE: (Peter Zijlstra)
    - ANNOTATE_NOENDBR
    - ANNOTATE_RETPOLINE_SAFE
    - instrumentation_{begin,end}()
    - VALIDATE_UNRET_BEGIN
    - ANNOTATE_IGNORE_ALTERNATIVE
    - ANNOTATE_INTRA_FUNCTION_CALL
    - {.UN}REACHABLE

 - Optimize the annotation-sections parsing code (Peter Zijlstra)

 - Centralize annotation definitions in <linux/objtool.h>

 - Unify & simplify the barrier_before_unreachable()/unreachable()
   definitions (Peter Zijlstra)

 - Convert unreachable() calls to BUG() in x86 code, as unreachable()
   has unreliable code generation (Peter Zijlstra)

 - Remove annotate_reachable() and annotate_unreachable(), as it's
   unreliable against compiler optimizations (Peter Zijlstra)

 - Fix non-standard ANNOTATE_REACHABLE annotation order (Peter Zijlstra)

 - Robustify the annotation code by warning about unknown annotation
   types (Peter Zijlstra)

 - Allow arch code to discover jump table size, in preparation of
   annotated jump table support (Ard Biesheuvel)

* tag 'objtool-core-2025-01-20' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm: Convert unreachable() to BUG()
  objtool: Allow arch code to discover jump table size
  objtool: Warn about unknown annotation types
  objtool: Fix ANNOTATE_REACHABLE to be a normal annotation
  objtool: Convert {.UN}REACHABLE to ANNOTATE
  objtool: Remove annotate_{,un}reachable()
  loongarch: Use ASM_REACHABLE
  x86: Convert unreachable() to BUG()
  unreachable: Unify
  objtool: Collect more annotations in objtool.h
  objtool: Collapse annotate sequences
  objtool: Convert ANNOTATE_INTRA_FUNCTION_CALL to ANNOTATE
  objtool: Convert ANNOTATE_IGNORE_ALTERNATIVE to ANNOTATE
  objtool: Convert VALIDATE_UNRET_BEGIN to ANNOTATE
  objtool: Convert instrumentation_{begin,end}() to ANNOTATE
  objtool: Convert ANNOTATE_RETPOLINE_SAFE to ANNOTATE
  objtool: Convert ANNOTATE_NOENDBR to ANNOTATE
  objtool: Generic annotation infrastructure
  • Loading branch information
Linus Torvalds committed Jan 21, 2025
2 parents 8838a1a + 41a1e97 commit a6640c8
Show file tree
Hide file tree
Showing 22 changed files with 267 additions and 463 deletions.
13 changes: 7 additions & 6 deletions arch/loongarch/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <asm/break.h>
#include <linux/stringify.h>
#include <linux/objtool.h>

#ifndef CONFIG_DEBUG_BUGVERBOSE
#define _BUGVERBOSE_LOCATION(file, line)
Expand Down Expand Up @@ -33,25 +34,25 @@

#define ASM_BUG_FLAGS(flags) \
__BUG_ENTRY(flags) \
break BRK_BUG
break BRK_BUG;

#define ASM_BUG() ASM_BUG_FLAGS(0)

#define __BUG_FLAGS(flags) \
asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags)));
#define __BUG_FLAGS(flags, extra) \
asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags)) \
extra);

#define __WARN_FLAGS(flags) \
do { \
instrumentation_begin(); \
__BUG_FLAGS(BUGFLAG_WARNING|(flags)); \
annotate_reachable(); \
__BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\
instrumentation_end(); \
} while (0)

#define BUG() \
do { \
instrumentation_begin(); \
__BUG_FLAGS(0); \
__BUG_FLAGS(0, ""); \
unreachable(); \
} while (0)

Expand Down
9 changes: 4 additions & 5 deletions arch/x86/entry/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,9 @@ SYM_CODE_END(xen_error_entry)
movq $-1, ORIG_RAX(%rsp) /* no syscall to restart */
.endif

call \cfunc

/* For some configurations \cfunc ends up being a noreturn. */
REACHABLE
ANNOTATE_REACHABLE
call \cfunc

jmp error_return
.endm
Expand Down Expand Up @@ -529,10 +528,10 @@ SYM_CODE_START(\asmsym)
movq %rsp, %rdi /* pt_regs pointer into first argument */
movq ORIG_RAX(%rsp), %rsi /* get error code into 2nd argument*/
movq $-1, ORIG_RAX(%rsp) /* no syscall to restart */
call \cfunc

/* For some configurations \cfunc ends up being a noreturn. */
REACHABLE
ANNOTATE_REACHABLE
call \cfunc

jmp paranoid_exit

Expand Down
22 changes: 1 addition & 21 deletions arch/x86/include/asm/alternative.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <linux/types.h>
#include <linux/stringify.h>
#include <linux/objtool.h>
#include <asm/asm.h>

#define ALT_FLAGS_SHIFT 16
Expand Down Expand Up @@ -54,16 +55,6 @@
#define LOCK_PREFIX ""
#endif

/*
* objtool annotation to ignore the alternatives and only consider the original
* instruction(s).
*/
#define ANNOTATE_IGNORE_ALTERNATIVE \
"999:\n\t" \
".pushsection .discard.ignore_alts\n\t" \
".long 999b\n\t" \
".popsection\n\t"

/*
* The patching flags are part of the upper bits of the @ft_flags parameter when
* specifying them. The split is currently like this:
Expand Down Expand Up @@ -310,17 +301,6 @@ void nop_func(void);
.endm
#endif

/*
* objtool annotation to ignore the alternatives and only consider the original
* instruction(s).
*/
.macro ANNOTATE_IGNORE_ALTERNATIVE
.Lannotate_\@:
.pushsection .discard.ignore_alts
.long .Lannotate_\@
.popsection
.endm

/*
* Issue one struct alt_instr descriptor entry (need to put it into
* the section .altinstructions, see below). This entry contains
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ do { \
do { \
__auto_type __flags = BUGFLAG_WARNING|(flags); \
instrumentation_begin(); \
_BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE); \
_BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE(1b)); \
instrumentation_end(); \
} while (0)

Expand Down
4 changes: 2 additions & 2 deletions arch/x86/include/asm/irq_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@
}

#define ASM_CALL_ARG0 \
"call %c[__func] \n" \
ASM_REACHABLE
"1: call %c[__func] \n" \
ANNOTATE_REACHABLE(1b)

#define ASM_CALL_ARG1 \
"movq %[arg1], %%rdi \n" \
Expand Down
18 changes: 0 additions & 18 deletions arch/x86/include/asm/nospec-branch.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,6 @@

#ifdef __ASSEMBLY__

/*
* This should be used immediately before an indirect jump/call. It tells
* objtool the subsequent indirect jump/call is vouched safe for retpoline
* builds.
*/
.macro ANNOTATE_RETPOLINE_SAFE
.Lhere_\@:
.pushsection .discard.retpoline_safe
.long .Lhere_\@
.popsection
.endm

/*
* (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions
* vs RETBleed validation.
Expand Down Expand Up @@ -350,12 +338,6 @@

#else /* __ASSEMBLY__ */

#define ANNOTATE_RETPOLINE_SAFE \
"999:\n\t" \
".pushsection .discard.retpoline_safe\n\t" \
".long 999b\n\t" \
".popsection\n\t"

typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE];
extern retpoline_thunk_t __x86_indirect_thunk_array[];
extern retpoline_thunk_t __x86_indirect_call_thunk_array[];
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ void __noreturn stop_this_cpu(void *dummy)
#ifdef CONFIG_SMP
if (smp_ops.stop_this_cpu) {
smp_ops.stop_this_cpu();
unreachable();
BUG();
}
#endif

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/reboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ static int crash_nmi_callback(unsigned int val, struct pt_regs *regs)

if (smp_ops.stop_this_cpu) {
smp_ops.stop_this_cpu();
unreachable();
BUG();
}

/* Assume hlt works */
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kvm/svm/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3820,7 +3820,7 @@ static int snp_begin_psc(struct vcpu_svm *svm, struct psc_buffer *psc)
goto next_range;
}

unreachable();
BUG();
}

static int __sev_snp_update_protected_guest_state(struct kvm_vcpu *vcpu)
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code,
ASM_CALL_ARG3,
, [arg1] "r" (regs), [arg2] "r" (address), [arg3] "r" (&info));

unreachable();
BUG();
}
#endif

Expand Down
12 changes: 0 additions & 12 deletions include/linux/compiler-gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,6 @@
*/
#define barrier_before_unreachable() asm volatile("")

/*
* Mark a position in code as unreachable. This can be used to
* suppress control flow warnings after asm blocks that transfer
* control elsewhere.
*/
#define unreachable() \
do { \
annotate_unreachable(); \
barrier_before_unreachable(); \
__builtin_unreachable(); \
} while (0)

#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
#define __HAVE_BUILTIN_BSWAP32__
#define __HAVE_BUILTIN_BSWAP64__
Expand Down
37 changes: 7 additions & 30 deletions include/linux/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,44 +109,21 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,

/* Unreachable code */
#ifdef CONFIG_OBJTOOL
/*
* These macros help objtool understand GCC code flow for unreachable code.
* The __COUNTER__ based labels are a hack to make each instance of the macros
* unique, to convince GCC not to merge duplicate inline asm statements.
*/
#define __stringify_label(n) #n

#define __annotate_reachable(c) ({ \
asm volatile(__stringify_label(c) ":\n\t" \
".pushsection .discard.reachable\n\t" \
".long " __stringify_label(c) "b - .\n\t" \
".popsection\n\t"); \
})
#define annotate_reachable() __annotate_reachable(__COUNTER__)

#define __annotate_unreachable(c) ({ \
asm volatile(__stringify_label(c) ":\n\t" \
".pushsection .discard.unreachable\n\t" \
".long " __stringify_label(c) "b - .\n\t" \
".popsection\n\t" : : "i" (c)); \
})
#define annotate_unreachable() __annotate_unreachable(__COUNTER__)

/* Annotate a C jump table to allow objtool to follow the code flow */
#define __annotate_jump_table __section(".rodata..c_jump_table,\"a\",@progbits #")

#else /* !CONFIG_OBJTOOL */
#define annotate_reachable()
#define annotate_unreachable()
#define __annotate_jump_table
#endif /* CONFIG_OBJTOOL */

#ifndef unreachable
# define unreachable() do { \
annotate_unreachable(); \
/*
* Mark a position in code as unreachable. This can be used to
* suppress control flow warnings after asm blocks that transfer
* control elsewhere.
*/
#define unreachable() do { \
barrier_before_unreachable(); \
__builtin_unreachable(); \
} while (0)
#endif

/*
* KENTRY - kernel entry point
Expand Down
11 changes: 5 additions & 6 deletions include/linux/instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

#ifdef CONFIG_NOINSTR_VALIDATION

#include <linux/objtool.h>
#include <linux/stringify.h>

/* Begin/end of an instrumentation safe region */
#define __instrumentation_begin(c) ({ \
asm volatile(__stringify(c) ": nop\n\t" \
".pushsection .discard.instr_begin\n\t" \
".long " __stringify(c) "b - .\n\t" \
".popsection\n\t" : : "i" (c)); \
ANNOTATE_INSTR_BEGIN(__ASM_BREF(c)) \
: : "i" (c)); \
})
#define instrumentation_begin() __instrumentation_begin(__COUNTER__)

Expand Down Expand Up @@ -48,9 +48,8 @@
*/
#define __instrumentation_end(c) ({ \
asm volatile(__stringify(c) ": nop\n\t" \
".pushsection .discard.instr_end\n\t" \
".long " __stringify(c) "b - .\n\t" \
".popsection\n\t" : : "i" (c)); \
ANNOTATE_INSTR_END(__ASM_BREF(c)) \
: : "i" (c)); \
})
#define instrumentation_end() __instrumentation_end(__COUNTER__)
#else /* !CONFIG_NOINSTR_VALIDATION */
Expand Down
Loading

0 comments on commit a6640c8

Please sign in to comment.