Skip to content

Commit

Permalink
Merge tag 'objtool-urgent-2025-04-10' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/linux/kernel/git/tip/tip

Pull misc objtool fixes from Ingo Molnar:

 - Remove the recently introduced ANNOTATE_IGNORE_ALTERNATIVE noise from
   clac()/stac() code to make .s files more readable

 - Fix INSN_SYSCALL / INSN_SYSRET semantics

 - Fix various false-positive warnings

* tag 'objtool-urgent-2025-04-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Fix false-positive "ignoring unreachables" warning
  objtool: Remove ANNOTATE_IGNORE_ALTERNATIVE from CLAC/STAC
  objtool, xen: Fix INSN_SYSCALL / INSN_SYSRET semantics
  objtool: Stop UNRET validation on UD2
  objtool: Split INSN_CONTEXT_SWITCH into INSN_SYSCALL and INSN_SYSRET
  objtool: Fix INSN_CONTEXT_SWITCH handling in validate_unret()
  • Loading branch information
Linus Torvalds committed Apr 10, 2025
2 parents ab59a86 + 87cb582 commit 54a012b
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 26 deletions.
12 changes: 6 additions & 6 deletions arch/x86/include/asm/smap.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@
#ifdef __ASSEMBLER__

#define ASM_CLAC \
ALTERNATIVE __stringify(ANNOTATE_IGNORE_ALTERNATIVE), "clac", X86_FEATURE_SMAP
ALTERNATIVE "", "clac", X86_FEATURE_SMAP

#define ASM_STAC \
ALTERNATIVE __stringify(ANNOTATE_IGNORE_ALTERNATIVE), "stac", X86_FEATURE_SMAP
ALTERNATIVE "", "stac", X86_FEATURE_SMAP

#else /* __ASSEMBLER__ */

static __always_inline void clac(void)
{
/* Note: a barrier is implicit in alternative() */
alternative(ANNOTATE_IGNORE_ALTERNATIVE "", "clac", X86_FEATURE_SMAP);
alternative("", "clac", X86_FEATURE_SMAP);
}

static __always_inline void stac(void)
{
/* Note: a barrier is implicit in alternative() */
alternative(ANNOTATE_IGNORE_ALTERNATIVE "", "stac", X86_FEATURE_SMAP);
alternative("", "stac", X86_FEATURE_SMAP);
}

static __always_inline unsigned long smap_save(void)
Expand All @@ -59,9 +59,9 @@ static __always_inline void smap_restore(unsigned long flags)

/* These macros can be used in asm() statements */
#define ASM_CLAC \
ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE "", "clac", X86_FEATURE_SMAP)
ALTERNATIVE("", "clac", X86_FEATURE_SMAP)
#define ASM_STAC \
ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE "", "stac", X86_FEATURE_SMAP)
ALTERNATIVE("", "stac", X86_FEATURE_SMAP)

#define ASM_CLAC_UNSAFE \
ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "clac", X86_FEATURE_SMAP)
Expand Down
4 changes: 1 addition & 3 deletions arch/x86/xen/xen-asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,7 @@ SYM_CODE_END(xen_early_idt_handler_array)
push %rax
mov $__HYPERVISOR_iret, %eax
syscall /* Do the IRET. */
#ifdef CONFIG_MITIGATION_SLS
int3
#endif
ud2 /* The SYSCALL should never return. */
.endm

SYM_CODE_START(xen_iret)
Expand Down
18 changes: 11 additions & 7 deletions tools/objtool/arch/x86/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
case INAT_PFX_REPNE:
if (modrm == 0xca)
/* eretu/erets */
insn->type = INSN_CONTEXT_SWITCH;
insn->type = INSN_SYSRET;
break;
default:
if (modrm == 0xca)
Expand All @@ -535,11 +535,15 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec

