Skip to content

Commit

Permalink
create-diff-object: check NOP-padded instruction when symbol missing
Browse files Browse the repository at this point in the history
commit 3e54c63 has added support for x86
NOP-padded functions.

However, it works only when pfx symbol exists.

In fedora 39 with kernel 6.7.4-200.fc39.x86_64.
I met the following error:
kpatch_bundle_symbols: 251: symbol uptime_proc_show at
offset 16 within section .text.uptime_proc_show, expected 0.

Problem here is, the symbol table of uptime.o has no __pfx symbol.

To solve this problem, we can add a check if the padding area
is filled with nop instructions.

Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
  • Loading branch information
anatasluo committed Feb 20, 2024
1 parent 0edd6e4 commit f94ca46
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,37 @@ static struct rela *toc_rela(const struct rela *rela)
(unsigned int)rela->addend);
}

static bool padding_is_all_nops(enum architecture arch, struct symbol *sym,
unsigned int expected_offset)
{
unsigned char *padding = NULL;
unsigned long len = sym->sym.st_value;
unsigned int i;
unsigned char nops_insn;

if (expected_offset != 0 || !sym->sec)
return false;

switch (arch) {
case X86_64:
nops_insn = (unsigned char)0x90;
break;
default:
return false;
}

padding = sym->sec->data->d_buf;
for (i = 0; i < len; i ++) {
/*
* For other architecture, len of nops may not be one char.
* In that case, we can compare two arrays.
*/
if (padding[i] != nops_insn)
return false;
}
return true;
}

/*
* When compiling with -ffunction-sections and -fdata-sections, almost every
* symbol gets its own dedicated section. We call such symbols "bundled"
Expand All @@ -247,7 +278,8 @@ static void kpatch_bundle_symbols(struct kpatch_elf *kelf)
else
expected_offset = 0;

if (sym->sym.st_value != expected_offset) {
if (sym->sym.st_value != expected_offset &&
!padding_is_all_nops(kelf->arch, sym, expected_offset)) {
ERROR("symbol %s at offset %lu within section %s, expected %u",
sym->name, sym->sym.st_value,
sym->sec->name, expected_offset);
Expand Down

0 comments on commit f94ca46

Please sign in to comment.