无法在ARM的Linux内核4.19中进行syscall挂钩/写入受保护的内存页面syscall_table

问题描述

我正在尝试开发一个挂钩系统调用的内核模块。我正在运行RaspBerry Buster Linux 4.19.97-v7 + armv7l的RaspBerry Pi 3B上进行测试。

因此,通常在x86上,我们可以覆盖CR0寄存器,但是在ARM体系结构上没有类似的寄存器。我尝试通过set_memory_rw进行操作,然后启用它,然后退出使用set_memory_ro,就像在Cannot use set_memory_rw in Linux kernel on ARM64上对类似问题的一个答案 但这不起作用。

我的代码

            up   down left right up  down left right     
[0,0]      NaN  NaN  NaN   NaN  Nan  NaN  NaN  NaN
[0,40]     NaN  NaN  NaN   NaN  NaN  NaN  NaN  NaN
[0,80]     NaN  NaN  NaN   NaN  NaN  NaN  NaN  NaN
[0,120]    NaN  NaN  NaN   NaN  NaN  NaN  NaN  NaN
[0,160]    NaN  NaN  NaN   NaN  NaN  NaN  NaN  NaN
.......

Dmesg跟踪错误如下

// SPDX-License-Identifier: GPL-3.0
#include <linux/init.h>     // module_{init,exit}()
#include <linux/module.h>   // THIS_MODULE,MODULE_VERSION,...
#include <linux/kernel.h>   // printk(),pr_*()
#include <linux/kallsyms.h> // kallsyms_lookup_name()
#include <asm/syscall.h>    // syscall_fn_t,__NR_*
#include <asm/ptrace.h>     // struct pt_regs
#include <asm/tlbflush.h>   // flush_tlb_kernel_range()
#include <asm/pgtable.h>    // {clear,set}_pte_bit(),set_pte()
#include <linux/vmalloc.h>  // vm_unmap_aliases()
#include <linux/mm.h>       // struct mm_struct,apply_to_page_range()
#include <linux/kconfig.h>  // IS_ENABLED()

#ifdef pr_fmt
#undef pr_fmt
#endif
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

static struct mm_struct *init_mm_ptr;
static void* *syscall_table;

#define MAGIC "mamaliga"
#define SIZEOF_MAGIC 8
#define ROOTKIT_SYS_CALL_TABLE 0x801011c4
int pos; 

// static void* original_read;
asmlinkage long (*original_read)(unsigned int fd,char __user *buf,size_t count);
/********** HELPERS **********/

// From arch/arm/mm/pageattr.c.
struct page_change_data {
    pgprot_t set_mask;
    pgprot_t clear_mask;
};

static int change_page_range(pte_t *ptep,pgtable_t token,unsigned long addr,void *data)
{
    struct page_change_data *cdata = data;
    pte_t pte = *ptep;

    pte = clear_pte_bit(pte,cdata->clear_mask);
    pte = set_pte_bit(pte,cdata->set_mask);

    set_pte_ext(ptep,pte,0);
    return 0;
}

void (*flush)(unsigned long start,unsigned long end);
// From arch/arm64/mm/pageattr.c.
static int __change_memory_common(unsigned long start,unsigned long size,pgprot_t set_mask,pgprot_t clear_mask)
{
    struct page_change_data data;
    int ret;

    data.set_mask = set_mask;
    data.clear_mask = clear_mask;

    ret = apply_to_page_range(init_mm_ptr,start,size,change_page_range,&data);
    flush = (void*)kallsyms_lookup_name("flush_tlb_kernel_range");
    flush(start,start + size);
    return ret;
}

// Simplified set_memory_rw() from arch/arm/mm/pageattr.c.
static int set_page_rw(unsigned long addr)
{
    vm_unmap_aliases();    
    return __change_memory_common(addr,PAGE_SIZE,__pgprot(0),__pgprot(L_PTE_RDONLY));
}

// Simplified set_memory_ro() from arch/arm/mm/pageattr.c.
static int set_page_ro(unsigned long addr)
{
    vm_unmap_aliases();
    return __change_memory_common(addr,__pgprot(L_PTE_RDONLY),__pgprot(0));
}

/********** ACTUAL MODULE **********/

