cannot hook __x64_sys_newuname to change uname Kernel 5.15.0-47-generic crash Unable to access opcode bytes at RIP 0xffffffffc1534f69
ydaniels opened this issue · comments
// Must pass the n to HOOK_FUNC_TEMPLATE()
HOOK_FUNC_TEMPLATE(__x64_sys_newuname);
// The hook function name must be "hook_ + origin_function_name"
long hook___x64_sys_newuname(struct new_utsname __user *name)
{
char *origin_newuname = GET_CODESPACE_ADDERSS(__x64_sys_newuname);
return (( long (*)(struct new_utsname __user *name))origin_newuname)(name);
}
Hooking works generally for other syscall but Getting this error while trying to hook uname on ubunutu 22
Here is stack trace
ode: Unable to access opcode bytes at RIP 0xffffffffc1534f69.
Sep 6 21:33:23 kernel: [ 8358.932020] RSP: 0018:ffffa8e242b43eb8 EFLAGS: 00010206
Sep 6 21:33:23 kernel: [ 8358.932023] RAX: ffffffffc15350b3 RBX: 0000000000000000 RCX: 0000000000000017
Sep 6 21:33:23 kernel: [ 8358.932025] RDX: ffffffffffffffff RSI: 0000000000000001 RDI: 00007ffd7f75cdf0
Sep 6 21:33:23 kernel: [ 8358.932027] RBP: ffffa8e242b43ec0 R08: 000000000000003f R09: 0000000000000000
Sep 6 21:33:23 kernel: [ 8358.932029] R10: 0000000000000001 R11: 0000000000000000 R12: ffffa8e242b43f58
Sep 6 21:33:23 kernel: [ 8358.932030] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
Sep 6 21:33:23 kernel: [ 8358.932032] FS: 00007fcc03d05e40(0000) GS:ffff9cc4a7540000(0000) knlGS:0000000000000000
Sep 6 21:33:23 kernel: [ 8358.932034] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Sep 6 21:33:23 kernel: [ 8358.932036] CR2: ffffffffc1534f69 CR3: 00000001b43a0005 CR4: 00000000003706e0
Sep 6 21:33:23 kernel: [ 8358.932038] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
Sep 6 21:33:23 kernel: [ 8358.932039] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Sep 6 21:33:28 kernel: [ 8364.104772] BUG: unable to handle page fault for address: ffffffffc1534f93
Sep 6 21:33:28 kernel: [ 8364.104779] #PF: supervisor instruction fetch in kernel mode
Sep 6 21:33:28 kernel: [ 8364.104781] #PF: error_code(0x0010) - not-present page
Sep 6 21:33:28 kernel: [ 8364.104783] PGD 119215067 P4D 119215067 PUD 119217067 PMD 12c4a6067 PTE 0
Sep 6 21:33:28 kernel: [ 8364.104789] Oops: 0010 [#3] SMP PTI
Sep 6 21:33:28 kernel: [ 8364.104792] CPU: 2 PID: 10310 Comm: uname Tainted: G D C OE 5.15.0-47-generic #51-Ubuntu
Sep 6 21:33:28 kernel: [ 8364.104796] Hardware name: Microsoft Corporation Surface Book 2/Surface Book 2, BIOS 390.3732.768 04.20.2021
Sep 6 21:33:28 kernel: [ 8364.104797] RIP: 0010:0xffffffffc1534f93
Sep 6 21:33:28 kernel: [ 8364.104802] Code: Unable to access opcode bytes at RIP 0xffffffffc1534f69.
Sep 6 21:33:28 kernel: [ 8364.104804] RSP: 0018:ffffa8e24333be58 EFLAGS: 00010206
Sep 6 21:33:28 kernel: [ 8364.104806] RAX: ffffffffc15350b3 RBX: 0000000000000000 RCX: 0000000000000017
Sep 6 21:33:28 kernel: [ 8364.104809] RDX: ffffffffffffffff RSI: 0000000000000001 RDI: 00007ffc607e91a0
Sep 6 21:33:28 kernel: [ 8364.104811] RBP: ffffa8e24333be60 R08: 000000000000003f R09: 0000000000000000
Sep 6 21:33:28 kernel: [ 8364.104812] R10: 0000000000000001 R11: 0000000000000000 R12: ffffa8e24333bf58
Sep 6 21:33:28 kernel: [ 8364.104814] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
Sep 6 21:33:28 kernel: [ 8364.104816] FS: 00007f6e39000740(0000) GS:ffff9cc4a7480000(0000) knlGS:0000000000000000
Sep 6 21:33:28 kernel: [ 8364.104819] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Sep 6 21:33:28 kernel: [ 8364.104821] CR2: ffffffffc1534f69 CR3: 000000018bac0004 CR4: 00000000003706e0
Sep 6 21:33:28 kernel: [ 8364.104823] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
Sep 6 21:33:28 kernel: [ 8364.104824] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Sep 6 21:33:28 kernel: [ 8364.104826] Call Trace:
Sep 6 21:33:28 kernel: [ 8364.104828] <TASK>
Sep 6 21:33:28 kernel: [ 8364.104830] ? __x64_sys_newuname_code_space+0x12/0x3d [hookFrameTest]
Sep 6 21:33:28 kernel: [ 8364.104836] hook___x64_sys_newuname+0x12/0x1b [hookFrameTest]
Sep 6 21:33:28 kernel: [ 8364.104839] do_syscall_64+0x59/0xc0
Sep 6 21:33:28 kernel: [ 8364.104843] ? handle_mm_fault+0xd8/0x2c0
Sep 6 21:33:28 kernel: [ 8364.104848] ? do_user_addr_fault+0x1e7/0x670
Sep 6 21:33:28 kernel: [ 8364.104852] ? exit_to_user_mode_prepare+0x37/0xb0
Sep 6 21:33:28 kernel: [ 8364.104856] ? irqentry_exit_to_user_mode+0x9/0x20
Sep 6 21:33:28 kernel: [ 8364.104860] ? irqentry_exit+0x1d/0x30
Sep 6 21:33:28 kernel: [ 8364.104863] ? exc_page_fault+0x89/0x170
Sep 6 21:33:28 kernel: [ 8364.104866] entry_SYSCALL_64_after_hwframe+0x61/0xcb
.
Hi ydaniels,
Thanks for reporting the issue. I will check it out later.
Aha, I see the problem here.
for __x64_sys_newuname:
ffffffff811091b0 <__x64_sys_newuname>:
ffffffff811091b0: e8 1b 1b fa ff callq ffffffff810aacd0 <__fentry__>
ffffffff811091b5: 55 push %rbp
ffffffff811091b6: 48 8b 7f 70 mov 0x70(%rdi),%rdi
ffffffff811091ba: 48 89 e5 mov %rsp,%rbp
ffffffff811091bd: e8 9e fe ff ff callq ffffffff81109060 <__do_sys_newuname>
ffffffff811091c2: 5d pop %rbp
ffffffff811091c3: 31 ff xor %edi,%edi
ffffffff811091c5: e9 b6 f6 fc 00 jmpq ffffffff820d8880 <__x86_return_thunk>
ffffffff811091ca: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
When hook the syscall, the start of the function, say a few instructions, will be copied to a different place, aka __x64_sys_newuname_code_space, and been executed there when resuming the original function. However the callq instruction, which contains a relative address referencing, after been copied to a different place, the relative addressing should be updated as well. The relative address updating for an instruction is not easy, there are many more cases need to be considered, so a simple solution is to forbid moving those instructions to a different place. See check_instruction_can_hijack()/check_target_can_hijack() in arm32 and arm64. However I didn't do the check in x86. I will update the code later.
In addition, could you try to hook a different function? Such as __do_sys_newuname, it will work with no problem and have the same hooking effects.
Nice hooking __do_sys_newuname works. Thanks for your time and the project