内核错误:无法处理 ffffffff81e00520 处的内核分页请求

内核错误:无法处理 ffffffff81e00520 处的内核分页请求

我正在尝试替换 Ubuntu 16.04 64 位中内核版本 4.15.0-74-generic 中的系统调用 __NR_rmdir,但它给出以下错误。以下代码在 Ubuntu 10.10 64 位中的 Linux 内核版本 2.6.35-22-generic 上运行良好,我在错误后添加了源代码:

[  133.631561] syscall_replace: sys_call_table address is 0x0000000030c42fec
[  133.631577] BUG: unable to handle kernel paging request at ffffffff81e00520
[  133.631582] IP: syscall_replace_init+0x1c/0x60 [syscall_replace]
[  133.631583] PGD 17700e067 P4D 17700e067 PUD 17700f063 PMD 0 
[  133.631587] Oops: 0000 [#1] SMP PTI
[  133.631588] Modules linked in: syscall_replace(OE+) pci_stub vboxpci(OE) vboxnetadp(OE) vboxnetflt(OE) vboxdrv(OE) input_leds ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 xt_hl ip6t_rt snd_hda_codec_realtek snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc snd_seq_midi snd_seq_midi_event nf_conntrack_ipv6 nf_defrag_ipv6 snd_rawmidi ipt_REJECT nf_reject_ipv4 aesni_intel aes_x86_64 xt_comment crypto_simd glue_helper cryptd intel_cstate nf_log_ipv4 binfmt_misc intel_rapl_perf snd_seq nf_log_common xt_LOG snd_seq_device i2c_i801 snd_timer xt_multiport wmi_bmof snd xt_limit xt_tcpudp xt_addrtype mei_me lpc_ich shpchp soundcore mei ie31200_edac
[  133.631610]  mac_hid nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack ip6table_filter ip6_tables nf_conntrack_netbios_ns nf_conntrack_broadcast nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack libcrc32c iptable_filter ip_tables x_tables parport_pc ppdev lp parport autofs4 hid_generic usbhid hid i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops r8169 mii drm ahci libahci wmi video
[  133.631638] CPU: 3 PID: 2558 Comm: insmod Tainted: G        W  OE    4.15.0-74-generic #83~16.04.1-Ubuntu
[  133.631639] Hardware name: LENOVO 3492H2Q/, BIOS F1KT52AUS 05/24/2013
[  133.631641] RIP: 0010:syscall_replace_init+0x1c/0x60 [syscall_replace]
[  133.631642] RSP: 0018:ffffbbb7c275fc68 EFLAGS: 00010286
[  133.631643] RAX: 000000000000003d RBX: ffffffffc07e3040 RCX: 0000000000000000
[  133.631644] RDX: 0000000000000000 RSI: ffff9f3d1f396498 RDI: ffff9f3d1f396498
[  133.631645] RBP: ffffbbb7c275fc68 R08: 0000000000010830 R09: ffffffff90b5c4c4
[  133.631646] R10: ffffbbb7c275fcb8 R11: 000000000000033c R12: ffffffffc07e10b0
[  133.631647] R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000001
[  133.631648] FS:  00007f6c1cfa2700(0000) GS:ffff9f3d1f380000(0000) knlGS:0000000000000000
[  133.631649] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  133.631650] CR2: ffffffff81e00520 CR3: 00000001d65ea006 CR4: 00000000001606e0
[  133.631651] Call Trace:
[  133.631657]  do_one_initcall+0x55/0x1ac
[  133.631662]  ? __vunmap+0x8e/0xc0
[  133.631664]  ? _cond_resched+0x1a/0x50
[  133.631667]  ? kmem_cache_alloc_trace+0xa6/0x1d0
[  133.631670]  do_init_module+0x5f/0x223
[  133.631672]  load_module+0x188c/0x1e90
[  133.631676]  ? ima_post_read_file+0x83/0xa0
[  133.631678]  SYSC_finit_module+0xe5/0x120
[  133.631680]  ? SYSC_finit_module+0xe5/0x120
[  133.631682]  SyS_finit_module+0xe/0x10
[  133.631684]  do_syscall_64+0x73/0x130
[  133.631687]  entry_SYSCALL_64_after_hwframe+0x3d/0xa2
[  133.631688] RIP: 0033:0x7f6c1cad54d9
[  133.631689] RSP: 002b:00007ffe2b150f08 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[  133.631691] RAX: ffffffffffffffda RBX: 000055c5da68b270 RCX: 00007f6c1cad54d9
[  133.631691] RDX: 0000000000000000 RSI: 000055c5d9f4e26b RDI: 0000000000000003
[  133.631692] RBP: 000055c5d9f4e26b R08: 0000000000000000 R09: 00007f6c1cd9aea0
[  133.631693] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[  133.631694] R13: 000055c5da68b210 R14: 0000000000000000 R15: 0000000000000000
[  133.631695] Code: ab ce 0f 1f 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 c7 c6 80 02 e0 81 48 c7 c7 60 20 7e c0 48 89 e5 e8 14 30 b1 ce <48> 8b 34 25 20 05 e0 81 48 c7 c7 98 20 7e c0 48 89 35 9e 22 00 
[  133.631715] RIP: syscall_replace_init+0x1c/0x60 [syscall_replace] RSP: ffffbbb7c275fc68
[  133.631716] CR2: ffffffff81e00520
[  133.631717] ---[ end trace fadfaa1785a9e6d9 ]---