asmlinkage long myread(unsigned int fd,size_t count)
{
    long ret;

    /* Call original read_syscall */
    ret = original_read(fd,buf,count);

    pr_info("Hooked!\n");

    return ret;
}

static int __init modinit(void)
{
    int res;

    pr_info("init\n");

    // Shouldn't fail.
    init_mm_ptr = (struct mm_struct *)kallsyms_lookup_name("init_mm");
    syscall_table = (void* *)kallsyms_lookup_name("sys_call_table");
    
    printk(KERN_INFO "syscall_table: 0xx%llx\n",syscall_table);
    
    original_read = syscall_table[__NR_read];

    res = set_page_rw(((unsigned long)syscall_table + __NR_read) & PAGE_MASK);
    if (res != 0) {
        pr_err("set_page_rw() Failed: %d\n",res);
        return res;
    }
    else {
        pr_info("set_page_rw() OK");
    }

    syscall_table[__NR_read] = myread;

    res = set_page_ro(((unsigned long)syscall_table + __NR_read) & PAGE_MASK);
    if (res != 0) {
        pr_err("set_page_ro() Failed: %d\n",res);
        return res;
    }
    else {
        pr_info("set_page_ro() OK");
    }

    pr_info("init done\n");

    return 0;
}

static void __exit modexit(void)
{
    int res;

    pr_info("exit\n");

    res = set_page_rw(((unsigned long)syscall_table + __NR_read) & PAGE_MASK);
    if (res != 0) {
        pr_err("set_page_rw() Failed: %d\n",res);
        return;
    }

    syscall_table[__NR_read] = original_read;

    res = set_page_ro(((unsigned long)syscall_table + __NR_read) & PAGE_MASK);
    if (res != 0)
        pr_err("set_page_ro() Failed: %d\n",res);

    pr_info("goodbye\n");
}

module_init(modinit);
module_exit(modexit);
MODULE_VERSION("0.1");
MODULE_DESCRIPTION("Syscall hijack on arm64.");
MODULE_AUTHOR("marco Bonelli");
MODULE_LICENSE("GPL");

我还尝试了ARM64 - Linux Memory Write protection won't disable的其他一些建议,这些建议通过使用Linux内核功能通过相应的PTE禁用了对虚拟地址的内存写保护。它也不起作用。

