I am trying to hook a system call on linux kernel 4.15.0-74-generic on Ubuntu 16.04. When loading the kernel module it gives following message in dmesg:

[96963.055549] BUG: unable to handle kernel paging request at ffffffff81e00520

[96963.055556] IP: entry_point+0x14/0x50 [syshook]

[96963.055557] PGD 1bbe0e067 P4D 1bbe0e067 PUD 1bbe0f063 PMD 0 

[96963.055560] Oops: 0000 [#1] SMP PTI

[96963.055562] Modules linked in: syshook(OE+) xt_recent pci_stub vboxpci(OE) vboxnetadp(OE) vboxnetflt(OE) vboxdrv(OE) ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 xt_hl ip6t_rt nf_conntrack_ipv6 nf_defrag_ipv6 ipt_REJECT nf_reject_ipv4 xt_comment nf_log_ipv4 nf_log_common xt_LOG xt_multiport intel_rapl x86_pkg_temp_thermal xt_limit intel_powerclamp coretemp kvm_intel kvm irqbypass xt_tcpudp snd_hda_codec_realtek snd_hda_codec_generic xt_addrtype input_leds snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm crct10dif_pclmul crc32_pclmul snd_seq_midi snd_seq_midi_event ghash_clmulni_intel snd_rawmidi nf_conntrack_ipv4 nf_defrag_ipv4 pcbc xt_conntrack snd_seq aesni_intel snd_seq_device ip6table_filter aes_x86_64 ip6_tables snd_timer nf_conntrack_netbios_ns nf_conntrack_broadcast crypto_simd nf_nat_ftp
[96963.055583]  nf_nat glue_helper i2c_i801 snd shpchp nf_conntrack_ftp cryptd intel_cstate intel_rapl_perf wmi_bmof mei_me mei soundcore ie31200_edac nf_conntrack libcrc32c iptable_filter lpc_ich binfmt_misc ip_tables ppdev mac_hid parport_pc x_tables lp parport autofs4 hid_generic usbhid hid i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect ahci sysimgblt libahci fb_sys_fops drm r8169 mii wmi video

[96963.055611] CPU: 3 PID: 1621 Comm: insmod Tainted: G        W  OE    4.15.0-74-generic #83~16.04.1-Ubuntu

[96963.055612] Hardware name: LENOVO 3492H2Q/, BIOS F1KT52AUS 05/24/2013

[96963.055615] RIP: 0010:entry_point+0x14/0x50 [syshook]

[96963.055616] RSP: 0018:ffffa2cdc89c7c68 EFLAGS: 00010246

[96963.055617] RAX: 0000000000000000 RBX: ffffffffc07a8000 RCX: 0000000000000000

[96963.055618] RDX: 0000000000833a67 RSI: 0000000000000000 RDI: ffffffff81e00280

[96963.055619] RBP: ffffa2cdc89c7ce8 R08: ffff90251f3a6080 R09: ffff902516803980
[96963.055620] R10: ffffc668c14f8a00 R11: ffffffff97c5fc20 R12: ffffffffc07a60c0
[96963.055621] R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000001

[96963.055622] FS:  00007fd9d1159700(0000) GS:ffff90251f380000(0000) knlGS:0000000000000000

[96963.055623] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033

[96963.055624] CR2: ffffffff81e00520 CR3: 0000000204ff4001 CR4: 00000000001626e0

[96963.055625] Call Trace:

[96963.055631]  ? do_one_initcall+0x55/0x1ac

[96963.055633]  ? _cond_resched+0x1a/0x50

[96963.055636]  ? kmem_cache_alloc_trace+0xa6/0x1d0

[96963.055640]  do_init_module+0x5f/0x223

[96963.055642]  load_module+0x188c/0x1e90

[96963.055646]  ? ima_post_read_file+0x83/0xa0

[96963.055648]  SYSC_finit_module+0xe5/0x120

[96963.055650]  ? SYSC_finit_module+0xe5/0x120

[96963.055652]  SyS_finit_module+0xe/0x10

[96963.055654]  do_syscall_64+0x73/0x130

[96963.055656]  entry_SYSCALL_64_after_hwframe+0x3d/0xa2

[96963.055658] RIP: 0033:0x7fd9d0c8c4d9

[96963.055658] RSP: 002b:00007ffdddf2e158 EFLAGS: 00000202 ORIG_RAX: 0000000000000139

[96963.055660] RAX: ffffffffffffffda RBX: 00005557c908b250 RCX: 00007fd9d0c8c4d9

[96963.055661] RDX: 0000000000000000 RSI: 00005557c87e526b RDI: 0000000000000003

[96963.055661] RBP: 00005557c87e526b R08: 0000000000000000 R09: 00007fd9d0f51ea0

[96963.055662] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000

[96963.055663] R13: 00005557c908b210 R14: 0000000000000000 R15: 0000000000000000

[96963.055664] Code: c0 c9 c3 e8 df b0 ee d5 0f 1f 44 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 c7 c7 80 02 e0 81 55 48 89 3d 74 22 00 00 <48> 8b 04 25 20 05 e0 81 48 89 e5 48 89 05 5a 22 00 00 e8 35 ff

[96963.055684] RIP: entry_point+0x14/0x50 [syshook] RSP: ffffa2cdc89c7c68

[96963.055685] CR2: ffffffff81e00520

[96963.055687] ---[ end trace fa6b1eb8d1543662 ]---

What am I doing wrong? How can I debug the kernel module?

Source code is:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/semaphore.h>
#include <linux/dirent.h>
#include <asm/cacheflush.h>
void **sys_call_table;
asmlinkage int (*original_rmdir)(const char __user * pathname);

asmlinkage int sys_rmdir(const char __user * pathname) 
    printk("Do whatever you want\n");
    return 0; 

int set_page_rw(unsigned long addr)
  unsigned int level;
  pte_t *pte = lookup_address(addr, &level);
  if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
  return 0;

int set_page_ro(unsigned long addr)
  unsigned int level;
  pte_t *pte = lookup_address(addr, &level);
  pte->pte = pte->pte &~_PAGE_RW;
  return 0;

static int entry_point(void) 
    sys_call_table = (void*)0xffffffff81e00280;
    original_rmdir = sys_call_table[__NR_rmdir];
    sys_call_table[__NR_rmdir] = sys_rmdir;
    return 0;

static void exit_point(void)
    sys_call_table[__NR_rmdir] = original_rmdir;
        return 0;

  • Please format your code properly. – schaiba Jan 22 '20 at 10:13
  • edited the code properly. Let me know what i am doing wrong in above code. – skp Jan 22 '20 at 10:20

Given the message you get:

[96963.055549] BUG: unable to handle kernel paging request at ffffffff81e00520

I would dig around your set_page_ro() and set_page_rw() functions.

Especially because the message give you the address you put for the syscall table (ffffffff81e00520).

Why did you hardcoded it with such value ? I would bet that the kernel export a macro or an extern void * or something like that to get the correct value ...

EDITED: So the address, if retrieved using the System.map of the running kernel, may be good. But, if you look to this code the process to switch a page RW/RO looks different than what you did ...

When you do:

if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;

The example code on github do:

set_pte_atomic(pte, pte_clear_flags(*pte, _PAGE_RW));
  • I have not added the hard coded value. Just i Have taken sys_call_table value from /boot/System.map file for hooking the system call rmdir. – skp Jan 22 '20 at 10:24
  • Since the value is written as-is in your code, it is hardcoded I strongly suggest you to find a way to get it from the kernel directly at the runtime. – binarym Jan 22 '20 at 10:26
  • Can you suggest any way two get the value. Because I am new to this kernel modules. and also give me any suggestion for to debugging this. – skp Jan 22 '20 at 10:29
  • Please, complete your question with the process that lead you to use this address cause i can't see any reference to the syscall_table on my System.map ... If the adress you used is the function's one, obviously it won't work. You have to replace the entry in the syscall table, not the code of the original syscall. – binarym Jan 22 '20 at 10:31
  • Ok, got it... in fact the symbol is /boot/System.map-4.19.0-6-amd64:ffffffff81c001e0 R sys_call_table so maybe the address you used is correct (even if not very smartly imported ;-p). I edited my answer with a link to an example since the process of switching a page R/W looks a bit more complicated ... – binarym Jan 22 '20 at 10:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.