gpt4 book ai didi

c - insmod : Unknown symbol in module issue

转载 作者:太空宇宙 更新时间:2023-11-04 08:05:22 32 4
gpt4 key购买 nike

我正在编写一个 LKM 来查看文件的扩展属性以确定是否应该打开它。我有一个 insmode: Unknown symbol in module 问题。我找不到造成这种情况的原因。以下模块:

#include <linux/module.h>  /* Needed by all kernel modules */
#include <linux/kernel.h> /* Needed for loglevels (KERN_WARNING, KERN_EMERG, KERN_INFO, etc.) */
#include <linux/init.h> /* Needed for __init and __exit macros. */
#include <linux/unistd.h> /* sys_call_table __NR_* system call function indices */
#include <linux/fs.h> /* filp_open */
#include <linux/slab.h> /* kmalloc */
#include <asm/paravirt.h> /* write_cr0 */
#include <asm/uaccess.h> /* get_fs, set_fs */
#include <linux/xattr.h>
#include <linux/dcache.h> /*dentry*/


#define PROC_V "/proc/version"
#define BOOT_PATH "/boot/System.map-"
#define MAX_VERSION_LEN 256


//https://tnichols.org/2015/10/19/Hooking-the-Linux-System-Call-Table/



unsigned long *syscall_table = NULL;
//unsigned long *syscall_table = (unsigned long *)0xffffffff81801400;
asmlinkage int (*original_open)(const char*, int flags, mode_t);
static int find_sys_call_table (char *kern_ver) {
char system_map_entry[MAX_VERSION_LEN];
int i = 0;
/*
* Holds the /boot/System.map-<version> file name as we build it
*/
char *filename;
/*
* Length of the System.map filename, terminating NULL included
*/
size_t filename_length = strlen(kern_ver) + strlen(BOOT_PATH) + 1;
/*
* This will point to our /boot/System.map-<version> file
*/
struct file *f = NULL;

mm_segment_t oldfs;

oldfs = get_fs();
set_fs (KERNEL_DS);
printk(KERN_EMERG "Kernel version: %s\n", kern_ver);

filename = kmalloc(filename_length, GFP_KERNEL);
if (filename == NULL) {
printk(KERN_EMERG "kmalloc failed on System.map-<version> filename allocation");
return -1;
}

/*
* Zero out memory to be safe
*/
memset(filename, 0, filename_length);

/*
* Construct our /boot/System.map-<version> file name
*/
strncpy(filename, BOOT_PATH, strlen(BOOT_PATH));
strncat(filename, kern_ver, strlen(kern_ver));

/*
* Open the System.map file for reading
*/
f = filp_open(filename, O_RDONLY, 0);
if (IS_ERR(f) || (f == NULL)) {
printk(KERN_EMERG "Error opening System.map-<version> file: %s\n", filename);
return -1;
}

memset(system_map_entry, 0, MAX_VERSION_LEN);

/*
* Read one byte at a time from the file until we either max out
* out our buffer or read an entire line.
*/
while (vfs_read(f, system_map_entry + i, 1, &f->f_pos) == 1) {
/*
* If we've read an entire line or maxed out our buffer,
* check to see if we've just read the sys_call_table entry.
*/
if ( system_map_entry[i] == '\n' || i == MAX_VERSION_LEN ) {
// Reset the "column"/"character" counter for the row
i = 0;

if (strstr(system_map_entry, "sys_call_table") != NULL) {
char *sys_string;
char *system_map_entry_ptr = system_map_entry;

sys_string = kmalloc(MAX_VERSION_LEN, GFP_KERNEL);
if (sys_string == NULL) {
filp_close(f, 0);
set_fs(oldfs);
kfree(filename);

return -1;
}

memset(sys_string, 0, MAX_VERSION_LEN);
strncpy(sys_string, strsep(&system_map_entry_ptr, " "), MAX_VERSION_LEN);

//syscall_table = (unsigned long long *) kstrtoll(sys_string, NULL, 16);
//syscall_table = kmalloc(sizeof(unsigned long *), GFP_KERNEL);
//syscall_table = kmalloc(sizeof(syscall_table), GFP_KERNEL);
kstrtoul(sys_string, 16, &syscall_table);
printk(KERN_EMERG "syscall_table retrieved\n");

kfree(sys_string);

break;
}

memset(system_map_entry, 0, MAX_VERSION_LEN);
continue;
}

i++;
}

filp_close(f, 0);
set_fs(oldfs);

kfree(filename);

return 0;
}
/*
* We have to pass in a pointer to a buffer to store the parsed
* version information in. If we declare a pointer to the
* parsed version info on the stack of this function, the
* pointer will disappear when the function ends and the
* stack frame is removed.
*/
char *acquire_kernel_version (char *buf) {
struct file *proc_version;
char *kernel_version;

/*
* We use this to store the userspace perspective of the filesystem
* so we can switch back to it after we are done reading the file
* into kernel memory
*/
mm_segment_t oldfs;

/*
* Standard trick for reading a file into kernel space
* This is very bad practice. We're only doing it here because
* we're malicious and don't give a damn about best practices.
*/
oldfs = get_fs();
set_fs (KERNEL_DS);

/*
* Open the version file in the /proc virtual filesystem
*/
proc_version = filp_open(PROC_V, O_RDONLY, 0);
if (IS_ERR(proc_version) || (proc_version == NULL)) {
return NULL;
}

/*
* Zero out memory just to be safe
*/
memset(buf, 0, MAX_VERSION_LEN);

/*
* Read version info from /proc virtual filesystem
*/
vfs_read(proc_version, buf, MAX_VERSION_LEN, &(proc_version->f_pos));

/*
* Extract the third field from the full version string
*/
kernel_version = strsep(&buf, " ");
kernel_version = strsep(&buf, " ");
kernel_version = strsep(&buf, " ");

filp_close(proc_version, 0);

/*
* Switch filesystem context back to user space mode
*/
set_fs(oldfs);

return kernel_version;
}
asmlinkage int new_open (const char* path, int flags, mode_t mode) {
//printk(KERN_EMERG "[+] open() hooked.");

char *start = "root/home/";

if(strncmp(start,path,sizeof(char)*10)){

mm_segment_t oldfs;
struct file *f;
int val;
struct dentry *dentry;

oldfs = get_fs();
set_fs (KERNEL_DS);
f = filp_open(path, O_RDONLY, 0);
if(f){
dentry = f->f_path.dentry;
filp_close(f, 0);
val = vfs_getxattr(dentry, "user.lock", NULL, 0);
//printk(KERN_EMERG "%d %s\n", val, path);
if(val != 0) return -1;
}

set_fs(oldfs);
}
return original_open(path, flags, mode);
}


