Hi all, can we write directly to user virtual address from kernel space? i.e. dereferencing a user address from driver entry point? I am attaching my sample driver code with user application. I tried to run this on RHEL4-U2. it is running fine. But on FC3, its not working giving segmentation fault in user space. The kernel messeges are:- Mydevice: open Mydevice: ioctl: GET_SIZE<1>Unable to handle kernel paging request at virtual address fefd53a0 printing eip: 1282319d *pde = 00000000 Oops: 0002 [#1] Modules linked in: driver1(U) parport_pc lp parport autofs4 i2c_dev i2c_core sunrpc md5 ipv6 dm_mod uhci_hcd snd_cs46xx snd_rawmidi snd_seq_device snd_ac97_codec snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd soundcore snd_page_alloc gameport 3c59x floppy ext3 jbd aic7xxx sd_mod scsi_mod CPU: 0 EIP: 0060:[<1282319d>] Not tainted VLI EFLAGS: 00010246 (2.6.9-1.667) EIP is at my_ioctl+0x67/0x72 [driver1] eax: 0000001a ebx: fefd53a0 ecx: 128232aa edx: 090e2f90 esi: 80047a03 edi: 0a17bca0 ebp: ffffffe7 esp: 090e2f8c ds: 007b es: 007b ss: 0068 Process a.out (pid: 3027, threadinfo=090e2000 task=0916d770) Stack: 128232aa 12823960 0217a147 fefd53a0 0881c2e4 0a17bca0 00000003 090e2fc0 00000004 090e2fc4 fefd5434 fefd53c0 090e2000 ffff4200 00000003 80047a03 fefd53a0 fefd5434 fefd53c0 fefd53a8 00000036 0000007b 0000007b 00000036 Call Trace: [<0217a147>] sys_ioctl+0x296/0x337 Code: <3>Debug: sleeping function called from invalid context at include/linux/rwsem.h:43 in_atomic():0[expected: 0], irqs_disabled():1 [<0211c8b9>] __might_sleep+0x7d/0x88 [<0215e27e>] rw_vm+0x216/0x482 [<12823172>] my_ioctl+0x3c/0x72 [driver1] [<12823172>] my_ioctl+0x3c/0x72 [driver1] [<0215e9d0>] get_user_size+0x30/0x57 [<12823172>] my_ioctl+0x3c/0x72 [driver1] [<0210682b>] show_registers+0x109/0x15e [<02106a2f>] die+0x14a/0x241 [<0211937e>] do_page_fault+0x0/0x511 [<0211937e>] do_page_fault+0x0/0x511 [<02119733>] do_page_fault+0x3b5/0x511 [<1282319d>] my_ioctl+0x67/0x72 [driver1] [<02153c78>] handle_mm_fault+0xe4/0x21e [<0211953a>] do_page_fault+0x1bc/0x511 [<0222b4fe>] vt_console_print+0x64/0x2a3 [<0222b4fe>] vt_console_print+0x64/0x2a3 [<0222b49a>] vt_console_print+0x0/0x2a3 [<0211937e>] do_page_fault+0x0/0x511 [<1282319d>] my_ioctl+0x67/0x72 [driver1] [<0217a147>] sys_ioctl+0x296/0x337 Bad EIP value. help me out. thanks in advance.
#include<linux/module.h> #include<linux/kernel.h> #include<linux/fs.h> #include<linux/init.h> #include<asm/uaccess.h> #define MAGIC 'z' #define GET_DATA _IOR(MAGIC, 1, int *) #define SET_DATA _IOW(MAGIC, 2, int *) #define GET_SIZE _IOR(MAGIC, 3, int *) struct file_operations fops; static char array[80] = "HelloWorld"; static int major; int Mydevice_init_module(void) { printk("In init module"); major = register_chrdev(0,"Mydevice",&fops); printk("\nThe device is registered by Major no: %d",major); if(major == -1) printk("\nError in registering the module"); else printk("\n"); return 0; } void Mydevice_cleanup_module(void) { unregister_chrdev(major,"Mydevice"); printk("In cleanup module"); } static int my_open(struct inode *inode, struct file *file) { printk("\nMydevice: open"); return 0; } static int my_release(struct inode *inode, struct file *file) { printk("\nMydevide: release"); return 0; } static ssize_t my_read(struct file *file, char *buff, size_t n,loff_t *offset) { int position = (long)*offset; printk("\nMydevice: read"); copy_to_user(buff,array+position,n); return 0; } static ssize_t my_write(struct file *file, const char *buff, size_t n, loff_t *offset) { int position = (long)*offset; printk("\nMydevice: write"); copy_from_user(array+position,buff,n); return 0; } static loff_t my_lseek(struct file *file,loff_t offset,int whence) { printk("\nMydevice: lseek"); switch(whence) { case 0: file->f_pos = offset; //SEEK_SET break; case 1: file->f_pos = (file->f_pos) + offset; //SEEK_CUR break; case 2: file->f_pos = sizeof(array) - offset; //SEEK_END break; } return file->f_pos; } static int my_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case GET_DATA: printk("\nMydevice: ioctl: GET_DATA"); copy_to_user((char *)arg, array, 80); break; case SET_DATA: printk("\nMydevice: ioctl: SET_DATA"); copy_from_user(array, (char *)arg, 80); break; case GET_SIZE: printk("\nMydevice: ioctl: GET_SIZE"); *(int *) arg = sizeof(array); break; } return 0; } struct file_operations fops = { open: my_open, release: my_release, read: my_read, write: my_write, llseek: my_lseek, ioctl: my_ioctl, }; module_init(Mydevice_init_module); module_exit(Mydevice_cleanup_module); MODULE_LICENSE("GPL");
#include<stdio.h> #include<fcntl.h> #include<unistd.h> #include<string.h> #include<sys/ioctl.h> #include"myioctl.h" int main(void) { int fd,size; int result; fd = open("mydevice",O_RDWR); if(fd == -1) { printf("\nError in open"); return -1; } result = ioctl(fd, GET_SIZE, &size); if(result == -1) { printf("\nError in ioctl"); return -1; } printf("\nThe result of GET_SIZE: %d",size); printf("\n"); }
#define MAGIC 'z' #define GET_DATA _IOR(MAGIC, 1, int *) #define SET_DATA _IOW(MAGIC, 2, int *) #define GET_SIZE _IOR(MAGIC, 3, int *)
Attachment:
Makefile
Description: Binary data
- Follow-Ups:
- Re: referring a user address from ioctl entry point
- From: Arjan van de Ven <[email protected]>
- Re: referring a user address from ioctl entry point
- Prev by Date: Re: interactive task starvation
- Next by Date: Re: interactive task starvation
- Previous by thread: [PATCH] SELinux - add slab cache for inode security struct
- Next by thread: Re: referring a user address from ioctl entry point
- Index(es):