【发布时间】:2015-04-05 03:24:27
【问题描述】:
我已经成功实现了一个自定义系统调用getpuid(),现在我需要编写一个自定义的动态加载模块来导出一个与自定义系统调用getpeuid()功能完全相同的函数。 该系统调用用于获取调用进程的父进程的euid。以及自定义模块的段:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/printk.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/cred.h>
static int *getpeuid(pid_t pid, uid_t *uid)
{
// Code to get the parent process euid
......;
}
EXPORT_SYMBOL(getpeuid);
/* This function is called when the module is loaded. */
int getpeuid_init(void)
{
printk(KERN_INFO "getpeuid() loaded\n");
return 0;
}
/* This function is called when the module is removed. */
void getpeuid_exit(void) {
printk(KERN_INFO "Removing getpeuid()\n");
}
/* Macros for registering module entry and exit points. */
module_init( getpeuid_init );
module_exit( getpeuid_exit );
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Return parent euid.");
MODULE_AUTHOR("CGG");
我已成功编译此自定义模块并将模块插入内核。然后,我写了一个测试来测试从实现的可加载内核模块导出的函数的功能:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid;
uid_t *uid;
uid = (uid_t *)malloc(sizeof(uid_t));
pid = getppid();
int retval = getpeuid(pid, uid);
if( retval < 0 )
{
perror("My system call returned with an error code.");
}
printf("My syscall's parameters: %ld \n", pid);
printf("My system call returned %d.\n", retval);
printf("Current values: uid=%ld \n", *uid);
return 0;
}
但是当我编译测试脚本时,它给了我以下错误:
/tmp/ccV8WTx0.o:在函数'main'中: hw5-test.c:(.text+0x33): undefined reference to `supermom' collect2: error: ld 返回 1 个退出状态
我使用cat /proc/kallsyms检查了系统中可用的符号,我导出的符号在那里:
fa0eb000 T getpeuid [getpeuid]
我只是不知道我应该如何使用我的自定义函数,因为我没有用于我的自定义模块的头文件以包含在我的测试脚本中。即使我需要写一个头文件,我也不知道如何为自定义内核模块写一个头文件。
有人可以帮帮我吗?
提前致谢!
编辑:
我只能使用可动态加载的内核模块来模拟系统调用的功能。
编辑:
模块初始化代码中不允许修改系统调用表。
我从其他人那里得到了以下链接作为提示:
【问题讨论】:
-
您的直接问题是您试图链接一个不支持您的更改的 C 库 - 它缺少自定义系统调用的包装器。如果你真的设法添加了一个新的系统调用,你有它的编号,并且通常有一个 C 库函数可以让你通过编号而不是名称调用任意一个,你可以在开始修改 C 库之前开始对于您修改后的内核。当然,您是否真的完成了添加新的系统调用,这似乎仍然是一个悬而未决的问题。
-
@ChrisStratton 是的,我已经修改了我的问题,实际上我需要做的是通过可加载内核模块添加一个函数来模拟我之前编写的系统调用的行为。
-
您不能在不修改系统调用表的情况下添加系统调用。因此,要么,您修改了它,您需要通过数字调用它或将包装器添加到您的库中,否则您没有修改它并且必须使用其他接口,或者您希望得到的东西只是'除非您花更多时间了解这些现实并根据它们调整目标,否则不会发生。最后,您必须停止以毫无意义的方式使用“模拟”一词。 准确地说你的意思。当你这样做的时候,别再把 C 程序称为“脚本”了。
-
....通过模拟我的意思是从模块中导出的函数必须与我之前实现的系统调用具有完全相同的功能。
-
这样的功能只导出到内核,而不是用户空间。如果您愿意,您将不得不使用内核用户空间接口之一,例如已经讨论过的。
标签: c linux-kernel system-calls kernel-module archlinux