Files
LDD-LinuxDeviceDrivers/study/engine/arm64/memoryEngine.c
T

1071 lines
24 KiB
C

/*
* Author: HIT CS HDMC team.
* Create: 2010-3-12 8:50
* Last modified: 2010-6-13 14:06:20
* Description:
* Memory fault injection engine running as a kernel module.
* This module will create "/proc/memoryEngine/" directory and 9 proc nodes.
* Write paramenters and request to these proc nodes and read the output from related proc node.
*/
#include "memoryEngine.h"
/*
* proc entries
*/
struct proc_dir_entry *dir = NULL; /// the directory of the MEMORY INJECT Moudle
struct proc_dir_entry *proc_pid = NULL; /// write only
struct proc_dir_entry *proc_va = NULL; /// write only
struct proc_dir_entry *proc_ctl = NULL; /// write only
struct proc_dir_entry *proc_kFuncName = NULL; /// write only
struct proc_dir_entry *proc_val = NULL; /// rw
struct proc_dir_entry *proc_signal = NULL; /// rw
struct proc_dir_entry *proc_pa = NULL; /// read only
struct proc_dir_entry *proc_taskINfo = NULL; /// read only
/*
* proc node values
*/
int pid; /// pid
unsigned long va; /// virtual Address
unsigned long pa; /// physical Addreess
int ctl; /// ctl
int signal; /// signal
char kFuncName[MAX_LINE]; /// kFuncName
long memVal; /// memVal
unsigned long ack_pa; /// physical Address
unsigned long ack_va; /// virtual Address
int ack_signal; /// signal
int ret; /// return value
char taskInfo[PAGE_SIZE]; /// taskInfo
///////////////////////////////////////////////
unsigned long userspace_phy_mem; /// user space physical memory
long orig_pa_data; /// origin data of the physics memory
long new_pa_data; /// the new data you want write to physics memory
int faultInterval;
/*
* kprobe
*/
static struct kprobe kp_kFunc;
struct jprobe jprobe1 =
{
.entry = jforce_sig_info,
.kp =
{
.symbol_name = "force_sig_info",
},
};
//时钟中断数计数
static int count = 0;
//保存原始代码
static long orig_code = 0;
/*
* process the request
*/
void do_request(void)
{
struct task_struct *task = NULL;
unsigned long pa = 0;
long kernel_va = 0;
int status;
/// get a task's memory map information
if(ctl == REQUEST_TASK_INFO)
{
dbginfo("Rcv request:Get task info\n");
memset(taskInfo,'\0',sizeof(taskInfo));
if(pid <= 0)
{
ack_signal = ACK_TASK_INFO;
return;
}
task = findTaskByPid(pid);
if( task != NULL )
{
getTaskInfo(task, taskInfo, sizeof(taskInfo));
}
ack_signal = ACK_TASK_INFO;
return;
}
/// convert a process's linear address to physical address
else if(ctl == REQUEST_V2P)
{
task = findTaskByPid(pid);
if( task == NULL )
{
dbginfo("No such process\n");
ack_pa = -1;
ack_signal = ACK_V2P;
return;
}
if( task->mm == NULL )
{
ack_pa = -1;
ack_signal = ACK_V2P;
return;
}
ack_pa = v2p(task->mm,va,&status);
if(ack_pa == FAIL)
{
dbginfo("No physical address\n");
}
ack_signal = ACK_V2P;
return;
}
/// convert kernel virtual address to physical address
else if(ctl == REQUEST_KV2P)
{
ack_pa = kv2p(va,&status);
if(pa == FAIL)
{
dbginfo("No physical address\n");
}
ack_signal = ACK_KV2P;
return;
}
/// get kernel function's addr(kernel virtual address)
else if(ctl == REQUEST_KFUNC_VA)
{
ack_va = kFunc2v(kFuncName);
ack_signal = ACK_KFUNC_VA;
return;
}
/// 请求读取内核函数起始地址内容
else if(ctl == REQUEST_READ_KFUNC)
{
kernel_va = kFunc2v(kFuncName);
memVal = *((long *)kernel_va);
ack_signal = ACK_READ_KFUNC;
}
/// 请求改写内核函数起始地址内容
else if(ctl == REQUEST_WRITE_KFUNC)
{
//利用kprobe,在第一次调用do_timer()时,注入故障
int ret;
count = 0;
if(strlen(kFuncName) > 0)
{
faultInterval = 1; //故障仅持续一个时钟周期
kp_kFunc.addr = 0;
kp_kFunc.symbol_name = kFuncName;
kp_kFunc.pre_handler = handler_pre_kFunc;
ret = register_kprobe(&kp_kFunc);
if(ret < 0)
{
dbginfo("Fained to register kprobe\n");
ack_signal = ACK_WRITE_KFUNC;
return;
}
//等待故障注入结束
dbginfo("start count\n");
int temp=0;
while(1)
{
if(count == -1)
{
unregister_kprobe(&kp_kFunc);
dbginfo("recovery\n");
break;
}
if(temp == -1)
{
break;
}
temp++;
//dbginfo("count:%d\n",count);
}
}
ack_signal = ACK_WRITE_KFUNC;
dbginfo("Success to inject MTTR fault\n");
return;
}
}
/*
* get a task's memory map information
*/
int getTaskInfo(struct task_struct *pTask, char *pData, int length)
{
struct mm_struct *pMM;
struct vm_area_struct *pVMA;
struct vm_area_struct *p;
char file[MAX_LINE];
struct dentry *pPath = NULL;
char *end, *start;
char *info = pData;
long phy_addr;
unsigned long start_va,end_va;
int status;
if(pTask == NULL) { return FAIL; }
if((pMM = pTask->mm) == NULL) { return FAIL; }
memset(pData, '\0', length);
//前19个字段是关于进程内存信息的总体信息
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->total_vm, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->locked_vm, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->shared_vm, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->exec_vm, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->stack_vm, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->reserved_vm, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->def_flags, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->nr_ptes, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->start_code, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->end_code, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->start_data, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->end_data, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->start_brk, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->brk, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->start_stack, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->arg_start, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->arg_end, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->env_start, DELIMITER);
safe_sprintf(pData, length, info+strlen(info), "%lx%c", pMM->env_end, DELIMITER);
pVMA = pMM->mmap;
if(pVMA == NULL) { return OK; }
for(p=pVMA; p!=NULL; p=p->vm_next)
{
//起始地址
safe_sprintf(pData, length, info+strlen(info), "%lx %lx ", p->vm_start, p->vm_end);
//属性
if(p->vm_flags & VM_READ)
{ safe_sprintf(pData, length, info+strlen(info), "r"); }
else
{ safe_sprintf(pData, length, info+strlen(info), "-"); }
if(p->vm_flags & VM_WRITE)
{ safe_sprintf(pData, length, info+strlen(info), "w"); }
else
{ safe_sprintf(pData, length, info+strlen(info), "-"); }
if(p->vm_flags & VM_EXEC)
{ safe_sprintf(pData, length, info+strlen(info), "x"); }
else
{ safe_sprintf(pData, length, info+strlen(info), "-"); }
if(p->vm_flags & VM_SHARED)
{ safe_sprintf(pData, length, info+strlen(info), "s"); }
else
{ safe_sprintf(pData, length, info+strlen(info), "p"); }
//对应文件名
if(p->vm_file != NULL)
{
if(p->vm_file->f_dentry != NULL)
{
safe_sprintf(pData, length, info+strlen(info), " ");
memset(file,'\0',sizeof(file));
for(pPath = p->vm_file->f_dentry; pPath != NULL; pPath = pPath->d_parent)
{
if(strcmp(pPath->d_name.name,"/") != 0)
{
strcpy(file + strlen(file), pPath->d_name.name);
strcpy(file + strlen(file), "/");
continue;
}
break;
}
do
{
end = file + strlen(file) - 1;
for(start = end - 1; *start != '/' && start > file; start--);
if(*start == '/') {start++;}
*end = '\0';
safe_sprintf(pData, length, info+strlen(info), "/%s", start);
*start = '\0';
} while(start > file);
}
}
safe_sprintf(pData, length, info+strlen(info), "%c", DELIMITER);
//对应物理地址页
start_va = p->vm_start;
end_va = p->vm_end;
while(end_va > start_va)
{
safe_sprintf(pData, length, info+strlen(info), "%lx-%lx\t", start_va, start_va + PAGE_SIZE);
phy_addr = v2p(pMM, start_va, &status);
if(phy_addr != FAIL)
{
safe_sprintf(pData, length, info+strlen(info), "va:0x%lx <--> pa:0x%lx", start_va, phy_addr);
}
start_va += PAGE_SIZE;
safe_sprintf(pData, length, info+strlen(info), "%c", DELIMITER);
}
safe_sprintf(pData, length, info+strlen(info), "%c", DELIMITER);
}
return OK;
}
/*
*
*/
static int handler_pre_kFunc(struct kprobe *p, struct pt_regs *regs)
{
unsigned long va;
va = (unsigned long)p->addr;
if(va <= 0) { return OK; }
//第一次触发
if(count == 0)
{
//读取前64字节,注入故障
orig_code = *((long *)va);
//_inject_fault(va,memVal);
*((long *)va) = memVal; //故障
return OK;
}
count ++;
//到达结束时间
if(count == faultInterval + 1)
{
//恢复code
*((long *)va) = orig_code;
count = -1;
}
return OK;
}
/*
* find_task_by_pid maybe not supported
* O(n) is fine :)
*/
struct task_struct * findTaskByPid(pid_t pid)
{
struct task_struct *task = NULL;
// Traversing the process in the system to find the PID
// add by gatieme @2016-03-20
for_each_process(task)
{
if(task->pid == pid)
{
return task;
}
}
return NULL;
}
/*
* convert a process's linear address to physical address
*/
long v2p(struct mm_struct *pMM,unsigned long va,int *pStatus)
{
pte_t *pte = NULL;
unsigned long phyaddress = FAIL;
pte = getPte(pMM, va);
if(pte != NULL)
{
phyaddress = (pte_val(*pte) & PAGE_MASK) | (va & ~PAGE_MASK);
}
return phyaddress;
}
/*
* convert kernel virtual address to physical address
*/
long kv2p(unsigned long va,int *pStatus)
{
if(va < 0)
return FAIL;
if(__pa(va) >= 0)
return __pa(va);
return FAIL;
}
/*
* get kernel function's addr(kernel virtual address)
* the kernel function should be looked up in the System.map
*/
static struct kprobe kp;
long kFunc2v(char *funcName)
{
int ret;
unsigned long va;
kp.addr = 0;
kp.symbol_name = funcName;
ret = register_kprobe(&kp);
if(ret < 0)
{
dbginfo("Fained to register kprobe\n");
return FAIL;
}
va = (unsigned long)kp.addr;
unregister_kprobe(&kp);
if(va == 0)
return FAIL;
return va;
}
/*
*
*/
struct vm_area_struct * getVMA(struct mm_struct *pMM,unsigned long va)
{
struct vm_area_struct *p;
if(pMM == NULL) return NULL;
p = pMM->mmap;
if(p == NULL) return NULL;
for(; p != NULL; p = p->vm_next)
{
if( va >= p->vm_start && va < p->vm_end )
{
return p;
}
}
return NULL;
}
/*
*
*/
pte_t * getPte(struct mm_struct *pMM, unsigned long va)
{
pgd_t *pgd = NULL;
pmd_t *pmd = NULL;
pud_t *pud = NULL;
pte_t *pte = NULL;
///get the pdg entry pointer
pgd = pgd_offset(pMM, va);
if(pgd_none(*pgd)) { return NULL; }
pud = pud_offset(pgd,va);
if(pud_none(*pud)) { return NULL; }
pmd = pmd_offset(pud,va);
if(pmd_none(*pmd)) { return NULL; }
pte = pte_offset_kernel(pmd,va);
if(pte_none(*pte)) { return NULL; }
if(!pte_present(*pte)) { return NULL; }
return pte;
}
/*
*
*/
int setVMAFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags)
{
struct vm_area_struct *p;
p = getVMA(pMM,va);
if(p == NULL) return FAIL;
if(flags > 0)
{
p->vm_flags |= VM_WRITE;
p->vm_flags |= VM_SHARED;
}
if(flags == 0)
{
p->vm_flags &= ~VM_WRITE;
p->vm_flags &= ~VM_SHARED;
}
else { return FAIL; }
return OK;
}
/*
*
*/
int setPageFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags)
{
pte_t *pte = NULL;
pte_t ret;
pte = getPte(pMM, va);
if( pte == NULL ) { return FAIL; }
if(flags > 0)
{
ret = pte_mkwrite(*pte);
}
else if(flags == 0)
{
ret = pte_wrprotect(*pte);
}
else { return FAIL; }
return OK;
}
/*
*
*/
int proc_write_pid( struct file *file,
const char __user *buffer,
unsigned long count,
void * data)
{
int iRet;
char sPid[MAX_LINE];
if(count <= 0)
{
return FAIL;
}
memset(sPid, '\0', sizeof(sPid));
/////////////////////////////////////////////////////////////////////
//
// copy_from_user函数的目的是从用户空间拷贝数据到内核空间,
// 失败返回没有被拷贝的字节数,成功返回0.
// 这么简单的一个函数却含盖了许多关于内核方面的知识,
// 比如内核关于异常出错的处理.
// 从用户空间拷贝数据到内核中时必须很小心,
// 假如用户空间的数据地址是个非法的地址,或是超出用户空间的范围,
// 或是那些地址还没有被映射到,都可能对内核产生很大的影响,
// 如oops,或被造成系统安全的影响.
// 所以copy_from_user函数的功能就不只是从用户空间拷贝数据那样简单了,
// 他还要做一些指针检查连同处理这些问题的方法.
//
// 函数原型在[arch/i386/lib/usercopy.c]中
// unsigned long
// copy_from_user( void *to,
// const void __user *from,
// unsigned long n)
//
/////////////////////////////////////////////////////////////////////
//
// 将用户空间中, 地址buffr指向的count个数据拷贝到内核空间地址sPid中
iRet = copy_from_user(sPid, buffer, count);
if(iRet != 0)
{
dbginfo("Error when copy_from_user...\n");
return FAIL;
}
iRet = sscanf(sPid, "%d", &pid); // 将读出来的数据sPid赋值给模块的全局变量pid
if(iRet != 1)
{
return FAIL;
}
dbginfo("Rcv pid:%d\n",pid);
return count;
}
/*
*
*/
int proc_read_virtualAddr( char * page,
char **start,
off_t off,
int count,
int * eof,
void * data)
{
int iLen;
iLen = sprintf(page, "%lx", ack_va);
return iLen;
}
/*
*
*/
int proc_write_virtualAddr( struct file *file,
const char *buffer,
unsigned long count,
void * data)
{
int iRet;
char sVa[MAX_LINE];
if(count <= 0)
{
return FAIL;
}
memset(sVa, '\0', sizeof(sVa));
iRet = copy_from_user(sVa, buffer, count);
if(iRet)
{
return FAIL;
}
iRet = sscanf(sVa,"%lx",&va);
if(iRet != 1)
{
return FAIL;
}
dbginfo("Rcv virtual addr:0x%lx\n",va);
return count;
}
/*
*
*/
int proc_write_ctl( struct file *file,
const char *buffer,
unsigned long count,
void * data)
{
int iRet;
char sCtl[MAX_LINE];
if(count <= 0)
{
return FAIL;
}
memset(sCtl, '\0', sizeof(sCtl));
iRet = copy_from_user(sCtl, buffer, count);
if(iRet)
{
return FAIL;
}
iRet = sscanf(sCtl,"%d",&ctl);
if(iRet != 1)
{
return FAIL;
}
do_request();
return count;
}
/*
*
*/
int proc_read_signal( char * page,
char **start,
off_t off,
int count,
int * eof,
void * data)
{
int iLen;
iLen = sprintf(page, "%d", ack_signal);
return iLen;
}
/*
*
*/
int proc_write_signal( struct file *file,
const char *buffer,
unsigned long count,
void * data)
{
int iRet;
char sSignal[MAX_LINE];
if(count <= 0)
{
return FAIL;
}
memset(sSignal, '\0', sizeof(sSignal));
iRet = copy_from_user(sSignal, buffer, count);
if(iRet)
{
return FAIL;
}
iRet = sscanf(sSignal,"%d",&signal);
if(iRet != 1)
{
return FAIL;
}
dbginfo("Rcv signal:%d\n",signal);
return count;
}
/*
*
*/
int proc_read_pa(char * page,char **start, off_t off, int count, int * eof,void * data)
{
int iLen;
iLen = sprintf(page, "%lx", ack_pa);
return iLen;
}
/*
*
*/
int proc_write_pa(struct file *file,const char *buffer,unsigned long count,void * data)
{
int iRet;
char sPa[MAX_LINE];
if(count <= 0) { return FAIL; }
memset(sPa, '\0', sizeof(sPa));
iRet = copy_from_user(sPa, buffer, count);
if(iRet) { return FAIL; }
iRet = sscanf(sPa,"%lx",&pa);
if(iRet != 1) { return FAIL; }
dbginfo("Rcv pa:0x%lx\n",pa);
return count;
}
/*
*
*/
int proc_write_kFuncName(struct file *file,const char *buffer,unsigned long count,void * data)
{
int iRet;
if(count <= 0) { return FAIL; }
memset(kFuncName, '\0', sizeof(kFuncName));
iRet = copy_from_user(kFuncName, buffer, count);
if(iRet) { return FAIL; }
//remove '\n'
if(kFuncName[strlen(kFuncName) - 1] == '\n')
{
kFuncName[strlen(kFuncName) - 1] = '\0';
}
dbginfo("Rcv kernel func name:%s\n",kFuncName);
return count;
}
/*
*
*/
int proc_read_taskInfo(char * page,char **start, off_t off, int count, int * eof,void * data)
{
int iLen;
iLen = sprintf(page, "%s", taskInfo);
return iLen;
}
/*
*
*/
int proc_write_memVal(struct file *file,const char *buffer,unsigned long count,void * data)
{
int iRet;
char sMemVal[MAX_LINE];
if(count <= 0)
{
return FAIL;
}
memset(sMemVal, '\0', sizeof(sMemVal));
iRet = copy_from_user(sMemVal, buffer, count);
if(iRet)
{
return FAIL;
}
iRet = sscanf(sMemVal,"%lx",&memVal);
if(iRet != 1)
{
return FAIL;
}
dbginfo("Rcv memVal:0x%lx\n",memVal);
return count;
}
/*
*
*/
int proc_read_memVal( char * page,
char **start,
off_t off,
int count,
int * eof,
void * data)
{
int iLen;
iLen = sprintf(page, "%lx", memVal);
return iLen;
}
/*
* init memory fault injection module
* 初始化内存注入故障模块
*
* 使用proc_mkdir()创建一个dir = /proc/memoryEngine
* 再利用create_proc_read_entry()函数创建一个processinfo文件。
* 我们从模块里面获取的信息都将写入到这些文件中。
*
*/
static int __init initME(void)
{
/*
* create a direntory named "memoryEngine" in /proc for the moudles
* as the interface between the kernel and the user program.
*
*/
dir = proc_mkdir("memoryEngine", NULL);
if(dir == NULL)
{
dbginfo("Can't create /proc/memoryEngine/\n");
return FAIL;
}
dir->owner = THIS_MODULE;
/// create a file named "pid" in direntory
proc_pid = create_proc_entry("pid", PERMISSION, dir);
if(proc_pid == NULL)
{
dbginfo("Can't create /proc/memoryEngine/pid\n");
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_pid->write_proc = proc_write_pid; /// write only
proc_pid->owner = THIS_MODULE;
/// create a file named "virtualAddr" in direntory
proc_va = create_proc_entry("virtualAddr", PERMISSION, dir);
if(proc_va == NULL)
{
dbginfo("Can't create /proc/memoryEngine/virtualAddr\n");
remove_proc_entry("pid", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_va->read_proc = proc_read_virtualAddr; // can read
proc_va->write_proc = proc_write_virtualAddr; // can write
proc_va->owner = THIS_MODULE;
/// create a file named "ctl" in direntory
proc_ctl = create_proc_entry("ctl", PERMISSION, dir);
if(proc_ctl == NULL)
{
dbginfo("Can't create /proc/memoryEngine/ctl\n");
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_ctl->write_proc = proc_write_ctl; // write only
proc_ctl->owner = THIS_MODULE;
/// create a file named "signal" in direntory
proc_signal = create_proc_entry("signal", PERMISSION, dir);
if(proc_signal == NULL)
{
dbginfo("Can't create /proc/memoryEngine/signal\n");
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("ctl", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_signal->read_proc = proc_read_signal; // can read
proc_signal->write_proc = proc_write_signal; // can write
proc_signal->owner = THIS_MODULE;
/// create a file named "physicalAddr" in direntory
proc_pa = create_proc_entry("physicalAddr", PERMISSION, dir);
if(proc_pa == NULL)
{
dbginfo("Can't create /proc/memoryEngine/physicalAddr\n");
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("ctl", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_pa->read_proc = proc_read_pa; // can read
proc_pa->write_proc = proc_write_pa; // can write
/// create a file named "kFuncName" in direntory
proc_kFuncName = create_proc_entry("kFuncName", PERMISSION, dir);
if(proc_kFuncName == NULL)
{
dbginfo("Can't create /proc/memoryEngine/kFuncName\n");
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("ctl", dir);
remove_proc_entry("physicalAddr", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_kFuncName->write_proc = proc_write_kFuncName; // write only
/// create a file named "taskInfo" in direntory
proc_taskINfo = create_proc_entry("taskInfo", PERMISSION, dir);
if(proc_taskINfo == NULL)
{
dbginfo("Can't create /proc/memoryEngine/taskInfo\n");
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("ctl", dir);
remove_proc_entry("physicalAddr", dir);
remove_proc_entry("kFuncName", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_taskINfo->read_proc = proc_read_taskInfo; // read only
/// create a file named "memVal" in direntory
proc_val = create_proc_entry("memVal", PERMISSION, dir);
if(proc_val == NULL)
{
dbginfo("Can't create /proc/memoryEngine/memVal\n");
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("ctl", dir);
remove_proc_entry("physicalAddr", dir);
remove_proc_entry("kFuncName", dir);
remove_proc_entry("taskInfo", dir);
remove_proc_entry("memoryEngine", NULL);
return FAIL;
}
proc_val->write_proc = proc_write_memVal; // can write
proc_val->read_proc = proc_read_memVal; // can read
ret = register_jprobe(&jprobe1);
if (ret < 0)
{
printk("register_jprobe jprobe1 failed, returned %d\n", ret);
return ret;
}
printk("Planted jprobe at force_sig_info: %p\n", jprobe1.kp.addr);
dbginfo("Memory engine module init\n");
return OK;
}
static int jforce_sig_info(int sig,struct siginfo *info,struct task_struct *t)
{
printk("MemSysFI: kernel is sending signal %d to process pid: %d, comm: %s\n",sig,t->pid,t->comm);
/*
if (f_inject == 'N')
{
jprobe_return();
return 0;
}
down_interruptible(&sem);
if ( addone(addone(inj_info.rear))==inj_info.front )
{
*/
/*error:队列满*/
/*
sprintf(inj_info.inj_log[inj_info.rear].msg,"caution : buf is full, messages have been dropped\n");
}
else
{
inj_info.rear = addone(inj_info.rear);
sprintf(inj_info.inj_log[inj_info.rear].msg,"warning : kernel is sending signal %d to process pid: %d, comm: %s\n",sig,current->pid,current->comm);
//inj_info->inj_log[inj_info->rear ] = x ;
}
up(&sem);
*/
/*
if(message!=NULL)
{
for(i=0;i<256;i++)
message[i]='\0';
sprintf(message,"warning : kernel is sending signal %d to process pid: %d, comm: %s\n\0",sig,current->pid,current->comm);
}
else
return -1;
struct bufferList *buflist;
buflist = (struct bufferList *)kmalloc(sizeof(struct bufferList),GFP_KERNEL);
buflist->pNext = NULL;
buflist->buffer = message;
down_interruptible(&sem);
if(Head==NULL)
{
Head = buflist;
Tail = Head;
}
else
{
Tail->pNext = buflist;
Tail = buflist;
}
flag = 1;
up(&sem);
*/
// wake_up_interruptible(&wq2);
jprobe_return();
return 0;
}
/*
* uninit memory fault injection module
*/
static void __exit exitME(void)
{
remove_proc_entry("pid", dir);
remove_proc_entry("virtualAddr", dir);
remove_proc_entry("ctl", dir);
remove_proc_entry("signal", dir);
remove_proc_entry("physicalAddr", dir);
remove_proc_entry("kFuncName", dir);
remove_proc_entry("taskInfo", dir);
remove_proc_entry("memVal", dir);
remove_proc_entry("memoryEngine", NULL);
unregister_jprobe(&jprobe1);
printk("jprobe at %p unregistered.\n", jprobe1.kp.addr);
dbginfo("Memory engine module exit\n");
}
module_init(initME);
module_exit(exitME);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HIT CS HDMC team");
MODULE_DESCRIPTION("Memory Engine Module.");