Objtool changes for v6.13:

- Detect non-relocated text references for more robust
    IBT sealing (Josh Poimboeuf)
 
  - Fix build error when building stripped down
    UAPI headers (HONG Yifan)
 
  - Exclude __tracepoints data from ENDBR checks to fix
    false positives on clang builds (Peter Zijlstra)
 
  - Fix ORC unwind for newly forked tasks (Zheng Yejian)
 
  - Fix readelf related faddr2line regression (Carlos Llamas)
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmc7FYARHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1g5nQ//W6Hs6dUlQpHyq5af/QU7OHdxo8EQTvWR
 6i2Y+D/+N+Va69N3IaaCmiYkvO9AETl8IrVjur6XAHhHm5ylFAJ9AhRCs/DUcDqs
 OCzN263x2fH38GHf4WOc6mSUKJhR2/FN6/qfuf3bFKQytOciAZLn7GYRrtQdFd5v
 8rRbETMaqkRexEfFukEJr3gPggy7NGcyBhOz2RZHiEO3aUQxkhVcHkP2Sr2pUDkb
 8e+X30wYMzMbi9ZhBuu4prb4L3GPfDRIuPvBQfldQvMuayKJlZ10NMnlzDfFrFDd
 R34DXhELlheWGxBGGj9Rq2GbQLpjneZDOX7i8XtuaHljiYfUaQyAMdsLkvMiKnmb
 44iHIOEExm0MKcnMO3dWSYXPCT2bBiqnvFnh3J2eWBaXF9i9an7/b54xBnNpC3Al
 KYJWmOiDzr6NZ8UyDclqaNc0Zv31fBPYAji0T5gSFe2qsN6XpyjNOmyl0vH61eEI
 WQfYBjopbVsMW/7Dh95qXwK55D94QUhSba4yZepzwd9meOlgnO3QNNx2MwciGG7i
 G1TKPdsT8ndbkaDuk6iTsrGi5UpGhDyQ45agXM7w/K3EXMQLEP6eBno/U213jvQV
 kPBp0X0EbD7LezDsvC0Q4khfNSDELVq8F493ctQCOzqmQa4ypAwVz0HevZQsXSxO
 7bCNMxA7Klk=
 =eio4
 -----END PGP SIGNATURE-----

Merge tag 'objtool-core-2024-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool updates from Ingo Molnar:

 - Detect non-relocated text references for more robust
   IBT sealing (Josh Poimboeuf)

 - Fix build error when building stripped down
   UAPI headers (HONG Yifan)

 - Exclude __tracepoints data from ENDBR checks to fix
   false positives on clang builds (Peter Zijlstra)

 - Fix ORC unwind for newly forked tasks (Zheng Yejian)

 - Fix readelf related faddr2line regression (Carlos Llamas)

* tag 'objtool-core-2024-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Exclude __tracepoints data from ENDBR checks
  Revert "scripts/faddr2line: Check only two symbols when calculating symbol size"
  x86/unwind/orc: Fix unwind for newly forked tasks
  objtool: Also include tools/include/uapi
  objtool: Detect non-relocated text references
This commit is contained in:
Linus Torvalds 2024-11-19 13:27:52 -08:00
commit 9d7d4ad222
8 changed files with 81 additions and 55 deletions

View File

@ -87,6 +87,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
.align 4 .align 4
.Lresume_point: .Lresume_point:
ANNOTATE_NOENDBR
/* We don't restore %rax, it must be 0 anyway */ /* We don't restore %rax, it must be 0 anyway */
movq $saved_context, %rax movq $saved_context, %rax
movq saved_context_cr4(%rax), %rbx movq saved_context_cr4(%rax), %rbx

View File

@ -77,6 +77,7 @@ SYM_CODE_START_NOALIGN(startup_64)
lretq lretq
.Lon_kernel_cs: .Lon_kernel_cs:
ANNOTATE_NOENDBR
UNWIND_HINT_END_OF_STACK UNWIND_HINT_END_OF_STACK
#ifdef CONFIG_AMD_MEM_ENCRYPT #ifdef CONFIG_AMD_MEM_ENCRYPT

