本文所涉及的代码均为linux kernel v2.6.31
在分析csaw 2010 pwn
创建proc文件
linux利用create_proc_entry()函数实现proc文件的创建,函数包含三个参数:
函数原型*create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
- name :表示文件的名字
- mode :文件的一些属性,默认是0755
- parent:表示文件的父目录,没有的话就是null
create_proc_entry函数的返回值
create_proc_entry函数的返回值是一个结构体
struct proc_dir_entry {
unsigned int low_ino;
unsigned short namelen;
const char *name;
mode_t mode;
nlink_t nlink;
uid_t uid;
gid_t gid;
loff_t size;
const struct inode_operations *proc_iops;
/*
* NULL ->proc_fops means "PDE is going away RSN" or
* "PDE is just created". In either case, e.g. ->read_proc won't be
* called because it's too late or too early, respectively.
*
* If you're allocating ->proc_fops dynamically, save a pointer
* somewhere.
*/
const struct file_operations *proc_fops;
struct proc_dir_entry *next, *parent, *subdir;
void *data;
read_proc_t *read_proc;
write_proc_t *write_proc;
atomic_t count; /* use count */
int pde_users; /* number of callers into module in progress */
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
struct completion *pde_unload_completion;
struct list_head pde_openers; /* who did ->open, but not ->release */
};
里面包含了对这个文件进行读写所需要的函数:read_proc_t read_proc;write_proc_t write_proc;
这两个函数也是用户空间与内核空间进行数据交换的重点
read_proc
函数原型
typedef int (read_proc_t)(char *page, char **start, off_t off,
int count, int *eof, void *data);
参数分析
- page: 在对proc文件进行读操作时,内核首先会分配一个页大小的缓冲区。
- start : 当start参数没设置时:off参数起作用,表示文件指针偏移;当设置start以后,off参数不再起作用
- off : 表示一段偏移,它可以通过lseek函数更改
- count : 读取的个数
- eof : 当eof=1时,随时可以在page中取出数据;当eof=0时,只有page填满数据时才能取出。
write_proc
typedef int (write_proc_t)(struct file *file, const char __user *buffer,
unsigned long count, void *data);