增加了自己的驱动学习...

This commit is contained in:
gatieme
2016-05-02 16:43:18 +08:00
parent 81386bf015
commit 9c310d57a0
25 changed files with 5673 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
/*
* Author: HIT CS HDMC team.
* Create: 2010-3-12 8:20:01
* Last modified: 2010-6-13 14:13:47
*/
#ifndef _MEMORY_ENGINE_H
#define _MEMORY_ENGINE_H
/*
* common include header files
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/kprobes.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/dcache.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/kallsyms.h>
#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#define MAX_LINE 256 /// max length of a line
#define DELIMITER '\n' /// the char is used to split the taskinfo
#define PERMISSION 0644 /// proc node permission
/*
* return values
*/
#define OK 0
#define FAIL -1
#define PGD_NONE -2
#define PUD_NONE -3
#define PMD_NONE -4
#define PTE_NONE -5
#define PTE_NOT_PRESENT -6
/*
* request command
*/
#define REQUEST_TASK_INFO 1 /// get a task's memory map information
#define REQUEST_V2P 2 /// convert a process's linear address to physical address
#define REQUEST_KV2P 3 /// convert kernel virtual address to physical address
#define REQUEST_KFUNC_VA 4 /// get kernel function's addr(kernel virtual address)
#define REQUEST_READ_KFUNC 5 /// 请求读取内核函数起始地址内容
#define REQUEST_WRITE_KFUNC 6 /// 请求改写内核函数起始地址内容
///#define REQUEST_WRITE 10 /// 请求改写指定物理地址内容,改为用户态实现此功能
///#define REQUEST_MEM 11 /// 请求获取全部物理内存信息
///#define REQUEST_ADDR_STOP 12 ///
/*
* ack signals
*/
#define ACK_TASK_INFO REQUEST_TASK_INFO
#define ACK_V2P REQUEST_V2P
#define ACK_KV2P REQUEST_KV2P
#define ACK_KFUNC_VA REQUEST_KFUNC_VA
#define ACK_READ_KFUNC REQUEST_READ_KFUNC
#define ACK_WRITE_KFUNC REQUEST_WRITE_KFUNC
///#define REQUEST_WRITE REQUEST_WRITE
///#define ACK_MEM REQUEST_MEM
///#define ACK_ADDR_STOP REQUEST_ADDR_STOP
/*
* #define DEBUG ,dbginfo() will add more debug information into nomal printk.
* #define SILENCE ,dbginfo() will print nothing.
* Otherwise ,dbginfo() equals to printk.
*/
#ifdef __FUNCTION__
#ifdef __LINE__
#ifdef DEBUG
//printk with line and function name
#define dbginfo(format,args...); \
printk(KERN_INFO "%s-L%d:"format,__FUNCTION__,__LINE__,##args);
#elif defined SILENCE
#define dbginfo(format,args...);
#else //printk normally
#define dbginfo(format,args...); printk(KERN_INFO format,##args);
#endif
#endif
#endif
/*
* safe sprintf
* It will not be out of range.
*/
#define safe_sprintf(start, n, p, format, args...); \
{ if( (p - start) < n ) { snprintf( (char *)p, (n - (p - start)), format, ##args ); } }
/*
* utility functions
*/
static int handler_pre_kFunc(struct kprobe *p, struct pt_regs *regs);
struct task_struct *findTaskByPid(pid_t pid);
long v2p(struct mm_struct *pMM,unsigned long va,int *pStatus);
long kv2p(unsigned long va,int *pStatus);
long kFunc2v(char *funcName);
struct vm_area_struct * getVMA(struct mm_struct *pMM,unsigned long va);
pte_t * getPte(struct mm_struct *pMM,unsigned long va);
int setVMAFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags);
int setPageFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags);
int getTaskInfo(struct task_struct *pTask, char *pData, int length);
/*
* proc entry function
*/
int proc_write_pid(struct file *file,const char __user *buffer,unsigned long count,void * data);
int proc_read_virtualAddr(char * page,char **start, off_t off, int count, int * eof,void * data);
int proc_write_virtualAddr(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_write_ctl(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_read_signal(char * page,char **start, off_t off, int count, int * eof,void * data);
int proc_write_signal(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_read_pa(char * page,char **start, off_t off, int count, int * eof,void * data);
static int jforce_sig_info(int sig,struct siginfo *info,struct task_struct *t);
#endif
+36
View File
@@ -0,0 +1,36 @@
# Makefile for the memory fault injection engine.
#
# Author: HIT CS HDMC team.
# Create: 2010-3-12 8:46
# Last modified: 2010-6-13 13:55:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
ifneq ($(KERNELRELEASE),)
obj-m := memoryEngine.o
else
obj-m := memoryEngine.o
KERNELDIR=/lib/modules/$(shell uname -r)/build
PWD=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
install:
insmod memoryEngine.ko
remove:
rmmod memoryEngine
clean:
make -C /lib/modules/`uname -r`/build M=`pwd` clean
rm -f modules.order Module.symvers Module.markers
endif
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
/*
* Author: HIT CS HDMC team.
* Create: 2010-3-12 8:20:01
* Last modified: 2010-6-13 14:13:47
*/
#ifndef _MEMORY_ENGINE_H
#define _MEMORY_ENGINE_H
/*
* common include header files
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/kprobes.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/dcache.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/kallsyms.h>
#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#define MAX_LINE 256 /// max length of a line
#define DELIMITER '\n' /// the char is used to split the taskinfo
#define PERMISSION 0644 /// proc node permission
/*
* return values
*/
#define OK 0
#define FAIL -1
#define PGD_NONE -2
#define PUD_NONE -3
#define PMD_NONE -4
#define PTE_NONE -5
#define PTE_NOT_PRESENT -6
/*
* request command
*/
#define REQUEST_TASK_INFO 1 /// get a task's memory map information
#define REQUEST_V2P 2 /// convert a process's linear address to physical address
#define REQUEST_KV2P 3 /// convert kernel virtual address to physical address
#define REQUEST_KFUNC_VA 4 /// get kernel function's addr(kernel virtual address)
#define REQUEST_READ_KFUNC 5 /// 请求读取内核函数起始地址内容
#define REQUEST_WRITE_KFUNC 6 /// 请求改写内核函数起始地址内容
///#define REQUEST_WRITE 10 /// 请求改写指定物理地址内容,改为用户态实现此功能
///#define REQUEST_MEM 11 /// 请求获取全部物理内存信息
///#define REQUEST_ADDR_STOP 12 ///
/*
* ack signals
*/
#define ACK_TASK_INFO REQUEST_TASK_INFO
#define ACK_V2P REQUEST_V2P
#define ACK_KV2P REQUEST_KV2P
#define ACK_KFUNC_VA REQUEST_KFUNC_VA
#define ACK_READ_KFUNC REQUEST_READ_KFUNC
#define ACK_WRITE_KFUNC REQUEST_WRITE_KFUNC
///#define REQUEST_WRITE REQUEST_WRITE
///#define ACK_MEM REQUEST_MEM
///#define ACK_ADDR_STOP REQUEST_ADDR_STOP
/*
* #define DEBUG ,dbginfo() will add more debug information into nomal printk.
* #define SILENCE ,dbginfo() will print nothing.
* Otherwise ,dbginfo() equals to printk.
*/
#ifdef __FUNCTION__
#ifdef __LINE__
#ifdef DEBUG
//printk with line and function name
#define dbginfo(format,args...); \
printk(KERN_INFO "%s-L%d:"format,__FUNCTION__,__LINE__,##args);
#elif defined SILENCE
#define dbginfo(format,args...);
#else //printk normally
#define dbginfo(format,args...); printk(KERN_INFO format,##args);
#endif
#endif
#endif
/*
* safe sprintf
* It will not be out of range.
*/
#define safe_sprintf(start, n, p, format, args...); \
{ if( (p - start) < n ) { snprintf( (char *)p, (n - (p - start)), format, ##args ); } }
/*
* utility functions
*/
static int handler_pre_kFunc(struct kprobe *p, struct pt_regs *regs);
struct task_struct *findTaskByPid(pid_t pid);
long v2p(struct mm_struct *pMM,unsigned long va,int *pStatus);
long kv2p(unsigned long va,int *pStatus);
long kFunc2v(char *funcName);
struct vm_area_struct * getVMA(struct mm_struct *pMM,unsigned long va);
pte_t * getPte(struct mm_struct *pMM,unsigned long va);
int setVMAFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags);
int setPageFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags);
int getTaskInfo(struct task_struct *pTask, char *pData, int length);
/*
* proc entry function
*/
int proc_write_pid(struct file *file,const char __user *buffer,unsigned long count,void * data);
int proc_read_virtualAddr(char * page,char **start, off_t off, int count, int * eof,void * data);
int proc_write_virtualAddr(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_write_ctl(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_read_signal(char * page,char **start, off_t off, int count, int * eof,void * data);
int proc_write_signal(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_read_pa(char * page,char **start, off_t off, int count, int * eof,void * data);
static int jforce_sig_info(int sig,struct siginfo *info,struct task_struct *t);
#endif
+230
View File
@@ -0,0 +1,230 @@
/*
* Author: HIT CS HDMC team.
* Last modified by zhaozhilong: 2010-1-14
*/
#ifndef _COMMON_H_
#define _COMMON_H_
/// 当前字符是数字
#define IsDigit(c) (c >= '0' && c <= '9')
/// 当前字符是8进制数据
#define IsOctDigit(c) (c >= '0' && c <= '7')
/// 当前字符是16进制数据
#define IsHexDigit(c) (IsDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
/// 当前字符是字母或者_
#define IsLetter(c) ((c >= 'a' && c <= 'z') || (c == '_') || (c >= 'A' && c <= 'Z'))
/// 当前自负是否满足C的变量命名规则
#define IsLetterOrDigit(c) (IsLetter(c) || IsDigit(c))
#define IsIdentifier IsLetterOrDigit
/// 当前字符是空白字符
#define IsSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
/// 取出当前信息的高4位
#define HIGH_4BIT(v) ((v) >> (8 * sizeof(int) - 4) & 0x0f)
/// 取出当前信息的高3位
#define HIGH_3BIT(v) ((v) >> (8 * sizeof(int) - 3) & 0x07)
/// 取出当前信息的高1位
#define HIGH_1BIT(v) ((v) >> (8 * sizeof(int) - 1) & 0x01)
//#define ALIGN(size, align) ((size + align - 1) & (~(align - 1)))
#define BitGet(number, pos) ((number) >> (pos) & 1) /// 用宏得到某数的某位
#define BitSet(number, pos) ((number) |= 1 << (pos)) /// 把某位置1
#define BitClr(number, pos) ((number) &= ~(1 << (pos))) /// 把某位清0
#define BitCpl(number, pos) ((number) ^= 1 << (pos)) /// 把number的POS位取反
///03: 得到指定地址上的一个字节或字
#define MEM_B(x) (*((byte *)(x)))
#define MEM_W(x) (*((word *)(x)))
///04: 求最大值和最小值
#define MAX(x,y) (((x)>(y)) ? (x) : (y))
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
///05: 得到一个field在结构体(struct)中的偏移量
#define FPOS(type,field) ((dword)&((type *)0)->field)
///06: 得到一个结构体中field所占用的字节数
#define FSIZ(type,field) sizeof(((type *)0)->field)
///07: 按照LSB格式把两个字节转化为一个Word
#define FLIPW(ray) ((((word)(ray)[0]) * 256) + (ray)[1])
///08: 按照LSB格式把一个Word转化为两个字节
#define FLOPW(ray,val) (ray)[0] = ((val)/256); (ray)[1] = ((val) & 0xFF)
///09: 得到一个变量的地址(word宽度)
#define B_PTR(var) ((byte *) (void *) &(var))
#define W_PTR(var) ((word *) (void *) &(var))
///10: 得到一个字的高位和低位字节
#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))
///11: 返回一个比X大的最接近的8的倍数
#define RND8(x) ((((x) + 7)/8) * 8)
///12: 将一个字母转换为大写
#define UPCASE(c) (((c)>='a' && (c) <= 'z') ? ((c) - 0x20) : (c))
#define ToUpper(c) (c & ~0x20)
///13: 判断字符是不是10进值的数字
#define DECCHK(c) ((c)>='0' && (c)<='9')
///14: 判断字符是不是16进值的数字
#define HEXCHK(c) (((c) >= '0' && (c)<='9') ((c)>='A' && (c)<= 'F') \
((c)>='a' && (c)<='f'))
///15: 防止溢出的一个方法
#define INC_SAT(val) (val=((val)+1>(val)) ? (val)+1 : (val))
///16: 返回数组元素的个数
#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))
///17: 返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
#define MOD_BY_POWER_OF_TWO( val, mod_by ) ((dword)(val) & (dword)((mod_by)-1))
///18: 对于IO空间映射在存储空间的结构,输入输出处理
#define inp(port) (*((volatile byte *)(port)))
#define inpw(port) (*((volatile word *)(port)))
#define inpdw(port) (*((volatile dword *)(port)))
#define outp(port,val) (*((volatile byte *)(port))=((byte)(val)))
#define outpw(port, val) (*((volatile word *)(port))=((word)(val)))
#define outpdw(port, val) (*((volatile dword *)(port))=((dword)(val)))
#define DEBUG
/**
* Macros to help with debugging. Set SCULL_DEBUG to 1 enable
* debugging (which you can do from the Makefile); these macros work
* in both kernelspace and userspace.
*/
/* undef it, just in case someone else defined it. */
#ifdef dbgprint
#undef dbgprint
#endif // dbgprint
#ifdef dprint
#undef dprint
#endif // dprint
#ifdef dout
#undef dount
#endif // dout
/**when you define DEBUG macro
dbgprint to use printk with line and funcitonname in kernel
dprint to use print without line and funcitonname in kernel
dbgprint to use printf with line and funcitonname in userspace
dprint to use printf without line and funcitonname in userspace
it's the same to dbgcout and dcout in userspace
*/
#ifdef DEBUG
#ifdef __KERNEL__
#ifdef __FILE__
#ifdef __LINE__
//printk with line and function name
#define dbgprint(format, args...) \
printk(KERN_INFO "[%s, %d] : "format, __FILE__, __LINE__, ##args)
#endif // __FILE__ && __LINE__
#endif // __FILE__ && __LINE__
//printk without line and function name
#define dprint(format,args...) printk(KERN_INFO format, ##args)
#define dprintk(format,args...) printk(KERN_INFO format, ##args)
#else // userspace
#ifdef __FILE__
#ifdef __LINE__
//printf with line and function name
#define dbgprint(format, args...) \
printf("[%s,%d] : "format, __FILE__, __LINE__, ##args)
#define dbgcout std::cout <<"[" <<__FILE__ <<", " <<__LINE__ <<"] : "
#endif // __FILE__ && __LINE__
#endif // __FILE__ && __LINE__
/* Debugging is on and we are in userspace. */
#define dprint(format, args...) printf(format, ## args)
#define dprintf(format, args...) printf(format, ## args)
#define dcout cout
#endif // __KERNEL__
#else /* Not debugging: do nothing. */
#define dbgprint(format,args...)
#define dprint(format, args...)
#define dprintf(format, args...)
#define dcout 0 && cout
#endif
/* PDEBUGG is a placeholder that makes it easy to "comment out" the debugging
statements without deleting them. */
#undef undprint
#define undprint(format, args...)
#undef undcout
#define undcout 0 && count
#undef undbgprint
#define undprint(format, args...)
#undef undbgcout
#define undbgcout 0 && cout
/*
* #define DEBUG ,dbginfo() will add more debug information into nomal printk.
* #define SILENCE ,dbginfo() will print nothing.
* Otherwise ,dbginfo() equals to printk.
*/
#ifdef __FUNCTION__
#ifdef __LINE__
#ifdef DEBUG
//printk with line and function name
#define dbginfo(format,args...); \
printk(KERN_INFO"MemFI-[%s, %d] : "format, __FUNCTION__, __LINE__, ##args);
#elif defined SILENCE
#define dbginfo(format,args...);
#else //printk normally
#define dbginfo(format,args...); printk(KERN_INFO format, ##args);
#endif
#endif
#endif
/*
* safe sprintf
* It will not be out of range.
*/
#define safe_sprintf(start, n, p, format, args...); \
{ if( (p - start) < n ) { snprintf( (char *)p, (n - (p - start)), format, ##args ); } }
#endif /* _COMMON_H_ */
+21
View File
@@ -0,0 +1,21 @@
# Makefile for the memory fault injection engine.
#
# Author: HIT CS HDMC team.
# Create: 2010-3-12 8:46
# Last modified: 2010-6-13 13:55:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
obj-m := mem.o
all:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
install:
insmod memoryEngine.ko
remove:
rmmod memoryEngine
clean:
make -C /lib/modules/`uname -r`/build M=`pwd` clean
rm -f modules.order Module.symvers Module.markers
+125
View File
@@ -0,0 +1,125 @@
/*****************************************************************
文件名:mem.c
输入参数:
pid 接收待查询进程的PID
va 接收待查询的虚拟地址
*****************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/page.h>
MODULE_LICENSE("GPL");
static int pid;
static unsigned long va;
module_param(pid, int, 0644);
module_param(va, ulong, 0644);
static int find_pgd_init(void)
{
unsigned long pa = 0;
struct task_struct *pcb_tmp = NULL;
pgd_t *pgd_tmp = NULL;
pud_t *pud_tmp = NULL;
pmd_t *pmd_tmp = NULL;
pte_t *pte_tmp = NULL;
printk(KERN_INFO"PAGE_OFFSET = 0x%lx\n", PAGE_OFFSET);
printk(KERN_INFO"PGDIR_SHIFT = %d\n", PGDIR_SHIFT);
printk(KERN_INFO"PUD_SHIFT = %d\n", PUD_SHIFT);
printk(KERN_INFO"PMD_SHIFT = %d\n", PMD_SHIFT);
printk(KERN_INFO"PAGE_SHIFT = %d\n", PAGE_SHIFT);
printk(KERN_INFO"PTRS_PER_PGD = %d\n", PTRS_PER_PGD);
printk(KERN_INFO"PTRS_PER_PUD = %d\n", PTRS_PER_PUD);
printk(KERN_INFO"PTRS_PER_PMD = %d\n", PTRS_PER_PMD);
printk(KERN_INFO"PTRS_PER_PTE = %d\n", PTRS_PER_PTE);
printk(KERN_INFO"PAGE_MASK = 0x%lx\n", PAGE_MASK);
//if(!(pcb_tmp = find_task_by_vpid(pid))) linux-3.0
if(!(pcb_tmp = find_task_by_pid(pid))) // linux-2.6
{
printk(KERN_INFO"Can't find the task %d .\n", pid);
return 0;
}
printk(KERN_INFO"pgd = 0x%p\n", pcb_tmp->mm->pgd);
/* 判断给出的地址va是否合法(va&lt;vm_end)*/
if(!find_vma(pcb_tmp->mm, va))
{
printk(KERN_INFO"virt_addr 0x%lx not available.\n", va);
return 0;
}
pgd_tmp = pgd_offset(pcb_tmp->mm, va);
printk(KERN_INFO"pgd_tmp = 0x%p\n", pgd_tmp);
printk(KERN_INFO"pgd_val(*pgd_tmp) = 0x%lx\n", pgd_val(*pgd_tmp));
if(pgd_none(*pgd_tmp))
{
printk(KERN_INFO"Not mapped in pgd.\n");
return 0;
}
pud_tmp = pud_offset(pgd_tmp, va);
printk(KERN_INFO"pud_tmp = 0x%p\n", pud_tmp);
printk(KERN_INFO"pud_val(*pud_tmp) = 0x%lx\n", pud_val(*pud_tmp));
if(pud_none(*pud_tmp))
{
printk(KERN_INFO"Not mapped in pud.\n");
return 0;
}
pmd_tmp = pmd_offset(pud_tmp, va);
printk(KERN_INFO"pmd_tmp = 0x%p\n", pmd_tmp);
printk(KERN_INFO"pmd_val(*pmd_tmp) = 0x%lx\n", pmd_val(*pmd_tmp));
if(pmd_none(*pmd_tmp))
{
printk(KERN_INFO"Not mapped in pmd.\n");
return 0;
}
/*在这里,把原来的pte_offset_map()改成了pte_offset_kernel*/
pte_tmp = pte_offset_kernel(pmd_tmp, va);
printk(KERN_INFO"pte_tmp = 0x%p\n", pte_tmp);
printk(KERN_INFO"pte_val(*pte_tmp) = 0x%lx\n", pte_val(*pte_tmp));
if(pte_none(*pte_tmp))
{
printk(KERN_INFO"Not mapped in pte.\n");
return 0;
}
if(!pte_present(*pte_tmp))
{
printk(KERN_INFO"pte not in RAM.\n");
return 0;
}
pa = (pte_val(*pte_tmp) & PAGE_MASK) | (va & ~PAGE_MASK);
printk(KERN_INFO"virt_addr 0x%lx in RAM is 0x%lx .\n", va, pa);
printk(KERN_INFO"contect in 0x%lx is 0x%lx\n", pa, *(unsigned long *)((char *)pa + PAGE_OFFSET));
return 0;
}
static void find_pgd_exit(void)
{
printk(KERN_INFO"Goodbye!\n");
}
module_init(find_pgd_init);
module_exit(find_pgd_exit);
+80
View File
@@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define page_map_file "/proc/self/pagemap"
#define PFN_MASK ((((uint64_t)1)<<55)-1)
#define PFN_PRESENT_FLAG (((uint64_t)1)<<63)
int mem_addr_vir2phy(unsigned long vir, unsigned long *phy)
{
int fd;
int page_size = getpagesize();
unsigned long vir_page_idx = vir / page_size;
unsigned long pfn_item_offset = vir_page_idx * sizeof(uint64_t);
uint64_t pfn_item;
fd = open(page_map_file, O_RDONLY);
if (fd < 0)
{
printf("open %s failed", page_map_file);
return -1;
}
if ((off_t)-1 == lseek(fd, pfn_item_offset, SEEK_SET))
{
printf("lseek %s failed", page_map_file);
return -1;
}
if (sizeof(uint64_t) != read(fd, &pfn_item, sizeof(uint64_t)))
{
printf("read %s failed", page_map_file);
return -1;
}
if (0==(pfn_item & PFN_PRESENT_FLAG))
{
printf("page is not present");
return -1;
}
*phy = (pfn_item & PFN_MASK)*page_size + vir % page_size;
return 0;
}
int main(int argc, char *argv[])
{
unsigned long viraddress;
unsigned long phyaddress;
if(argc != 2)
{
printf("Usage : %s viraddress\n", argv[0]);
exit(-1);
}
sscanf(argv[1], "%d", &viraddress);
mem_addr_vir2phy(viraddress, &phyaddress);
printf("%x", phyaddress);
return EXIT_SUCCESS;
}
File diff suppressed because it is too large Load Diff
+121
View File
@@ -0,0 +1,121 @@
/*
* Author: HIT CS HDMC team.
* Create: 2010-3-12 8:20:01
* Last modified: 2010-6-13 14:13:47
*/
#ifndef _MEMORY_ENGINE_H
#define _MEMORY_ENGINE_H
/*
* common include header files
*/
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/kprobes.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/dcache.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/kallsyms.h>
#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include "common.h"
#define MAX_LINE 256 /// max length of a line
#define DELIMITER '\n' /// the char is used to split the taskinfo
#define PERMISSION 0644 /// proc node permission
/*
* return values
*/
#define OK 0
#define FAIL -1
#define PGD_NONE -2
#define PUD_NONE -3
#define PMD_NONE -4
#define PTE_NONE -5
#define PTE_NOT_PRESENT -6
/*
* request command
*/
#define REQUEST_TASK_INFO 1 /// get a task's memory map information
#define REQUEST_V2P 2 /// convert a process's linear address to physical address
#define REQUEST_KV2P 3 /// convert kernel virtual address to physical address
#define REQUEST_KFUNC_VA 4 /// get kernel function's addr(kernel virtual address)
#define REQUEST_READ_KFUNC 5 /// 请求读取内核函数起始地址内容
#define REQUEST_WRITE_KFUNC 6 /// 请求改写内核函数起始地址内容
///#define REQUEST_WRITE 10 /// 请求改写指定物理地址内容,改为用户态实现此功能
///#define REQUEST_MEM 11 /// 请求获取全部物理内存信息
///#define REQUEST_ADDR_STOP 12 ///
/*
* ack signals
*/
#define ACK_TASK_INFO REQUEST_TASK_INFO
#define ACK_V2P REQUEST_V2P
#define ACK_KV2P REQUEST_KV2P
#define ACK_KFUNC_VA REQUEST_KFUNC_VA
#define ACK_READ_KFUNC REQUEST_READ_KFUNC
#define ACK_WRITE_KFUNC REQUEST_WRITE_KFUNC
///#define REQUEST_WRITE REQUEST_WRITE
///#define ACK_MEM REQUEST_MEM
///#define ACK_ADDR_STOP REQUEST_ADDR_STOP
/*
* utility functions
*/
static int handler_pre_kFunc(struct kprobe *p, struct pt_regs *regs);
struct task_struct *findTaskByPid(pid_t pid);
long v2p(struct mm_struct *pMM,unsigned long va,int *pStatus);
long kv2p(unsigned long va,int *pStatus);
long kFunc2v(char *funcName);
struct vm_area_struct * getVMA(struct mm_struct *pMM,unsigned long va);
pte_t * getPte(struct mm_struct *pMM,unsigned long va);
int setVMAFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags);
int setPageFlags(struct mm_struct *pMM,unsigned long va,int *pStatus,int flags);
int getTaskInfo(struct task_struct *pTask, char *pData, int length);
/*
* proc entry function
*/
int proc_write_pid(struct file *file,const char __user *buffer,unsigned long count,void * data);
int proc_read_virtualAddr(char * page,char **start, off_t off, int count, int * eof,void * data);
int proc_write_virtualAddr(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_write_ctl(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_read_signal(char * page,char **start, off_t off, int count, int * eof,void * data);
int proc_write_signal(struct file *file,const char *buffer,unsigned long count,void * data);
int proc_read_pa(char * page,char **start, off_t off, int count, int * eof,void * data);
static int jforce_sig_info(int sig,struct siginfo *info,struct task_struct *t);
#endif
+5
View File
@@ -0,0 +1,5 @@
CC=gcc
INCLUDEDIR = /home/linux/include/
MODCFLAGS :=-Wall -O -DMODULE -D__KERNEL__ -DLINUX -I$(INCLUDEDIR)
map_driver.o: map_driver.c
$(CC) $(MODCFLAGS) -c map_driver.c
+216
View File
@@ -0,0 +1,216 @@
#define _VERSION__
#include <linux/kernel.h>
#include <linux/module.h>
#if CONFIG_MODVERSIOINS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
#include<linux/fs.h>
#include<linux/string.h>
#include<linux/errno.h>
#include<linux/mm.h>
#include<linux/vmalloc.h>
#include<linux/wrapper.h>
#include<linux/slab.h>
#include<asm/io.h>
#include<linux/mman.h>
#define MAPLEN (4096*10)
/* device open */
int mapdrv_open(struct inode *inode,struct file *file);
/* device close */
int mapdrv_release(struct inode *inode,struct file *file);
/*device mmap */
int mapdrv_mmap(struct file *file,struct vm_area_struct *vma);
/* vm area open */
void map_vopen(struct vm_area_struct *vma);
/* vm area close */
void map_vclose(struct vm_area_struct *vma);
/* vm area nopage */
struct page *map_nopage(struct vm_area_struct *vma,unsigned long address,int write_access);
static struct file_operations mapdrv_fops=
{
owner : THIS_MODULE,
mmap : mapdrv_mmap,
open : mapdrv_open,
release:mapdrv_release,
};
static struct vm_operations_struct map_vm_ops=
{
open : map_vopen,
close : map_vclose,
nopage: map_nopage,
};
static int *vmalloc_area = NULL;
static int major; // major number of device
volatile void *vaddr_to_kaddr(volatile void *address)
{
pgd_t *pgd; pmd_t *pmd; pte_t *ptep, pte;
unsigned long va, ret = 0UL;
va=VMALLOC_VMADDR((unsigned long)address);
/* get the page directory. Use the kernel memory map. */
pgd = pgd_offset_k(va);
/* check whether we found an entry */
if (!pgd_none(*pgd))
{
/* get the page middle directory */
pmd = pmd_offset(pgd, va);
/* check whether we found an entry */
if (!pmd_none(*pmd))
{
/* get a pointer to the page table entry */
ptep = pte_offset(pmd, va);
pte = *ptep;
/* check for a valid page */
if (pte_present(pte))
{
/* get the address the page is refering to */
ret = (unsigned long)page_address(pte_page(pte));
/* add the offset within the page to the page address */ ret |= (va & (PAGE_SIZE -1));
}
}
}
return((volatile void *)ret);
}
static int __init mapdrv_init(void)
{
unsigned long virt_addr;
if ((major=register_chrdev(0, "mapdrv", &mapdrv_fops))<0)
{
printk("mapdrv: unable to register character device\n");
return (-EIO);
}
/* get a memory area that is only virtual contigous. */
vmalloc_area=vmalloc(MAPLEN/*+2*PAGE_SIZE*/);
for (virt_addr=(unsigned long)vmalloc_area;virt_addr<(unsigned long)(&(vmalloc_area[MAPLEN/sizeof(int)]));virt_addr+=PAGE_SIZE)
{
mem_map_reserve(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
}
/* set a hello message to kernel space for read by user */
strcpy((char*)vmalloc_area,"hello world from kernel space !");
printk("vmalloc_area at 0x%p (phys 0x%lx)\n", vmalloc_area,
virt_to_phys((void *)vaddr_to_kaddr(vmalloc_area)));
return(0);
}
static void __exit mapdrv_exit(void)
{
unsigned long virt_addr;
/* unreserve all pages */
for (virt_addr=(unsigned long)vmalloc_area;virt_addr<(unsigned long)(&(vmalloc_area[MAPLEN/sizeof(int)]));virt_addr+=PAGE_SIZE)
{
mem_map_unreserve(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
}
/* and free the two areas */
if (vmalloc_area)
vfree(vmalloc_area);
/* unregister the device */
unregister_chrdev(major, "mapdrv");
return;
}
/* device open method */
int mapdrv_open(struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
return(0);
}
/* device close method */
int mapdrv_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return(0);
}
int mapdrv_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long offset = vma->vm_pgoff<<PAGE_SHIFT;
unsigned long size = vma->vm_end - vma->vm_start;
if (offset & ~PAGE_MASK)
{
printk("offset not aligned: %ld\n", offset);
return -ENXIO;
}
if (size>MAPLEN)
{
printk("size too big\n");
return(-ENXIO);
}
/* only support shared mappings.*/
if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
{
printk("writeable mappings must be shared, rejecting\n");
return(-EINVAL);
}
/* do not want to have this area swapped out, lock it */
vma->vm_flags |= VM_LOCKED;
if (offset == 0)
{
vma->vm_ops = &map_vm_ops;
/* call the open routine to increment the usage count */
map_vopen(vma);
}else
{
printk("offset out of range\n");
return -ENXIO;
}
return(0);
}
/* open handler for vm area */
void map_vopen(struct vm_area_struct *vma)
{
/* needed to prevent the unloading of the module while
somebody still has memory mapped */
MOD_INC_USE_COUNT;
}
/* close handler form vm area */
void map_vclose(struct vm_area_struct *vma)
{
MOD_DEC_USE_COUNT;
}
/* page fault handler */
struct page *map_nopage(struct vm_area_struct *vma, unsigned long address, int write_access)
{
unsigned long offset;
unsigned long virt_addr;
/* determine the offset within the vmalloc'd area */
offset = address - vma->vm_start + (vma->vm_pgoff<<PAGE_SHIFT);
/* translate the vmalloc address to kmalloc address */
virt_addr = (unsigned long)vaddr_to_kaddr(&vmalloc_area[offset/sizeof(int)]);
if (virt_addr == 0UL)
{
return((struct page *)0UL);
}
/* increment the usage count of the page */
atomic_inc(&(virt_to_page(virt_addr)->count));
printk("map_drv: page fault for offset 0x%lx (kseg x%lx)\n",offset, virt_addr);
return(virt_to_page(virt_addr));
}
module_init(mapdrv_init);
module_exit(mapdrv_exit);
+21
View File
@@ -0,0 +1,21 @@
# Makefile for the memory fault injection engine.
#
# Author: HIT CS HDMC team.
# Create: 2010-3-12 8:46
# Last modified: 2010-6-13 13:55:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
obj-m := map_driver.o
all:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
install:
insmod memoryEngine.ko
remove:
rmmod memoryEngine
clean:
make -C /lib/modules/`uname -r`/build M=`pwd` clean
rm -f modules.order Module.symvers Module.markers
+345
View File
@@ -0,0 +1,345 @@
#define _VERSION__
#include <linux/kernel.h>
#include <linux/module.h>
#if CONFIG_MODVERSIOINS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
#include<linux/fs.h>
#include<linux/string.h>
#include<linux/errno.h>
#include<linux/mm.h>
#include<linux/vmalloc.h>
//#include<linux/wrapper.h>
#include<linux/slab.h>
#include<asm/io.h>
#include<linux/mman.h>
#define MAPLEN (4096*10)
/*
* 将代码从linux2.4移植到linux2.6.*
*
* ==A==
* 2.4内核中,模块自身通过 MOD_INC_USE_COUNT, MOD_DEC_USE_COUNT宏来管理自己被使用的计数。
* 2.6内核提供了更健壮、灵活的模块计数管理接口 try_module_get(&module), module_put(&module)
* 取代2.4中的模块使用计数管理宏;模块的使用计数不必由自身管理,
* 而且在管理模块使用计数时考虑到 SMP与PREEMPT机制的影响。
*
* ==B==
* em_map_reserve是2.4的函数 而到2.6被SetPageReserved取代
* */
/* device open */
int mapdrv_open(struct inode *inode,struct file *file);
/* device close */
int mapdrv_release(struct inode *inode,struct file *file);
/*device mmap */
int mapdrv_mmap(struct file *file,struct vm_area_struct *vma);
/* vm area open */
void map_vopen(struct vm_area_struct *vma);
/* vm area close */
void map_vclose(struct vm_area_struct *vma);
/* vm area nopage */
struct page *map_nopage(struct vm_area_struct *vma,unsigned long address,int write_access);
static struct file_operations mapdrv_fops=
{
owner : THIS_MODULE,
mmap : mapdrv_mmap,
open : mapdrv_open,
release:mapdrv_release,
};
static struct vm_operations_struct map_vm_ops=
{
open : map_vopen,
close : map_vclose,
nopage: map_nopage,
};
static int *vmalloc_area = NULL;
static int major; // major number of device
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
volatile void *vaddr_to_kaddr(volatile void *address)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *ptep, pte;
unsigned long va;
unsigned long ret = 0UL;
va = VMALLOC_VMADDR((unsigned long)address);
/* get the page directory. Use the kernel memory map. */
pgd = pgd_offset_k(va);
/* check whether we found an entry */
if (pgd_none(*pgd))
{
return NULL;
}
/* get the page upper directory */
pud = pud_offset(pgd, va);
/* check whether we found an entry */
if (pud_none(*pud))
{
return NULL;
}
/* get the page middle directory */
pmd = pmd_offset(pud, va);
/* check whether we found an entry */
if (pmd_none(*pmd))
{
return NULL;
}
/* get a pointer to the page table entry */
/*ptep = pte_offset(pmd, va); implicit declaration of function pte_offset`. */
ptep = pte_offset_kernel(pmd, va);
pte = *ptep;
/* check for a valid page */
if (pte_present(pte))
{
/* get the address the page is refering to */
ret = (unsigned long)page_address(pte_page(pte));
/* add the offset within the page to the page address */
ret |= (va & (PAGE_SIZE -1));
}
return((volatile void *)ret);
}
static int __init mapdrv_init(void)
{
unsigned long virt_addr;
if ((major = register_chrdev(0, "mapdrv", &mapdrv_fops)) < 0)
{
printk("mapdrv: unable to register character device\n");
return (-EIO);
}
/* get a memory area that is only virtual contigous. */
vmalloc_area = vmalloc(MAPLEN/* + 2 * PAGE_SIZE*/);
for (virt_addr = (unsigned long)vmalloc_area;
virt_addr < (unsigned long)(&(vmalloc_area[MAPLEN / sizeof(int)]));
virt_addr += PAGE_SIZE)
{
/*
error: implicit declaration of function mem_map_reserve
`mem_map_reserve` can be found in linux-2.4, but not define in linux-2.6
you can use `SetPageReserved` instead...
#define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags)
#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags))
so the code
mem_map_reserve(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
use the next instead
SetPageReserved(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
it's the same to mem_map_unreserve
*/
SetPageReserved(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
}
/* set a hello message to kernel space for read by user */
strcpy((char*)vmalloc_area, "hello world from kernel space !");
printk("vmalloc_area at 0x%p (phys 0x%lx)\n",
vmalloc_area,
virt_to_phys((void *)vaddr_to_kaddr(vmalloc_area)));
return (0);
}
static void __exit mapdrv_exit(void)
{
unsigned long virt_addr;
/* unreserve all pages */
for (virt_addr = (unsigned long)vmalloc_area;
virt_addr < (unsigned long)(&(vmalloc_area[MAPLEN / sizeof(int)]));
virt_addr += PAGE_SIZE)
{
/*
* error: implicit declaration of function mem_map_unreserve`.
* it's the same to mem_map_reserve
so the code
mem_map_unreserve(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
use the next code instead...
ClearPageReserved(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
*/
ClearPageReserved(virt_to_page(vaddr_to_kaddr((void *)virt_addr)));
}
/* and free the two areas */
if (vmalloc_area)
{
vfree(vmalloc_area);
}
/* unregister the device */
unregister_chrdev(major, "mapdrv");
return;
}
/* device open method */
int mapdrv_open(struct inode *inode, struct file *file)
{
/*
the code in linux-2.4
MOD_INC_USE_COUNT;
use the next instead...
try_module_get(THIS_MODULE);
*/
try_module_get(THIS_MODULE);
return(0);
}
/* device close method */
int mapdrv_release(struct inode *inode, struct file *file)
{
/*
the code in linux-2.4
MOD_DEC_USE_COUNT;
use the next instead
module_put(THIS_MODULE);
*/
module_put(THIS_MODULE);
return(0);
}
int mapdrv_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long offset = vma->vm_pgoff<<PAGE_SHIFT;
unsigned long size = vma->vm_end - vma->vm_start;
if (offset & ~PAGE_MASK)
{
printk("offset not aligned: %ld\n", offset);
return -ENXIO;
}
if (size>MAPLEN)
{
printk("size too big\n");
return(-ENXIO);
}
/* only support shared mappings.*/
if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
{
printk("writeable mappings must be shared, rejecting\n");
return(-EINVAL);
}
/* do not want to have this area swapped out, lock it */
vma->vm_flags |= VM_LOCKED;
if (offset == 0)
{
vma->vm_ops = &map_vm_ops;
/* call the open routine to increment the usage count */
map_vopen(vma);
}else
{
printk("offset out of range\n");
return -ENXIO;
}
return(0);
}
/* open handler for vm area */
void map_vopen(struct vm_area_struct *vma)
{
/* needed to prevent the unloading of the module while
somebody still has memory mapped */
// MOD_INC_USE_COUNT;
/*
the code in linux-2.4
MOD_INC_USE_COUNT;
use the next instead...
try_module_get(THIS_MODULE);
*/
try_module_get(THIS_MODULE);
}
/* close handler form vm area */
void map_vclose(struct vm_area_struct *vma)
{
/*
the code in linux-2.4
MOD_DEC_USE_COUNT;
use the next instead
module_put(THIS_MODULE);
*/
module_put(THIS_MODULE);
}
/* page fault handler */
struct page *map_nopage(struct vm_area_struct *vma, unsigned long address, int write_access)
{
unsigned long offset;
unsigned long virt_addr;
/* determine the offset within the vmalloc'd area */
offset = address - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT);
/* translate the vmalloc address to kmalloc address */
virt_addr = (unsigned long)vaddr_to_kaddr(&vmalloc_area[offset / sizeof(int)]);
if (virt_addr == 0UL)
{
return((struct page *)0UL);
}
/* increment the usage count of the page */
atomic_inc(&(virt_to_page(virt_addr)->_count));
printk("map_drv: page fault for offset 0x%lx (kseg x%lx)\n",offset, virt_addr);
return(virt_to_page(virt_addr));
}
module_init(mapdrv_init);
module_exit(mapdrv_exit);
+33
View File
@@ -0,0 +1,33 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#define LEN (10*4096)
int main(void)
{
int fd;
unsigned int *vadr;
if ((fd=open("mapfile", O_RDWR))<0)
{
perror("open");
exit(-1);
}
(char *)vadr = (char*)mmap(0, LEN, PROT_READ, MAP_SHARED, fd, 0);
if (vadr == MAP_FAILED)
{
perror("mmap");
exit(-1);
}
printf("%s\n",vadr);
close(fd);
return(0);
}
+28
View File
@@ -0,0 +1,28 @@
map_driver.c
(vmalloc)
vaddress_to_kaddressvmalloc,
kmalloc
map_nopage()访VMA
test.c ok!
map_driver.cmap_driver.o,Makefile
insmod map_driver.o
1 /proc/devicesmap_drivergrep mapdrv /proc/devices
2 mknod mapfile c 254 0 254
maptestmapfile
mmap.tar Martin Frey
return(0);
http://blog.chinaunix.net/uid-24227137-id-3723898.html
+105
View File
@@ -0,0 +1,105 @@
/*****************************************************************
文件名:mem.c
输入参数:
pid 接收待查询进程的PID
va 接收待查询的虚拟地址
*****************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/page.h>
MODULE_LICENSE("GPL");
static int pid;
static unsigned long va;
module_param(pid,int,0644);
module_param(va,ulong,0644);
static int find_pgd_init(void)
{
unsigned long pa = 0;
struct task_struct *pcb_tmp = NULL;
pgd_t *pgd_tmp = NULL;
pud_t *pud_tmp = NULL;
pmd_t *pmd_tmp = NULL;
pte_t *pte_tmp = NULL;
printk(KERN_INFO"PAGE_OFFSET = 0x%lx\n",PAGE_OFFSET);
printk(KERN_INFO"PGDIR_SHIFT = %d\n",PGDIR_SHIFT);
printk(KERN_INFO"PUD_SHIFT = %d\n",PUD_SHIFT);
printk(KERN_INFO"PMD_SHIFT = %d\n",PMD_SHIFT);
printk(KERN_INFO"PAGE_SHIFT = %d\n",PAGE_SHIFT);
printk(KERN_INFO"PTRS_PER_PGD = %d\n",PTRS_PER_PGD);
printk(KERN_INFO"PTRS_PER_PUD = %d\n",PTRS_PER_PUD);
printk(KERN_INFO"PTRS_PER_PMD = %d\n",PTRS_PER_PMD);
printk(KERN_INFO"PTRS_PER_PTE = %d\n",PTRS_PER_PTE);
printk(KERN_INFO"PAGE_MASK = 0x%lx\n",PAGE_MASK);
if(!(pcb_tmp = find_task_by_pid(pid))) {
printk(KERN_INFO"Can't find the task %d .\n",pid);
return 0;
}
printk(KERN_INFO"pgd = 0x%p\n",pcb_tmp->mm->pgd);
/* 判断给出的地址va是否合法(va&lt;vm_end)*/
if(!find_vma(pcb_tmp->mm,va)){
printk(KERN_INFO"virt_addr 0x%lx not available.\n",va);
return 0;
}
pgd_tmp = pgd_offset(pcb_tmp->mm,va);
printk(KERN_INFO"pgd_tmp = 0x%p\n",pgd_tmp);
printk(KERN_INFO"pgd_val(*pgd_tmp) = 0x%lx\n",pgd_val(*pgd_tmp));
if(pgd_none(*pgd_tmp)){
printk(KERN_INFO"Not mapped in pgd.\n");
return 0;
}
pud_tmp = pud_offset(pgd_tmp,va);
printk(KERN_INFO"pud_tmp = 0x%p\n",pud_tmp);
printk(KERN_INFO"pud_val(*pud_tmp) = 0x%lx\n",pud_val(*pud_tmp));
if(pud_none(*pud_tmp)){
printk(KERN_INFO"Not mapped in pud.\n");
return 0;
}
pmd_tmp = pmd_offset(pud_tmp,va);
printk(KERN_INFO"pmd_tmp = 0x%p\n",pmd_tmp);
printk(KERN_INFO"pmd_val(*pmd_tmp) = 0x%lx\n",pmd_val(*pmd_tmp));
if(pmd_none(*pmd_tmp)){
printk(KERN_INFO"Not mapped in pmd.\n");
return 0;
}
/*在这里,把原来的pte_offset_map()改成了pte_offset_kernel*/
pte_tmp = pte_offset_kernel(pmd_tmp,va);
printk(KERN_INFO"pte_tmp = 0x%p\n",pte_tmp);
printk(KERN_INFO"pte_val(*pte_tmp) = 0x%lx\n",pte_val(*pte_tmp));
if(pte_none(*pte_tmp)){
printk(KERN_INFO"Not mapped in pte.\n");
return 0;
}
if(!pte_present(*pte_tmp)){
printk(KERN_INFO"pte not in RAM.\n");
return 0;
}
pa = (pte_val(*pte_tmp) &amp; PAGE_MASK) |(va &amp; ~PAGE_MASK);
printk(KERN_INFO"virt_addr 0x%lx in RAM is 0x%lx .\n",va,pa);
printk(KERN_INFO"contect in 0x%lx is 0x%lx\n",pa,
*(unsigned long *)((char *)pa + PAGE_OFFSET));
return 0;
}
static void find_pgd_exit(void)
{
printk(KERN_INFO"Goodbye!\n");
}
module_init(find_pgd_init);
module_exit(find_pgd_exit);
+11
View File
@@ -0,0 +1,11 @@
obj-m := list.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
+111
View File
@@ -0,0 +1,111 @@
  #include <linux /list.h>
  #include <linux /module.h>
  #include <linux/init.h>
  #include <linux/sched.h>
  #define METHOD 2
  static int list_init(void)
  {
  struct task_struct *task, *p;
  struct list_head *pos;
  int count;
  char *method;
  count = 0; /*下面这些初始化完全是为了消除编译时的警告信息*/
  p = NULL;
  task = NULL;
  pos = NULL;
  method = NULL;
  task = &init_task;
  printk(KERN_ALERT"PID/tCOMM/n");
  switch(METHOD) {
  case 1:
  method="list_for_each";
  break;
  case 2:
  method="for_each_process";
  break;
  case 3:
  method="list_for_each_entry";
  break;
  }
  printk( "The method is %s/n", method );
#if METHOD == 1
  list_for_each( pos, &task->tasks ) {
  p = list_entry( pos, struct task_struct, tasks );
  count++;
  printk( KERN_ALERT "%d/t%s/n", p->pid, p->comm );
  }
#elif METHOD == 2
  for_each_process(task) {
  count++;
  printk( KERN_ALERT "%d/t%s/n", task->pid, task->comm );
  }
#elif METHOD == 3
   list_for_each_entry( p, &task->tasks, tasks ) {
   count++;
printk( KERN_ALERT "%d/t%s/n", p->pid, p->comm );
}
#endif
 printk("系统当前共 %d 个进程!!", count);
return 0;
}
static void list_exit(void)
{
printk( KERN_ALERT "GOOD BYE!!/n");
}
module_init( list_init );
module_exit( list_exit );
MODULE_AUTHOR( "Along" );
MODULE_LICENSE( "GPL" );
+14
View File
@@ -0,0 +1,14 @@
obj-m := mem_dev.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
+58
View File
@@ -0,0 +1,58 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#define DEVKMEM "/dev/kmem"
#define PAGE_SIZE 0x1000
#define PAGE_MASK (~(PAGE_SIZE-1))
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("usage...");
exit(-1);
}
int fd;
char *mbase;
char read_buf[10];
unsigned int regAddr;
unsigned int varAddr;
varAddr = strtoul(argv[1], 0, 16);
unsigned int ptr = varAddr & ~(PAGE_MASK);
fd = open(DEVKMEM, O_RDONLY);
if (fd == -1)
{
printf("%s %d", __func__, __LINE__);
perror("open");
exit(-1);
}
mbase = (char *)mmap(0, PAGE_SIZE, PROT_READ, MAP_SHARED,fd, (varAddr & PAGE_MASK));
if (mbase == MAP_FAILED)
{
printf("map failed %s\n",strerror(errno));
}
printf("varAddr = 0x%X \n", varAddr);
printf("mapbase = 0x%X \n", (unsigned int)mbase);
printf("value = 0x%X \n",*(unsigned int*)(mbase+ptr));
printf("char = %c%c%c%c \n",
*(char *)(mbase+ptr), *(char *)(mbase+ptr+1),
*(char *)(mbase+ptr+2), *(char *)(mbase+ptr+3));
close(fd);
munmap(mbase,PAGE_SIZE);
return 0;
}
+132
View File
@@ -0,0 +1,132 @@
/*
* devmem2.c: Simple program to read/write from/to any location in memory.
*
* Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
*
*
* This software has been developed for the LART computing board
* (http://www.lart.tudelft.nl/). The development has been sponsored by
* the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/)
* and Ubiquitous Communications (http://www.ubicom.tudelft.nl/)
* projects.
*
* The author can be reached at:
*
* Jan-Derk Bakker
* Information and Communication Theory Group
* Faculty of Information Technology and Systems
* Delft University of Technology
* P.O. Box 5031
* 2600 GA Delft
* The Netherlands
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
int main(int argc, char **argv) {
int fd;
void *map_base, *virt_addr;
unsigned long read_result, writeval;
off_t target;
int access_type = 'w';
if(argc < 2) {
fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
"\taddress : memory address to act upon\n"
"\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n"
"\tdata : data to be written\n\n",
argv[0]);
exit(1);
}
target = strtoul(argv[1], 0, 0);
if(argc > 2)
access_type = tolower(argv[2][0]);
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
printf("/dev/mem opened.\n");
fflush(stdout);
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
if(map_base == (void *) -1) FATAL;
printf("Memory mapped at address %p.\n", map_base);
fflush(stdout);
virt_addr = map_base + (target & MAP_MASK);
switch(access_type) {
case 'b':
read_result = *((unsigned char *) virt_addr);
break;
case 'h':
read_result = *((unsigned short *) virt_addr);
break;
case 'w':
read_result = *((unsigned long *) virt_addr);
break;
default:
fprintf(stderr, "Illegal data type '%c'.\n", access_type);
exit(2);
}
printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
fflush(stdout);
if(argc > 3)
{
writeval = strtoul(argv[3], 0, 0);
switch(access_type) {
case 'b':
*((unsigned char *) virt_addr) = writeval;
read_result = *((unsigned char *) virt_addr);
break;
case 'h':
*((unsigned short *) virt_addr) = writeval;
read_result = *((unsigned short *) virt_addr);
break;
case 'w':
*((unsigned long *) virt_addr) = writeval;
read_result = *((unsigned long *) virt_addr);
break;
}
printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
fflush(stdout);
}
if(munmap(map_base, MAP_SIZE) == -1) FATAL;
close(fd);
return 0;
}
+140
View File
@@ -0,0 +1,140 @@
/*
* getjiff.c
*
* this toolkit shows how to get jiffies value from user space:
* 1. find jiffies's address from kernel image.
* 2. access virtual address space to get jiffies value.
* 3. access physical address sapce to get jiffies value.
*
* demostrate following techniques:
* o get ELF object symbol address by calling nlist()
* o access virtual memory space from /dev/kmem
* o access virtual memory space from /dev/mem
*/
#include <stdio.h>
#include <stdlib.h> //exit
#include <linux/a.out.h> //nlist
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <memory.h>
#define LONG *(volatile unsigned long*)
/* read from virtual memory */
int read_kmem(off_t offset, void* buf, size_t count)
{
int fd;
int n;
fd = open("/dev/kmem", O_RDONLY);
if (fd < 0)
{
perror("open /dev/kmem failed");
return -1;
}
lseek(fd, offset, SEEK_SET);
n = read(fd, buf, count);
if (n != count)
perror("/dev/kmem read failed");
else
printf("/dev/kmem read buf = %ld\n", *(unsigned long *)buf);
close(fd);
return n;
}
/* read from physical memory */
int read_mem(off_t offset, void* buf, size_t count)
{
int fd;
int n;
int page_size;
void *map_base;
unsigned long value;
printf("/dev/mem: the offset is %lx\n", offset);
fd = open("/dev/mem", O_RDONLY);
if (fd < 0)
{
perror("open /dev/mem failed");
return -1;
}
if(1){
page_size = getpagesize();
printf("the page size = %d\n", page_size);
map_base = mmap(0,page_size,PROT_READ,MAP_SHARED,fd,offset);
if (map_base == MAP_FAILED){
perror("mmap");
exit(1);
}
value = LONG(map_base);
printf("/dev/mem: the value is %ld\n", value);
buf = (unsigned long *)map_base;
}
if(0){
lseek(fd, offset, SEEK_SET);
n = read(fd, buf, count);
if (n != count)
perror("/dev/mem read failed");
else
printf("/dev/mem read buf = %ld\n", *(unsigned long *)buf);
}
close(fd);
return n;
}
int main(int argc, char **argv)
{
FILE *fp;
char addr_str[11]="0x";
char var[51];
unsigned long addr;
unsigned long jiffies;
char ch;
int r;
if (argc != 2) {
fprintf(stderr,"usage: %s System.map\n",argv[0]);
exit(-1);
}
if ((fp = fopen(argv[1],"r")) == NULL) {
perror("fopen");
exit(-1);
}
do {
r = fscanf(fp,"%8s %c %50s\n",&addr_str[2],&ch,var); // format of System.map
if (strcmp(var,"jiffies")==0)
break;
} while(r > 0);
if (r < 0) {
printf("could not find jiffies\n");
exit(-1);
}
addr = strtoul(addr_str,NULL,16); //Convert string to unsigned long integer
printf("found jiffies at (%s) %08lx\n",addr_str,addr);
read_kmem(addr, &jiffies, sizeof(jiffies));
printf("jiffies=%ld (read from virtual memory)\n\n", jiffies);
jiffies = 0; //reinit for checking read_mem() below
read_mem(addr-0xC0000000, &jiffies, sizeof(jiffies));
printf("jiffies=%ld (read from physical memory)\n", jiffies);
return 0;
}
+73
View File
@@ -0,0 +1,73 @@
/*************************************************************************
> File Name: process.c
> Author: GatieMe
> Mail: gatieme@163.com
> Created Time: 2016年04月01日 星期五 21时09分29秒
************************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
//#define METHOD 2
static unsigned int METHOD = 1;
module_param(METHOD, uint,0400);
long readPhysicsAddress(unsigned long pa, int *pStatus);
long writePhysicsAddress(unsigned long pa, unsigned long data, int *pStatus);
static int mem_dev_init(void)
{
readPhysicsAddress(0x12345, NULL);
return 0;
}
static void mem_dev_exit(void)
{
printk( KERN_ALERT "GOOD BYE!!\n");
}
/** add by gatieme */
/*
*
*/
long readPhysicsAddress(unsigned long pa, int *pStatus)
{
long data = -1;
//long *point = (long *)pa;
data = *(long *)pa;
printk(KERN_INFO "physics address : 0x%lx, data : 0x%lx", pa, data);
return data;
}
long writePhysicsAddress(unsigned long pa, unsigned long data, int *pStatus)
{
long oldData = -1;
oldData = *(long *)pa;
printk(KERN_INFO "physics address : 0x%lx, old data : 0x%lx", pa, *(long *)pa);
*(long *)pa = data;
printk(KERN_INFO "physics address : 0x%lx, new data : 0x%lx", pa, *(long *)pa);
return oldData;
}
module_init(mem_dev_init);
module_exit(mem_dev_exit);
MODULE_AUTHOR("gatieme");
MODULE_LICENSE("GPL");