static int __init onload(void) {
char *kernel_version = kmalloc(MAX_VERSION_LEN, GFP_KERNEL);
printk(KERN_WARNING "Hello world!\n");
// printk(KERN_EMERG "Version: %s\n", acquire_kernel_version(kernel_version));

find_sys_call_table(acquire_kernel_version(kernel_version));

printk(KERN_EMERG "Syscall table address: %p\n", syscall_table);
printk(KERN_EMERG "sizeof(unsigned long *): %zx\n", sizeof(unsigned long*));
printk(KERN_EMERG "sizeof(sys_call_table) : %zx\n", sizeof(syscall_table));

if (syscall_table != NULL) {
write_cr0 (read_cr0 () & (~ 0x10000));
original_open = (void *)syscall_table[__NR_open];
syscall_table[__NR_open] = &new_open;
write_cr0 (read_cr0 () | 0x10000);
printk(KERN_EMERG "[+] onload: sys_call_table hooked\n");
} else {
printk(KERN_EMERG "[-] onload: syscall_table is NULL\n");
}

kfree(kernel_version);

/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
static void __exit onunload(void) {
if (syscall_table != NULL) {
write_cr0 (read_cr0 () & (~ 0x10000));
syscall_table[__NR_open] = original_open;
write_cr0 (read_cr0 () | 0x10000);
printk(KERN_EMERG "[+] onunload: sys_call_table unhooked\n");
} else {
printk(KERN_EMERG "[-] onunload: syscall_table is NULL\n");
}
printk(KERN_INFO "Goodbye world!\n");
}
module_init(onload);
module_exit(onunload);

当我注释掉 val = vfs_getxattr(dentry, "user.lock", NULL, 0);(在 new_open() 中)时,它就会安装。我无法弄清楚是什么导致了这个问题,我们将张开双臂欢迎任何想法!

最佳答案

符号 vfs_getxattr 被导出仅用于 GPL 模块(使用 EXPORT_SYMBOL_GPL)。

你需要

MODULE_LICENSE("GPL");

在你的模块中使用这些符号。


在每个驱动程序中都有 MODULE_LICENSE(); 总是更好,无论它是“通用公共(public)许可证”还是专有的。

关于c - insmod : Unknown symbol in module issue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43197536/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com