首页 > 解决方案 > 加载 Linux 内核模块时,如何使用 `kallsyms_lookup_name` 函数修复`unknown character` 错误?

问题描述

我正在尝试在我的 uni 作业程序中完成一个挂钩示例附件。该任务需要sys_rt_sigaction在 Linux 内核中启动可加载模块时挂钩系统调用(我使用 Ubuntu 18.04 LTS,内核版本为 5.0.0-23-generic)。因此,我正在苦苦挣扎的情况源于could not insert module <module name>: Unknown symbol in module我开始时的错误sudo insmod <my module name>.ko。经过一番谷歌搜索,我清楚地看到这个问题是由于缺少sys_call_table导出以顺利运行插入而出现的。在这篇文章之后,我想kallsyms_lookup_name在开始程序之前处理那个调用调用init
.c-file 提供模块可访问的操作定义(文件名为buffer.c):

#define __KERNEL__
#define MODULE

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kallsyms.h>
#include <linux/unistd.h>

void * sys_call_table = (void *) kallsyms_lookup_name("sys_call_table");// some wrongness here, but what exactly? 

MODULE_LICENSE("GPL");

int (*real_rt_sigaction)(const char * path); // true syscall prototype 
static int __init buffer_init_module(void);
static void __exit buffer_exit_module(void);
static int device_open(struct inode *, struct file *); // driver file opening
static int device_release(struct inode *, struct file *); // return of system resource control
static ssize_t device_read(struct file *, char *, size_t, loff_t *); // reading from driver file
static ssize_t device_write(struct file *, const char *, size_t, loff_t *); // writing into driver file

#define DEVICE_NAME "buffer"
#define BUF_LEN 80

// to be called instead  
int alter_rt_sigaction(int signum, const struct sigaction *act,
                       struct sigaction *oldact, size_t sigsetsize) {
    printk(KERN_INFO "Syscall function hooked - you've lost control of your experience");
    return 0;
}


static int Major;
static int Device_Open = 0;
static int total_open = 1;

static char Buf[BUF_LEN + 1] = "Buffer is empty, add some input\n";
static char *Msg_ptr;
static int Buf_Char = 50;
static int Bytes_Read = 0;

static struct file_operations fops = {
        .read = device_read,
        .write = device_write,
        .open = device_open,
        .release = device_release
};

static int __init buffer_init_module(void)
{
    printk(KERN_INFO
    "Device initializing in progress...");
    Major = register_chrdev(0, DEVICE_NAME, &fops);
    if(Major < 0) {
        printk("Major number hasn't been assigned - Driver registration failed\n");
        return Major;
    }
    printk(KERN_INFO "Registration success - device major number: %d\n", Major);
    real_rt_sigaction=sys_call_table[__NR_rt_sigaction]; 
    sys_call_table[__NR_rt_sigaction]=alter_rt_sigaction; // hooking implementation 
    return 0;
}

static void __exit buffer_exit_module(void)
{
    unregister_chrdev(Major, DEVICE_NAME);
    printk(KERN_INFO "Outside the module - exit successfully completed\n");
    sys_call_table[__NR_rt_sigaction]=real_rt_sigaction; // original call reset
}

static int device_open(struct inode *inode, struct file *file)
{
    if(Device_Open)
        return -EBUSY;
    Device_Open++;
    printk(KERN_INFO "Device file has been accessed %d time(s)\n", total_open++);
    Msg_ptr = Buf;
    try_module_get(THIS_MODULE);
    Bytes_Read = 0;

    return 0;
}

static int device_release(struct inode * node, struct file * filep)
{
    Device_Open--;
    module_put(THIS_MODULE);
    printk(KERN_INFO "Device file gets close\n");
    return 0;
}

static ssize_t device_read(struct file * filep, char * buffer, size_t len, loff_t * offset)
{
    int got_read = Bytes_Read;

    if(Bytes_Read >= Buf_Char)
        return 0;

    while(len && (Bytes_Read < Buf_Char)) {
        put_user(Msg_ptr[Bytes_Read], buffer+Bytes_Read);
        len--;
        Bytes_Read++;
    }
    return Bytes_Read-got_read;
}

static ssize_t device_write(struct file * filep, const char * buffer, size_t len, loff_t * offset)
{
    Buf_Char = 0;
    if(Buf_Char >= BUF_LEN) {
        return 0;
    }

    while(len && (Buf_Char < BUF_LEN))
    {
        get_user(Msg_ptr[Buf_Char], buffer+Buf_Char);
        len--;
        Buf_Char++;
    }

    return Buf_Char;
}

module_init(buffer_init_module);
module_exit(buffer_exit_module);

此外,还有代码Makefile

obj-m += buffer.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

initializer element is not constant每当我试图sudo make在我的项目文件夹中构建模块时,这里的痛苦时刻是一条错误消息。当我遵循初学者的教程并需要一些基本的洞察力时,很可能会看到任何有关解决方案的帮助,甚至是一些如何更有效地处理相同问题的想法。

标签: hooksystem-callskernel-module

解决方案


推荐阅读