WeiJiLab / kernel-hook-framework

A generic linux kernel inline hook framework for arm32, arm64, x86, x86_64 and powerpc

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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