insn->type = INSN_JUMP_CONDITIONAL;

} else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
op2 == 0x35) {
} else if (op2 == 0x05 || op2 == 0x34) {

/* sysenter, sysret */
insn->type = INSN_CONTEXT_SWITCH;
/* syscall, sysenter */
insn->type = INSN_SYSCALL;

} else if (op2 == 0x07 || op2 == 0x35) {

/* sysret, sysexit */
insn->type = INSN_SYSRET;

} else if (op2 == 0x0b || op2 == 0xb9) {

Expand Down Expand Up @@ -676,7 +680,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec

case 0xca: /* retf */
case 0xcb: /* retf */
insn->type = INSN_CONTEXT_SWITCH;
insn->type = INSN_SYSRET;
break;

case 0xe0: /* loopne */
Expand Down Expand Up @@ -721,7 +725,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
} else if (modrm_reg == 5) {

/* jmpf */
insn->type = INSN_CONTEXT_SWITCH;
insn->type = INSN_SYSRET;

} else if (modrm_reg == 6) {

Expand Down
2 changes: 1 addition & 1 deletion tools/objtool/arch/x86/special.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
* indicates a rare GCC quirk/bug which can leave dead
* code behind.
*/
if (reloc_type(text_reloc) == R_X86_64_PC32) {
if (!file->ignore_unreachables && reloc_type(text_reloc) == R_X86_64_PC32) {
WARN_INSN(insn, "ignoring unreachables due to jump table quirk");
file->ignore_unreachables = true;
}
Expand Down
59 changes: 51 additions & 8 deletions tools/objtool/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -3505,6 +3505,34 @@ static struct instruction *next_insn_to_validate(struct objtool_file *file,
return next_insn_same_sec(file, alt_group->orig_group->last_insn);
}

static bool skip_alt_group(struct instruction *insn)
{
struct instruction *alt_insn = insn->alts ? insn->alts->insn : NULL;

/* ANNOTATE_IGNORE_ALTERNATIVE */
if (insn->alt_group && insn->alt_group->ignore)
return true;

/*
* For NOP patched with CLAC/STAC, only follow the latter to avoid
* impossible code paths combining patched CLAC with unpatched STAC
* or vice versa.
*
* ANNOTATE_IGNORE_ALTERNATIVE could have been used here, but Linus
* requested not to do that to avoid hurting .s file readability
* around CLAC/STAC alternative sites.
*/

if (!alt_insn)
return false;

/* Don't override ASM_{CLAC,STAC}_UNSAFE */
if (alt_insn->alt_group && alt_insn->alt_group->ignore)
return false;

return alt_insn->type == INSN_CLAC || alt_insn->type == INSN_STAC;
}

/*
* Follow the branch starting at the given instruction, and recursively follow
* any other branches (jumps). Meanwhile, track the frame pointer state at
Expand Down Expand Up @@ -3625,7 +3653,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
}
}

if (insn->alt_group && insn->alt_group->ignore)
if (skip_alt_group(insn))
return 0;

if (handle_insn_ops(insn, next_insn, &state))
Expand Down Expand Up @@ -3684,14 +3712,20 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,

break;

case INSN_CONTEXT_SWITCH:
if (func) {
if (!next_insn || !next_insn->hint) {
WARN_INSN(insn, "unsupported instruction in callable function");
return 1;
}
break;
case INSN_SYSCALL:
if (func && (!next_insn || !next_insn->hint)) {
WARN_INSN(insn, "unsupported instruction in callable function");
return 1;
}

break;

case INSN_SYSRET:
if (func && (!next_insn || !next_insn->hint)) {
WARN_INSN(insn, "unsupported instruction in callable function");
return 1;
}

return 0;

case INSN_STAC:
Expand Down Expand Up @@ -3886,6 +3920,12 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
WARN_INSN(insn, "RET before UNTRAIN");
return 1;

case INSN_SYSCALL:
break;

case INSN_SYSRET:
return 0;

case INSN_NOP:
if (insn->retpoline_safe)
return 0;
Expand All @@ -3895,6 +3935,9 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
break;
}

if (insn->dead_end)
return 0;

if (!next) {
WARN_INSN(insn, "teh end!");
return 1;
Expand Down
3 changes: 2 additions & 1 deletion tools/objtool/include/objtool/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ enum insn_type {
INSN_CALL,
INSN_CALL_DYNAMIC,
INSN_RETURN,
INSN_CONTEXT_SWITCH,
INSN_SYSCALL,
INSN_SYSRET,
INSN_BUG,
INSN_NOP,
INSN_STAC,
Expand Down

0 comments on commit 54a012b

Please sign in to comment.