我正在尝试替换 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。有关更详细的技术,您可以阅读这里