From a683f7da21dd603c5689e3cb3fb44d105c80c295 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 3 Nov 2015 14:44:00 -0600 Subject: [PATCH] kmod/core: fix crash with !CONFIG_DEBUG_SET_MODULE_RONX When loading a patch module on a kernel with !CONFIG_DEBUG_SET_MODULE_RONX, the following crash occurs: loading core module: /root/src/kpatch/kpatch/../kmod/core/kpatch.ko loading patch module: kpatch-meminfo-string.ko BUG: unable to handle kernel paging request at ffffffffa0010cc0 IP: [] do_init_module+0x84/0x1af PGD 13d3067 PUD 13d4063 PMD 1e1ee067 PTE 1e1a0161 Oops: 0003 [#1] Modules linked in: kpatch_meminfo_string(O+) kpatch(O) CPU: 0 PID: 149 Comm: insmod Tainted: G O K 4.1.0+ #1 task: ffff88001e17b810 ti: ffff88001e1cc000 task.ti: ffff88001e1cc000 RIP: 0010:[] [] do_init_module+0x84/0x1af RSP: 0018:ffff88001e1cfda8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffffffffa0010cc0 RCX: 0000000080a02001 RDX: 0000000000000024 RSI: 0000000000000000 RDI: ffffffff813fabe0 RBP: 0000000000000000 R08: 0000000000000000 R09: 00000000d0000000 R10: ffffffffa000e000 R11: 0000000000000001 R12: ffff88001eb58638 R13: ffffffffa0010d10 R14: 0000000000000001 R15: 0000000000000000 FS: 00007f0ae00aa700(0000) GS:ffffffff813e1000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: ffffffffa0010cc0 CR3: 000000001e181000 CR4: 00000000000006b0 Stack: ffff88001e1cfed8 0000000000000001 ffffffffa0010cc0 ffffffff81058aac ffff88001e207680 00000000810a462f ffffc90000096890 0000000000000e00 ffffffff00000016 ffffffff8126cd40 ffff88001eaa6a08 ffff88001e1cfe48 Call Trace: [] ? load_module+0x18ad/0x18e9 [] ? copy_module_from_fd+0x86/0xdf [] ? SyS_finit_module+0x56/0x61 [] ? system_call_fastpath+0x12/0x6a Code: f8 00 00 00 74 23 49 c7 c0 80 ca 26 81 48 8d 53 18 89 c1 4c 89 c6 48 c7 c7 6d ef 36 81 31 c0 e8 16 fb ff ff e8 18 06 00 00 31 f6 03 00 00 00 00 48 89 da 48 c7 c7 c0 c9 3f 81 e8 7e b3 dd ff RIP [] do_init_module+0x84/0x1af RSP CR2: ffffffffa0010cc0 With !CONFIG_DEBUG_SET_MODULE_RONX, module text and rodata pages are writable, and the debug_align() macro allows the module struct to share a page with executable text. When klp_write_module_reloc() calls set_memory_ro() on the page, it effectively turns the module struct into a read-only structure, resulting in a page fault when load_module() does "mod->state = MODULE_STATE_LIVE". Fixes: #497 --- kmod/core/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kmod/core/core.c b/kmod/core/core.c index 7c16c7957..2d52607b6 100644 --- a/kmod/core/core.c +++ b/kmod/core/core.c @@ -584,7 +584,6 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod, struct kpatch_dynrela *dynrela; u64 loc, val; unsigned long core = (unsigned long)kpmod->mod->module_core; - unsigned long core_ro_size = kpmod->mod->core_ro_size; unsigned long core_size = kpmod->mod->core_size; unsigned long src; @@ -639,16 +638,17 @@ static int kpatch_write_relocations(struct kpatch_module *kpmod, return -EINVAL; } - if (loc >= core && loc < core + core_ro_size) - readonly = 1; - else if (loc >= core + core_ro_size && loc < core + core_size) - readonly = 0; - else { + if (loc < core || loc >= core + core_size) { pr_err("bad dynrela location 0x%llx for symbol %s\n", loc, dynrela->name); return -EINVAL; } +#ifdef CONFIG_DEBUG_SET_MODULE_RONX + if (loc < core + kpmod->mod->core_ro_size) + readonly = 1; +#endif + numpages = (PAGE_SIZE - (loc & ~PAGE_MASK) >= size) ? 1 : 2; if (readonly)