Ubuntu 16.04のLinuxカーネル4.15.0-74-genericでシステムコールを接続しようとしています。カーネルモジュールをロードすると、次のメッセージが表示されます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 ]---
私は何が間違っていましたか?カーネルモジュールをデバッグする方法は?
ソースコードは次のとおりです
#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];
set_page_rw(sys_call_table);
sys_call_table[__NR_rmdir] = sys_rmdir;
return 0;
}
static void exit_point(void)
{
sys_call_table[__NR_rmdir] = original_rmdir;
set_page_ro(sys_call_table);
return 0;
}
module_init(entry_point);
module_exit(exit_point);
ベストアンサー1
あなたが受け取ったメッセージによると:
[96963.055549] BUG: unable to handle kernel paging request at ffffffff81e00520
私はあなたset_page_ro()
のset_page_rw()
機能を掘り下げます。
特に、メッセージはシステムコールテーブルに入力されたアドレス(ffffffff81e00520)を提供するためです。
なぜこのような値でハードコードするのですか?カーネルがextern void *
正しい値を得るためにマクロやそれに似たものをエクスポートすると確信しています...
編集する:したがって、実行中のカーネルのSystem.mapを使用してそのアドレスを検索することをお勧めします。しかし、あなたが見るとこのコードページRW / ROを切り替えるプロセスは、現在実行中の操作とは異なるようです。
これを行うとき:
if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
githubのサンプルコードは次のとおりです。
set_pte_atomic(pte, pte_clear_flags(*pte, _PAGE_RW));