mirror of https://github.com/dynup/kpatch
create-klp-module: Properly align merged .parainstructions sections
When a patch is composed of multiple .o files which have .parainstructions sections, loading the patch causes a panic: general protection fault: 0000 [#1] SMP Modules linked in: livepatch_4_9_88_1_20180518_1(OK+) livepatch_4_9_88_1_20180510_1(OK) ... CPU: 1 PID: 17257 Comm: insmod Tainted: G O K 4.9.0-6-amd64 #1 Debian 4.9.88-1 Hardware name: HP ProLiant MicroServer Gen8, BIOS J06 11/02/2015 task: ffff9ff3411a4480 task.stack: ffffac8f8271c000 RIP: 0010:[<ffffffff8ae2e1d0>] [<ffffffff8ae2e1d0>] apply_paravirt+0xc0/0x140 RSP: 0018:ffffac8f8271f9a0 EFLAGS: 00010216 RAX: 00010749ffffffff RBX: ffffffffc0940658 RCX: 0000000000000085 RDX: 00000000bfebfbff RSI: ffffac8f8271f9a2 RDI: 0000000000000246 RBP: ffffac8f8271f9a2 R08: 0000000000000085 R09: ffffffff8ae5acb0 R10: 0000000000000001 R11: ffff9ff3544b4400 R12: ffffffffc0940660 R13: 0000000000000000 R14: ffff9ff3544b49c0 R15: ffff9ff3b43f0800 FS: 00007f04c1cea700(0000) GS:ffff9ff3ca640000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000560cfd63e460 CR3: 00000001455c6000 CR4: 0000000000160670 Stack: 401f0ff889486973 6172007172006b00 746c00650031312e 007265746e655f69 74006e6f69007870 ffffac8f006e6f69 00ffac8f8271fa28 ffffffff8b13ae86 ffffac8f8271fa68 ffffffffc09471ec ffffffff8b7da9eb 0000000affffffff Call Trace: [<ffffffff8b13ae86>] ? vsscanf+0x4c6/0x800 [<ffffffff8b13b20e>] ? sscanf+0x4e/0x70 [<ffffffff8ae52be5>] ? arch_klp_init_object_loaded+0x105/0x130 [<ffffffff8b13b0be>] ? vsscanf+0x6fe/0x800 [<ffffffff8b13b20e>] ? sscanf+0x4e/0x70 [<ffffffff8aee29e8>] ? klp_init_object_loaded+0xf8/0x210 [<ffffffff8aee2d85>] ? klp_register_patch+0x285/0x390 [<ffffffffc09491fa>] ? patch_init+0x1fa/0x1000 [livepatch_4_9_88_1_20180518_1] [<ffffffffc0949000>] ? 0xffffffffc0949000 [<ffffffff8ae0218e>] ? do_one_initcall+0x4e/0x180 [<ffffffff8afc87dd>] ? __vunmap+0x6d/0xc0 [<ffffffff8afc87dd>] ? __vunmap+0x6d/0xc0 [<ffffffff8af7eaa1>] ? do_init_module+0x5b/0x1ed [<ffffffff8af025a6>] ? load_module+0x2596/0x2ab0 [<ffffffff8aefed50>] ? __symbol_put+0x60/0x60 [<ffffffff8af02d06>] ? SYSC_finit_module+0xc6/0xf0 [<ffffffff8ae03b7d>] ? do_syscall_64+0x8d/0xf0 [<ffffffff8b41244e>] ? entry_SYSCALL_64_after_swapgs+0x58/0xc6 Code: 8d 7c 05 00 e8 62 f7 ff ff 0f b6 53 f9 48 8b 7b f0 48 89 ee e8 f2 f8 ff ff 49 39 dc 76 57 44 0f b6 43 09 41 80 f8 ff 75 84 0f 0b <48> 8b 10 48 8d 7d 08 48 83 e7 f8 48 89 55 00 89 ca 48 8b 74 10 RIP [<ffffffff8ae2e1d0>] apply_paravirt+0xc0/0x140 RSP <ffffac8f8271f9a0> ---[ end trace 128c0fa6efe85d9e ]--- The panic is caused by a corrupt .klp.arch.vmlinux..parainstructions section: Relocation section [208] '.rela.klp.arch.vmlinux..parainstructions' for section [207] '.klp.arch.vmlinux..parainstructions' at offset 0x29dc78 contains 10 entries: Offset Type Value Addend Name 000000000000000000 X86_64_64 000000000000000000 +750 __get_user_pages 0x0000000000000010 X86_64_64 000000000000000000 +823 __get_user_pages 0x0000000000000020 X86_64_64 000000000000000000 +890 __get_user_pages 0x0000000000000030 X86_64_64 000000000000000000 +941 __get_user_pages 0x0000000000000040 X86_64_64 000000000000000000 +1631 __get_user_pages 0x0000000000000050 X86_64_64 000000000000000000 +1671 __get_user_pages 0x000000000000005c X86_64_64 000000000000000000 +1245 handle_userfault 0x000000000000006c X86_64_64 000000000000000000 +1340 handle_userfault 0x000000000000007c X86_64_64 000000000000000000 +1417 handle_userfault 0x000000000000008c X86_64_64 000000000000000000 +1717 handle_userfault The entries are supposed to be 16 bytes each, but notice they become misaligned starting with the 'handle_userfault' entry. This happens because the kernel linking process lies about the .parainstructions section size, underreporting it by four bytes. So when two .parainstructions sections are merged together, it results in a corrupted .klp.arch.vmlinux..parainstructions section. Fix it by properly aligning the section before merging it with another one. Fixes #852. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
This commit is contained in:
parent
8b1e193eae
commit
3d04265899
|
@ -292,6 +292,27 @@ static void create_klp_arch_sections(struct kpatch_elf *kelf, char *strings)
|
|||
* single .klp.arch.vmlinux..parainstructions section
|
||||
*/
|
||||
old_size = sec->data->d_size;
|
||||
|
||||
/*
|
||||
* Due to a quirk in how .parainstructions gets linked, the
|
||||
* section size doesn't encompass the last 4 bytes of the last
|
||||
* entry. Align the old size properly before merging.
|
||||
*/
|
||||
if (!strcmp(base->name, ".parainstructions")) {
|
||||
char *str;
|
||||
static int align_mask = 0;
|
||||
|
||||
if (!align_mask) {
|
||||
str = getenv("PARA_STRUCT_SIZE");
|
||||
if (!str)
|
||||
ERROR("PARA_STRUCT_SIZE not set");
|
||||
|
||||
align_mask = atoi(str) - 1;
|
||||
}
|
||||
|
||||
old_size = (old_size + align_mask) & ~align_mask;
|
||||
}
|
||||
|
||||
new_size = old_size + base->data->d_size;
|
||||
sec->data->d_buf = realloc(sec->data->d_buf, new_size);
|
||||
sec->data->d_size = new_size;
|
||||
|
|
Loading…
Reference in New Issue