Как можно использовать функцию `kallsyms_lookup_name` для исправления ошибки` неизвестный символ` при загрузке модуля ядра Linux? - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь завершить пример подключения приложения в программе для моего задания в университете. Задача требует подключения системного вызова sys_rt_sigaction при запуске загружаемого модуля в ядре Linux (я использую Ubuntu 18.04 LTS, версия ядра 5.0.0-23-generi c). Итак, дело, с которым я борюсь, происходит из-за ошибки could not insert module <module name>: Unknown symbol in module, как только я начал sudo insmod <my module name>.ko. После некоторого поиска в Google я вижу, что эта проблема возникает из-за отсутствия экспорта sys_call_table для выполнения вставки так же гладко. После этого поста я хочу справиться с вызовом kallsyms_lookup_name перед тем, как запустить init процедуру.
Существует .c -файл, который предоставляет определения операций, доступных модулю (имя файла is 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 в папке моего проекта. Поскольку я следую учебным пособиям для начинающих и нуждаюсь в некотором базовом понимании, было бы весьма полезно увидеть какую-либо помощь в решении или даже некоторые идеи о том, как действительно решить ту же проблему более эффективно.

...