Hi, Here is a simple kernel module, that prints the arguments of a particular task. // Print task's arguments, Linux Kernel 2.6.12.2. // // A simple kernel module that prints the arguments of a given task. // After successfull execve(), the arguments (together with the environment) // reside in user space memory. There is no kernel data structure that // provides direct access to task's arguments. This fact can be observed // from how do_execve() and proc_pid_cmdline() work. // // The do_execve() first copies the arguments and environment into // kernel space. Looking at the source code reveals that bprm variable // holds the copied data and it is freed later. // // The proc_pid_cmdline() shows how to access the relevant data from // user space pages. It uses the access_process_vm() to do this. // Since this function is not exported, the get_user_pages() is used instead. // // This kernel module implements a simple character device with file operations // open(), release() and read(). The read() method prints the task's arguments. // // I hope the code is correct. It is essentially a copy-paste-edit // of access_process_vm(). // // # mknod args c 253 0 // # cat args a b c d e f // # dmesg // #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/binfmts.h> #include <linux/highmem.h> #include <linux/pagemap.h> #define FIRST_MINOR 0 #define MINOR_COUNT 1 #define DEVICE_NAME "args" static dev_t device_number; static struct cdev device; static int open_fop(struct inode *, struct file *); static int release_fop(struct inode *, struct file *); static ssize_t read_fop(struct file *file, char __user *buf, size_t size, loff_t *off); static struct file_operations fops= { owner:THIS_MODULE, open:open_fop, release:release_fop, read:read_fop, }; static void print_args(struct task_struct *task); static int __init init(void) { int ret; if((ret=alloc_chrdev_region(&device_number, FIRST_MINOR, MINOR_COUNT, DEVICE_NAME))<0) goto out; cdev_init(&device, &fops); if((ret=cdev_add(&device, device_number, MINOR_COUNT))<0){ unregister_chrdev_region(device_number, MINOR_COUNT); goto out; } out: return ret; } static void __exit exit(void) { cdev_del(&device); unregister_chrdev_region(device_number, MINOR_COUNT); } module_init(init); module_exit(exit); MODULE_LICENSE("GPL"); static int open_fop(struct inode *inode, struct file *file) { try_module_get(THIS_MODULE); return 0; } static int release_fop(struct inode *inode, struct file *file) { module_put(THIS_MODULE); return 0; } static ssize_t read_fop(struct file *file, char __user *buf, size_t size, loff_t *off) { print_args(current); return 0; } #define NEWLINE '\n' #define NULLCHAR 0 #define GUP_LEN 1 #define GUP_WRITE 0 #define GUP_FORCE 1 static void print_args(struct task_struct *task) { struct mm_struct *mm=task->mm; struct page *page=0; struct vm_area_struct *vma=0; char *addr=0; int offset=0; int bytes=0; int i=0; // The task's arguments lie in the user space // virtual memory range <mm->arg_start, mm->arg_end). // Therefore the total size of task's arguments is the following. int args_size=mm->arg_end-mm->arg_start; int start=mm->arg_start; struct page *tmp_page=0; char *tmp_addr=0; tmp_page=alloc_page(GFP_HIGHUSER); tmp_addr=kmap(tmp_page); down_read(&mm->mmap_sem); // The arguments are printed page by page. // Every cycle prints the contents of one page. while(args_size){ // Make the user space page available in kernel space. // The get_user_pages() creates shared mapping (not a copy // of the user space contents). if(get_user_pages(task, mm, start, GUP_LEN, GUP_WRITE, GUP_FORCE, &page, &vma)<=0) goto out; addr=kmap(page); // Here, the task's arguments are available in kernel space memory. // Note that the mm->arg_start does not have to be page-aligned, // therefore the arguments can start in the middle of the page // (not just at the beginning). offset=start&(PAGE_SIZE-1); bytes=PAGE_SIZE-offset; if(args_size<bytes) bytes=args_size; // Every null-character is substituted for newline for the // purpose of pretty-printing. Because the get_user_pages // creates shared mapping, the contents are first copied // to temporary storage. memcpy(tmp_addr, addr, PAGE_SIZE); for(i=offset; i<PAGE_SIZE; ++i) if(tmp_addr[i]==NULLCHAR) tmp_addr[i]=NEWLINE; // The printing is not very precise. A single argument can // overlap two consecutive pages. In that case, its print // is interrupted by a newline. printk(KERN_NOTICE "%.*s\n", bytes, tmp_addr+offset); kunmap(page); page_cache_release(page); args_size-=bytes; start+=bytes; } out: up_read(&mm->mmap_sem); kunmap(tmp_page); __free_page(tmp_page); } BlackHole -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