View File

@ -723,7 +723,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
state->sp = task->thread.sp + sizeof(*frame); state->sp = task->thread.sp + sizeof(*frame);
state->bp = READ_ONCE_NOCHECK(frame->bp); state->bp = READ_ONCE_NOCHECK(frame->bp);
state->ip = READ_ONCE_NOCHECK(frame->ret_addr); state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
state->signal = (void *)state->ip == ret_from_fork; state->signal = (void *)state->ip == ret_from_fork_asm;
} }
if (get_stack_info((unsigned long *)state->sp, state->task, if (get_stack_info((unsigned long *)state->sp, state->task,

View File

@ -252,7 +252,7 @@ __faddr2line() {
found=2 found=2
break break
fi fi
done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2 | ${GREP} -A1 --no-group-separator " ${sym_name}$") done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2)
if [[ $found = 0 ]]; then if [[ $found = 0 ]]; then
warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size" warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size"

View File

@ -24,6 +24,7 @@ LIBELF_LIBS := $(shell $(HOSTPKG_CONFIG) libelf --libs 2>/dev/null || echo -lel
all: $(OBJTOOL) all: $(OBJTOOL)
INCLUDES := -I$(srctree)/tools/include \ INCLUDES := -I$(srctree)/tools/include \
-I$(srctree)/tools/include/uapi \
-I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \ -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \
-I$(srctree)/tools/arch/$(SRCARCH)/include \ -I$(srctree)/tools/arch/$(SRCARCH)/include \
-I$(srctree)/tools/objtool/include \ -I$(srctree)/tools/objtool/include \

View File

@ -456,10 +456,6 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
if (!rex_w) if (!rex_w)
break; break;
/* skip RIP relative displacement */
if (is_RIP())
break;
/* skip nontrivial SIB */ /* skip nontrivial SIB */
if (have_SIB()) { if (have_SIB()) {
modrm_rm = sib_base; modrm_rm = sib_base;
@ -467,6 +463,12 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
break; break;
} }
/* lea disp(%rip), %dst */
if (is_RIP()) {
insn->type = INSN_LEA_RIP;
break;
}
/* lea disp(%src), %dst */ /* lea disp(%src), %dst */
ADD_OP(op) { ADD_OP(op) {
op->src.offset = ins.displacement.value; op->src.offset = ins.displacement.value;
@ -737,7 +739,10 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
break; break;
} }
insn->immediate = ins.immediate.nbytes ? ins.immediate.value : 0; if (ins.immediate.nbytes)
insn->immediate = ins.immediate.value;
else if (ins.displacement.nbytes)
insn->immediate = ins.displacement.value;
return 0; return 0;
} }

View File

@ -4392,58 +4392,12 @@ static bool noendbr_range(struct objtool_file *file, struct instruction *insn)
return insn->offset == sym->offset + sym->len; return insn->offset == sym->offset + sym->len;
} }
static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn) static int __validate_ibt_insn(struct objtool_file *file, struct instruction *insn,
struct instruction *dest)
{ {
struct instruction *dest;
struct reloc *reloc;
unsigned long off;
int warnings = 0;
/*
* Looking for function pointer load relocations. Ignore
* direct/indirect branches:
*/
switch (insn->type) {
case INSN_CALL:
case INSN_CALL_DYNAMIC:
case INSN_JUMP_CONDITIONAL:
case INSN_JUMP_UNCONDITIONAL:
case INSN_JUMP_DYNAMIC:
case INSN_JUMP_DYNAMIC_CONDITIONAL:
case INSN_RETURN:
case INSN_NOP:
return 0;
default:
break;
}
for (reloc = insn_reloc(file, insn);
reloc;
reloc = find_reloc_by_dest_range(file->elf, insn->sec,
reloc_offset(reloc) + 1,
(insn->offset + insn->len) - (reloc_offset(reloc) + 1))) {
/*
* static_call_update() references the trampoline, which
* doesn't have (or need) ENDBR. Skip warning in that case.
*/
if (reloc->sym->static_call_tramp)
continue;
off = reloc->sym->offset;
if (reloc_type(reloc) == R_X86_64_PC32 ||
reloc_type(reloc) == R_X86_64_PLT32)
off += arch_dest_reloc_offset(reloc_addend(reloc));
else
off += reloc_addend(reloc);
dest = find_insn(file, reloc->sym->sec, off);
if (!dest)
continue;
if (dest->type == INSN_ENDBR) { if (dest->type == INSN_ENDBR) {
mark_endbr_used(dest); mark_endbr_used(dest);
continue; return 0;
} }
if (insn_func(dest) && insn_func(insn) && if (insn_func(dest) && insn_func(insn) &&
@ -4463,25 +4417,87 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
* As such, blanket accept self-references without * As such, blanket accept self-references without
* issue. * issue.
*/ */
continue; return 0;
} }
/* /*
* Accept anything ANNOTATE_NOENDBR. * Accept anything ANNOTATE_NOENDBR.
*/ */
if (dest->noendbr) if (dest->noendbr)
continue; return 0;
/* /*
* Accept if this is the instruction after a symbol * Accept if this is the instruction after a symbol
* that is (no)endbr -- typical code-range usage. * that is (no)endbr -- typical code-range usage.
*/ */
if (noendbr_range(file, dest)) if (noendbr_range(file, dest))
continue; return 0;
WARN_INSN(insn, "relocation to !ENDBR: %s", offstr(dest->sec, dest->offset)); WARN_INSN(insn, "relocation to !ENDBR: %s", offstr(dest->sec, dest->offset));
return 1;
}
warnings++; static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn)
{
struct instruction *dest;
struct reloc *reloc;
unsigned long off;
int warnings = 0;
/*
* Looking for function pointer load relocations. Ignore
* direct/indirect branches:
*/
switch (insn->type) {
case INSN_CALL:
case INSN_CALL_DYNAMIC:
case INSN_JUMP_CONDITIONAL:
case INSN_JUMP_UNCONDITIONAL:
case INSN_JUMP_DYNAMIC:
case INSN_JUMP_DYNAMIC_CONDITIONAL:
case INSN_RETURN:
case INSN_NOP:
return 0;
case INSN_LEA_RIP:
if (!insn_reloc(file, insn)) {
/* local function pointer reference without reloc */
off = arch_jump_destination(insn);
dest = find_insn(file, insn->sec, off);
if (!dest) {
WARN_INSN(insn, "corrupt function pointer reference");
return 1;
}
return __validate_ibt_insn(file, insn, dest);
}
break;
default:
break;
}
for (reloc = insn_reloc(file, insn);
reloc;
reloc = find_reloc_by_dest_range(file->elf, insn->sec,
reloc_offset(reloc) + 1,
(insn->offset + insn->len) - (reloc_offset(reloc) + 1))) {
off = reloc->sym->offset;
if (reloc_type(reloc) == R_X86_64_PC32 ||
reloc_type(reloc) == R_X86_64_PLT32)
off += arch_dest_reloc_offset(reloc_addend(reloc));
else
off += reloc_addend(reloc);
dest = find_insn(file, reloc->sym->sec, off);
if (!dest)
continue;
warnings += __validate_ibt_insn(file, insn, dest);
} }
return warnings; return warnings;
@ -4557,6 +4573,7 @@ static int validate_ibt(struct objtool_file *file)
!strcmp(sec->name, "__jump_table") || !strcmp(sec->name, "__jump_table") ||
!strcmp(sec->name, "__mcount_loc") || !strcmp(sec->name, "__mcount_loc") ||
!strcmp(sec->name, ".kcfi_traps") || !strcmp(sec->name, ".kcfi_traps") ||
!strcmp(sec->name, "__tracepoints") ||
strstr(sec->name, "__patchable_function_entries")) strstr(sec->name, "__patchable_function_entries"))
continue; continue;

View File

@ -28,6 +28,7 @@ enum insn_type {
INSN_CLD, INSN_CLD,
INSN_TRAP, INSN_TRAP,
INSN_ENDBR, INSN_ENDBR,
INSN_LEA_RIP,
INSN_OTHER, INSN_OTHER,
}; };