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.

Reply via email to