源代码 :

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <asm/cacheflush.h>
#include <linux/syscalls.h>
#include <linux/mm.h>
#include <linux/utsname.h>
#include <asm/pgtable.h>

MODULE_DESCRIPTION("system call replace test module");
MODULE_AUTHOR("knqyf263");
MODULE_LICENSE("GPL");


static void **syscall_table = (void *)0xffffffff81e00280;
typedef void (*sys_call_ptr_t)(void);


typedef asmlinkage int (*original_rmdir)(const char __user * pathname);



original_rmdir orig_rmdir = NULL;



asmlinkage long hooked_rmdir(const char __user * pathname) {

    pr_info("Cannot delete files and folder");
    return 0;
}

static void save_original_syscall_address(void){
    orig_rmdir = (original_rmdir) syscall_table[__NR_rmdir];
}

static void change_page_attr_to_rw(pte_t *pte){
    set_pte_atomic(pte, pte_mkwrite(*pte));
}

static void change_page_attr_to_ro(pte_t *pte){
    set_pte_atomic(pte, pte_clear_flags(*pte, _PAGE_RW));
}

static void replace_system_call(void *new){
    unsigned int level = 0;
    pte_t *pte;

    pte = lookup_address((unsigned long) syscall_table, &level);


    syscall_table[__NR_rmdir] = new;


    change_page_attr_to_ro(pte);
}

static int syscall_replace_init(void){
    pr_info("sys_call_table address is 0x%p\n", syscall_table);

    save_original_syscall_address();
    pr_info("original sys_uname's address is %p\n", orig_rmdir);

    replace_system_call(hooked_rmdir);

    pr_info("system call replaced\n");
    return 0;
}

static void syscall_replace_cleanup(void){
    pr_info("cleanup");
    if (orig_rmdir)
        replace_system_call(orig_rmdir);
}

module_init(syscall_replace_init);
module_exit(syscall_replace_cleanup);

答案1

由于第二行,您的错误似乎与系统调用表的地址有关

BUG: unable to handle kernel paging request at ffffffff81e00520

原因可能是卡斯劳尔它在 3.14 版本的 Linux 主线中引入。

卡斯劳尔代表内核地址空间布局随机化,这意味着每次启动系统时内核的地址都会被随机化,包括系统调用表地址,因此要获得它的正确地址,您应该使用其中一种技术来获取它,例如在内存中搜索或使用 kallsysms_lookup_name。有关更详细的技术,您可以阅读这里

相关内容