From: Dong Kai dongkai11@huawei.com
hulk inclusion category: bugfix bugzilla: 50425 CVE: NA
---------------------------
The jump_label_apply_nops is used to replace default nops with ideal nops. This can be called only once per module. The current logic is incorrent as it is called per klp_object. Then if klp patch contains multi klp_object to be patched, it will be called more than one times, and lead to following crash:
livepatch_scsi_test: loading out-of-tree module taints kernel. livepatch_scsi_test: tainting kernel with TAINT_LIVEPATCH jump_label: Fatal kernel bug, unexpected op at patch_exit+0x0/0x38 [livepatch_scsi_test] [(____ptrval____)] (66 66 66 66 90) 80 ------------[ cut here ]------------ kernel BUG at arch/x86/kernel/jump_label.c:37! invalid opcode: 0000 [#1] SMP NOPTI CPU: 0 PID: 116 Comm: insmod Tainted: G OE K --------- - - 4.18.0+ #13 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 RIP: 0010:bug_at+0x1d/0x20 Code: 02 ba d1 04 00 00 ee c3 90 90 90 90 90 66 66 66 66 90 41 89 f0 48 89 f9 48 89 fa 48 89 fe 48 c7 c7 98 79 c6 9d e8 01 79 0f 00 <0f> 0b 90 66 66 66 66 90 48 83 ec 18 48 8b 3f 65 48 8b 04 25 28
RSP: 0018:ffffb074c0563bb0 EFLAGS: 00000282 RAX: 000000000000007f RBX: ffffffffc036f018 RCX: ffffffff9de5abc8 RDX: 0000000000000000 RSI: 0000000000000082 RDI: 0000000000000246 RBP: ffffffffc036f018 R08: 0000000000000175 R09: 20363628205d295f R10: ffffa00743f8b580 R11: 3038202930392036 R12: ffffa00743f7fb40 R13: ffffffffc036f100 R14: ffffa00743f22160 R15: 0000000000000001 FS: 0000000001a088c0(0000) GS:ffffa00747800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000001a0f000 CR3: 0000000003fb6000 CR4: 00000000000006f0 Call Trace: __jump_label_transform.isra.0+0x50/0x130 jump_label_apply_nops+0x64/0x70 klp_register_patch+0x55b/0x6f0 ? _cond_resched+0x15/0x40 ? kmem_cache_alloc_trace+0x1a6/0x1c0 ? patch_free_scaffold+0xa7/0xbf [livepatch_scsi_test] patch_init+0x43e/0x1000 [livepatch_scsi_test] ? 0xffffffffc037f000 do_one_initcall+0x46/0x1c8 ? free_unref_page_commit+0x95/0x120 ? _cond_resched+0x15/0x40 ? kmem_cache_alloc_trace+0x3e/0x1c0 do_init_module+0x5b/0x1fc load_module+0x15b1/0x1e50 ? vmap_page_range_noflush+0x33f/0x4a0 ? __do_sys_init_module+0x167/0x1a0 __do_sys_init_module+0x167/0x1a0 do_syscall_64+0x5b/0x1b0 entry_SYSCALL_64_after_hwframe+0x65/0xca RIP: 0033:0x4d63a9
To solve this, we put the jump_label_apply_nops to klp_init_patch.
Fixes: 61ddd2126320 ("livepatch/core: support jump_label") Signed-off-by: Dong Kai dongkai11@huawei.com Reviewed-by: Yang Jihong yangjihong1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- kernel/livepatch/core.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 81c8b02ce3d1..c981d400fe55 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -1074,17 +1074,10 @@ static int klp_init_object_loaded(struct klp_patch *patch, }
arch_klp_init_object_loaded(patch, obj); - - set_mod_klp_rel_state(patch->mod, MODULE_KLP_REL_DONE); - jump_label_apply_nops(patch->mod); module_enable_ro(patch->mod, true);
mutex_unlock(&text_mutex);
- ret = jump_label_register(patch->mod); - if (ret) - return ret; - klp_for_each_func(obj, func) { ret = klp_find_object_symbol(obj->name, func->old_name, func->old_sympos, @@ -1222,6 +1215,19 @@ static int klp_init_patch(struct klp_patch *patch) goto free; }
+ set_mod_klp_rel_state(patch->mod, MODULE_KLP_REL_DONE); + mutex_lock(&text_mutex); + module_disable_ro(patch->mod); + jump_label_apply_nops(patch->mod); + ret = jump_label_register(patch->mod); + if (ret) { + module_enable_ro(patch->mod, true); + mutex_unlock(&text_mutex); + goto free; + } + module_enable_ro(patch->mod, true); + mutex_unlock(&text_mutex); + #ifdef CONFIG_LIVEPATCH_WO_FTRACE klp_for_each_object(patch, obj) klp_load_hook(obj);