Skip to content

Commit

Permalink
create-diff-object: convert global symbols to local
Browse files Browse the repository at this point in the history
As reported in PR #658, when patching an exported function which is used
by the patch module init code, the init code will incorrectly link to
the patched version of the function and will call the patched function
before its relocations have been applied.

For example, when patching __kmalloc(), I see:

  # insmod kpatch-kmalloc.ko
  kpatch_kmalloc: module is marked as livepatch module, but livepatch support is disabled
  kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
  BUG: unable to handle kernel paging request at ffffc90001d03c58
  IP: 0xffffc90001d03c58
  PGD 7c8b4067
  PUD 7c8b5067
  PMD 755f7067
  PTE 800000007ad03163
  Oops: 0011 [#1] PREEMPT SMP
  Modules linked in: kpatch_kmalloc(OE+) kpatch(OE) ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 xt_conntrack cfg80211 rfkill ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw snd_hda_codec_generic ppdev crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel snd_hda_intel virtio_balloon snd_hda_codec snd_hwdep serio_raw virtio_console snd_hda_core parport_pc parport snd_pcm virtio_net snd_timer snd i2c_piix4 soundcore virtio_blk qxl drm_kms_helper ttm drm virtio_pci virtio_ring virtio ata_generic pata_acpi
  CPU: 1 PID: 1042 Comm: insmod Tainted: G           OE   4.10.0-rc5 #1
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.1-1.fc24 04/01/2014
  task: ffff88007560d480 task.stack: ffffc90001d00000
  RIP: 0010:0xffffc90001d03c58
  RSP: 0018:ffffc90001d03c50 EFLAGS: 00010286
  RAX: 0000000000000004 RBX: 0000000000000008 RCX: 0000000000000000
  RDX: 0000000000000000 RSI: 00000000014080c0 RDI: 0000000000000008
  RBP: ffff88007ad00058 R08: 0000000000000001 R09: 0000000000000001
  R10: 0000000000000000 R11: 0000000000000001 R12: 00000000fffffff4
  R13: ffffffffa0394ef0 R14: 0000000000000000 R15: ffffc90001d03ea8
  FS:  00007f9689d74700(0000) GS:ffff88007d000000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: ffffc90001d03c58 CR3: 000000007af1d000 CR4: 00000000001406e0
  Call Trace:
   ? kzalloc.constprop.6+0xe/0x10 [kpatch_kmalloc]
   ? patch_init+0xa6/0x1000 [kpatch_kmalloc]
   ? 0xffffffffa0399000
   ? do_one_initcall+0x52/0x1b0
   ? do_init_module+0x27/0x1fa
   ? rcu_read_lock_sched_held+0x4a/0x80
   ? kmem_cache_alloc_trace+0x28a/0x2f0
   ? do_init_module+0x5f/0x1fa
   ? load_module+0x2446/0x2b90
   ? __symbol_put+0x90/0x90
   ? vfs_read+0x137/0x180
   ? SYSC_finit_module+0xdf/0x110
   ? SyS_finit_module+0xe/0x10
   ? entry_SYSCALL_64_fastpath+0x1f/0xc2
  Code: c9 ff ff 10 00 00 00 00 00 00 00 86 02 01 00 00 00 00 00 50 3c d0 01 00 c9 ff ff 18 00 00 00 00 00 00 00 b4 33 39 a0 ff ff ff ff <a0> 3c d0 01 00 c9 ff ff a6 90 39 a0 ff ff ff ff 00 00 00 00 00
  RIP: 0xffffc90001d03c58 RSP: ffffc90001d03c50
  CR2: ffffc90001d03c58
  • Loading branch information
jpoimboe committed Jan 23, 2017
1 parent 1dcf13f commit ac89945
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
9 changes: 9 additions & 0 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,15 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
log_debug("lookup for %s @ 0x%016lx len %lu\n",
sym->name, result.value, result.size);

/*
* Convert global symbols to local so other objects in
* the patch module (like the patch hook object's init
* code) won't link to this function and call it before
* its relocations have been applied.
*/
sym->bind = STB_LOCAL;
sym->sym.st_info = GELF_ST_INFO(sym->bind, sym->type);

/* add entry in text section */
funcs[index].old_addr = result.value;
funcs[index].old_size = result.size;
Expand Down
17 changes: 17 additions & 0 deletions test/integration/fedora-25/convert-global-local.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
This is a test for #658: a kernel panic seen when patching an exported
function (e.g., kmalloc) which is used by patch_init().
---
diff --git a/mm/slub.c b/mm/slub.c
index 067598a..b517aec 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3719,6 +3719,9 @@ void *__kmalloc(size_t size, gfp_t flags)
struct kmem_cache *s;
void *ret;

+ if (!jiffies)
+ printk("kpatch kmalloc\n");
+
if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
return kmalloc_large(size, flags);

0 comments on commit ac89945

Please sign in to comment.