linux 系统调用system call

来源:互联网 发布:php集成环境哪个好 编辑:程序博客网 时间:2024/06/10 06:05

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>/*  *系统调用表(表的函数)。我们  *这定义为外部,和内核  *把它填平“当我们insmod”   *   * sys_call_table不再出口在2.6。x内核。  *如果你真的想尝试这种危险的模块  *必须应用提供对当前内核补丁  *并重新编译它 */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);/* 一个指向原来的系统调用。的原因  *我们保持这一点,而不是最初的函数调用  *(sys_open),是因为别人  *取代了系统调用在我们面前。请注意,这  *不是100%安全,因为如果另一个模块  *取代sys_open在我们面前,然后当我们插入  *我们将在该模块,调用该函数  *可能会删除之前。  *   *这是另一个原因,我们不能得到sys_open。  *这是一个静态变量,所以它不出口。 * */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;}


1 0
原创粉丝点击