https://sourceware.org/bugzilla/show_bug.cgi?id=34970
Bug ID: 34970
Summary: Stripping kpatch generated livepatches modules breaks
some relocations
Product: binutils
Version: 2.46
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: adamhet at scaleway dot com
Target Milestone: ---
Created attachment 17259
--> https://sourceware.org/bugzilla/attachment.cgi?id=17259&action=edit
scripts to build a kernel + livepatch used for reproduction
Running strip or objcopy on a livepatch module breaks secondary relocations.
Generating and testing is somewhat involved, I've included a tarball[1]
containing the unstripped livepatch module+kernel+initrd to reproduce. All the
binaries where generated/configured via a few helper scripts present in another
tarball[2].
```
$ readelf -aW patch-demo.ko| grep -A 3 .klp.rela
[64] .klp.rela.vmlinux..text.cmdline_proc_show RELA
0000000000000000 070410 000018 18 AIo 61 51 8
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
--
Relocation section '.klp.rela.vmlinux..text.cmdline_proc_show' at offset
0x70410 contains 1 entry:
Offset Info Type Symbol's Value
Symbol's Name + Addend
0000000000000018 0000006400000002 R_X86_64_PC32 0000000000000000
.klp.sym.vmlinux.saved_command_line,0 - 4
No processor specific unwind information to decode
$ strip --strip-debug -o patch-demo.stripped.ko patch-demo.ko
$ readelf -aW patch-demo.stripped.ko| grep .klp.rela
[47] .klp.rela.vmlinux..text.cmdline_proc_show LOOS+0x4
0000000000000000 001090 000018 18 Ao 0 0 8
$ ./run-qemu.sh
[...]
```
Once the guest boots, login as cirros:gocubsgo then escalate to root
```
# mount /dev/sda1 /mnt
# insmod /mnt/patch-demo.stripped.ko
[ 78.452426] patch_demo: loading out-of-tree module taints kernel.
[ 78.452863] patch_demo: tainting kernel with TAINT_LIVEPATCH
[ 78.458143] livepatch: enabling patch 'patch_demo'
[ 78.470940] livepatch: 'patch_demo': starting patching transition
[ 78.839387] livepatch: 'patch_demo': patching complete
# cat /proc/cmdline
[ 99.094393] Oops: general protection fault, probably for non-canonical
address 0xe8c0016336c6c748: 0000 [#1] PREEMI
[ 99.094976] CPU: 0 UID: 0 PID: 247 Comm: cat Tainted: G O K
6.12.115 #1
[ 99.095211] Tainted: [O]=OOT_MODULE, [K]=LIVEPATCH
[...]
```
This behavior also affects plain objcopy:
```
$ objcopy -I elf64-x86-64 -O elf64-x86-64 patch-demo.ko patch-demo.copy.ko
$ readelf -aW patch-demo.copy.ko| grep .klp.rela
[61] .klp.rela.vmlinux..text.cmdline_proc_show LOOS+0x4
0000000000000000 03cf80 000018 18 Ao 0 0 8
```
Bisection yields 2 distinct regressions:
The first one from `eb92a17c47ea497e3e1e11c33a290860a8b1f6a2` makes objcopy
error out the following way:
```
$ /tmp/builddir/binutils/objcopy -I elf64-x86-64 -O elf64-x86-64 patch-demo.ko
patch-demo.copy.ko
/tmp/builddir/binutils/objcopy:
patch-demo.copy.ko(.klp.rela.vmlinux..text.cmdline_proc_show): error: internal
relocs missing for secondary reloc section
/tmp/builddir/binutils/objcopy: patch-demo.copy.ko: bad value
```
This regression appears to be a typo in the refactoring that can be fixed with
the following patch:
```
diff --git a/bfd/elf.c b/bfd/elf.c
index 2cae97a6dd3a..c5534d304e5a 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -14004,7 +14004,7 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd,
asection *sec)
last_sym = NULL;
last_sym_idx = 0;
dst_rela = hdr->contents;
- src_irel = sec->sec_info;
+ src_irel = relsec->sec_info;
if (src_irel == NULL)
{
_bfd_error_handler
```
The corruption regression comes from `f5c3ce3687f7e1047c2f8a5c5dd9af2f36055663`
that stops calling `_bfd_elf_copy_special_section_fields` and can be fixed by
the following patch:
```
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 6912549446c1..68cc97bf1a75 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -5028,7 +5028,10 @@ _bfd_elf_x86_copy_special_section_fields
{
/* Return false for Solaris binary to properly set the sh_info and
sh_link fields of Solaris specific sections. */
- return elf_elfheader (ibfd)->e_ident[EI_OSABI] != ELFOSABI_SOLARIS;
+ if (elf_elfheader (ibfd)->e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+ return false;
+
+ return _bfd_elf_copy_special_section_fields (ibfd, obfd, isection,
osection);
}
void
```
With both patches applied, strip and the livepatch are working as expected:
```
$ strip --strip-debug -o patch-demo.stripped.ko patch-demo.ko
$ readelf -aW patch-demo.stripped.ko| grep -A 2 .klp.rela
[47] .klp.rela.vmlinux..text.cmdline_proc_show RELA
0000000000000000 001090 000018 18 Ao 48 37 8
[48] .symtab SYMTAB 0000000000000000 0010a8 000630 18
49 38 8
[49] .strtab STRTAB 0000000000000000 0016d8 000409 00
0 0 1
--
Relocation section '.klp.rela.vmlinux..text.cmdline_proc_show' at offset 0x1090
contains 1 entry:
Offset Info Type Symbol's Value
Symbol's Name + Addend
0000000000000018 0000004100000002 R_X86_64_PC32 0000000000000000
.klp.sym.vmlinux.saved_command_line,0 - 4
```
Both fixes are required to restore the original (pre 2.46) behavior. I'll send
the patches to the mailing list shortly.
[1]: https://data.xdbob.net/livepatch-binaries.tar.gz
[2]: attached (generate-livepatch.tar.gz)
--
You are receiving this mail because:
You are on the CC list for the bug.