[   89.767769] interceptor: loading out-of-tree module taints kernel.
[   89.771442] interceptor: init
[   89.806435] syscall_table: 0xx75c5dda175c5dda1
[   89.812886] interceptor: set_page_rw() OK
[   89.812898] Unable to handle kernel paging request at virtual address 801011d0
[   89.822616] pgd = c9de9ec3
[   89.826529] [801011d0] *pgd=0001141e(bad)
[   89.831760] Internal error: Oops: 80d [#1] SMP ARM
[   89.837763] Modules linked in: interceptor(O+) cmac bnep hci_uart btbcm serdev bluetooth ecdh_generic binfmt_misc evdev brcmfmac brcmutil sha256_generic cfg80211 raspBerrypi_hwmon rfkill hwmon bcm2835_codec(C) bcm2835_v4l2(C) snd_bcm2835(C) v4l2_mem2mem snd_pcm bcm2835_mmal_vchiq(C) v4l2_common videobuf2_dma_contig snd_timer videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_common snd videodev media vc_sm_cma(C) fixed uio_pdrv_genirq uio ip_tables x_tables ipv6
[   89.887532] cpu: 1 PID: 981 Comm: insmod Tainted: G         C O      4.19.97-v7+ #1293
[   89.898046] Hardware name: BCM2835
[   89.902693] PC is at modinit+0xb0/0x1000 [interceptor]
[   89.909084] LR is at   (null)
[   89.913214] pc : [<7f7430b0>]    lr : [<00000000>]    psr: 60000013
[   89.920704] sp : b20e5d80  ip : 80d0517c  fp : b20e5d9c
[   89.927176] r10: b5ab3340  r9 : 00000002  r8 : b5ab3300
[   89.933650] r7 : 00000000  r6 : fffff000  r5 : 00000000  r4 : 801011c4
[   89.941469] r3 : 7f73e068  r2 : 75c5dda1  r1 : 00000000  r0 : 0000001d
[   89.949256] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
[   89.957653] Control: 10c5383d  Table: 320ec06a  DAC: 00000055
[   89.964666] Process insmod (pid: 981,stack limit = 0x322dc319)
[   89.971873] Stack: (0xb20e5d80 to 0xb20e6000)
[   89.977495] 5d80: 7f740000 7f743000 80d04d48 00000000 b20e5e14 b20e5da0 8010312c 7f74300c
[   89.988192] 5da0: 802821d4 8085dffc 00000000 006000c0 b20e5dcc b20e5dc0 8085dffc 802ba274
[   89.998889] 5dc0: b20e5e14 b20e5dd0 802ba274 802c7118 802bb6cc 802bab54 00000001 00003c76
[   90.009578] 5de0: 00000000 a0000013 bccc8000 75c5dda1 7f740000 7f740000 7f740000 b7c04880
[   90.020281] 5e00: 80d04d48 b5ab3300 b20e5e3c b20e5e18 801ba19c 801030e8 b20e5e3c b20e5e28
[   90.031099] 5e20: 802a8250 b20e5f30 7f740000 00000002 b20e5f0c b20e5e40 801b9114 801ba134
[   90.042029] 5e40: 7f74000c 00007fff 7f740000 801b6100 00000000 80ae4f00 7f7401fc 7f740114
[   90.053063] 5e60: 7f740130 00000000 b5ab3308 7f740048 b20e5e94 80afd2d0 802d061c 802d0488
[   90.064243] 5e80: b20e5ea0 b21029c0 00000000 00000000 00000000 00000000 00000000 00000000
[   90.075471] 5ea0: 6e72656b 00006c65 00000000 00000000 00000000 00000000 00000000 00000000
[   90.086778] 5ec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 75c5dda1
[   90.098119] 5ee0: 7fffffff 80d04d48 00000000 00000003 0002d064 7fffffff 00000000 0000017b
[   90.109451] 5f00: b20e5fa4 b20e5f10 801b9974 801b7360 7fffffff 00000000 00000003 00000000
[   90.120790] 5f20: 00000000 bccc8000 0000209c 00000000 bccc84e2 bccc89c0 bccc8000 0000209c
[   90.132121] 5f40: bccc9a5c bccc98a8 bccc92a0 00003000 000032c0 00000000 00000000 00000000
[   90.143457] 5f60: 000018d8 00000025 00000026 0000001d 0000001b 00000017 00000000 75c5dda1
[   90.154784] 5f80: 010d6c00 7e9317d4 0003fce8 0000017b 801011c4 b20e4000 00000000 b20e5fa8
[   90.166119] 5fa0: 80101000 801b98c4 010d6c00 7e9317d4 00000003 0002d064 00000000 00000004
[   90.177457] 5fc0: 010d6c00 7e9317d4 0003fce8 0000017b 01355818 00000000 00000002 00000000
[   90.188783] 5fe0: 7e931608 7e9315f8 00022cb8 76cadaf0 60000010 00000003 00000000 00000000
[   90.200155] [<7f7430b0>] (modinit [interceptor]) from [<8010312c>] (do_one_initcall+0x50/0x218)
[   90.212033] [<8010312c>] (do_one_initcall) from [<801ba19c>] (do_init_module+0x74/0x220)
[   90.223280] [<801ba19c>] (do_init_module) from [<801b9114>] (load_module+0x1dc0/0x2404)
[   90.234455] [<801b9114>] (load_module) from [<801b9974>] (sys_finit_module+0xbc/0xcc)
[   90.245459] [<801b9974>] (sys_finit_module) from [<80101000>] (ret_fast_syscall+0x0/0x28)
[   90.256813] Exception stack(0xb20e5fa8 to 0xb20e5ff0)
[   90.263464] 5fa0:                   010d6c00 7e9317d4 00000003 0002d064 00000000 00000004
[   90.274748] 5fc0: 010d6c00 7e9317d4 0003fce8 0000017b 01355818 00000000 00000002 00000000
[   90.286023] 5fe0: 7e931608 7e9315f8 00022cb8 76cadaf0
[   90.292627] Code: eb28f040 e594400c e30e3068 e3473f73 (e584300c)
[   90.300277] ---[ end trace 9daed852fe9a568f ]---

此刻我真的很卡住,您的建议将不胜感激!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)