Linux内核模块编程指南
所以,如果我们想改变某个系统调用的工作方式,我们需要做的是编写自己的函数来实现它(通常通过添加一些我们自己的代码,然后调用原始的函数),然后更改sys_call_table指向函数的指针。因为我们可能被移除后,我们不想离开系统处于不稳定状态,重要的是cleanup_module表恢复到原来的状态。 下面是一个示例的源代码的内核模块。我们想“间谍”在一个特定的用户,并printk()消息每当用户打开一个文件。实现这一目标,我们系统调用来打开一个文件替换为自己的函数,称为our_sys_open。这个函数检查uid(用户id)当前的过程,如果它等于我们监视的uid,它调用printk()来显示文件的名称被打开。然后,无论哪种方式
注意,所有的相关问题做出系统调用偷unfeasiable供生产使用。为了阻止人们做潜在有害的事情sys_call_table不再是出口。这意味着,如果你想做更多的东西,而不仅仅是一个干燥的运行这个示例,您将不得不当前内核补丁为了sys_call_table出口。在示例目录,你会发现一个自述和补丁。可以想象,这样的修改是不能掉以轻心。不试试这个价值系统(即系统,你并不拥有——或不能恢复容易)。你需要得到本指南的完整源代码里作为一个tarball为了得到补丁和README。根据您的内核版本,你甚至可能需要应用补丁。还在这里吗?嗯,本章也是如此。如果一个内核黑客威尔的大笨狼,这是他想的第一件事。
/*
* syscall.c
*
* System call "stealing" sample.
*/
/*
* Copyright (C) 2001 by Peter Jay Salzman
*/
/*
* The necessary header files
*/
/*
* Standard in kernel modules
*/
#include <linux/kernel.h> /* We‘re doing kernel work */
#include <linux/module.h> /* Specifically, a module, */
#include <linux/moduleparam.h> /* which will have params */
#include <linux/unistd.h> /* The list of system calls */
/*
* For the current (process) structure, we need
* this to know who the current user is.
*/
#include <linux/sched.h>
#include <asm/uaccess.h>
/*
* The system call table (a table of functions). We
* just define this as external, and the kernel will
* fill it up for us when we are insmod‘ed
*
* sys_call_table is no longer exported in 2.6.x kernels.
* If you really want to try this DANGEROUS module you will
* have to apply the supplied patch against your current kernel
* and recompile it.
*/
extern void *sys_call_table[];
/*
* UID we want to spy on - will be filled from the
* command line
*/
static int uid;
module_param(uid, int, 0644);
/*
* A pointer to the original system call. The reason
* we keep this, rather than call the original function
* (sys_open), is because somebody else might have
* replaced the system call before us. Note that this
* is not 100% safe, because if another module
* replaced sys_open before us, then when we‘re inserted
* we‘ll call the function in that module - and it
* might be removed before we are.
*
* Another reason for this is that we can‘t get sys_open.
* It‘s a static variable, so it is not exported.
*/
asmlinkage int (*original_call) (const char *, int, int);
/*
* The function we‘ll replace sys_open (the function
* called when you call the open system call) with. To
* find the exact prototype, with the number and type
* of arguments, we find the original function first
* (it‘s at fs/open.c).
*
* In theory, this means that we‘re tied to the
* current version of the kernel. In practice, the
* system calls almost never change (it would wreck havoc
* and require programs to be recompiled, since the system
* calls are the interface between the kernel and the
* processes).
*/
asmlinkage int our_sys_open(const char *filename, int flags, int mode)
{
int i = 0;
char ch;
/*
* Check if this is the user we‘re spying on
*/
if (uid == current->uid) {
/*
* Report the file, if relevant
*/
printk("Opened file by %d: ", uid);
do {
get_user(ch, filename + i);
i++;
printk("%c", ch);
} while (ch != 0);
printk("\n");
}
/*
* Call the original sys_open - otherwise, we lose
* the ability to open files
*/
return original_call(filename, flags, mode);
}
/*
* Initialize the module - replace the system call
*/
int init_module()
{
/*
* Warning - too late for it now, but maybe for
* next time...
*/
printk(KERN_ALERT "I‘m dangerous. I hope you did a ");
printk(KERN_ALERT "sync before you insmod‘ed me.\n");
printk(KERN_ALERT "My counterpart, cleanup_module(), is even");
printk(KERN_ALERT "more dangerous. If\n");
printk(KERN_ALERT "you value your file system, it will ");
printk(KERN_ALERT "be \"sync; rmmod\" \n");
printk(KERN_ALERT "when you remove this module.\n");
/*
* Keep a pointer to the original function in
* original_call, and then replace the system call
* in the system call table with our_sys_open
*/
original_call = sys_call_table[__NR_open];
sys_call_table[__NR_open] = our_sys_open;
/*
* To get the address of the function for system
* call foo, go to sys_call_table[__NR_foo].
*/
printk(KERN_INFO "Spying on UID:%d\n", uid);
return 0;
}
/*
* Cleanup - unregister the appropriate file from /proc
*/
void cleanup_module()
{
/*
* Return the system call back to normal
*/
if (sys_call_table[__NR_open] != our_sys_open) {
printk(KERN_ALERT "Somebody else also played with the ");
printk(KERN_ALERT "open system call\n");
printk(KERN_ALERT "The system may be left in ");
printk(KERN_ALERT "an unstable state.\n");
}
sys_call_table[__NR_open] = original_call;
}
原文地址:http://blog.csdn.net/wuheshi/article/details/43794141