mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
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:
commit
9d7d4ad222
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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"
|
||||||
|
@ -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 \
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user