Hi, I need some help here to understand copy_to_user(). I encountered a strange copy_to_user() behavior when working on CentOS from Redhat (kernel version 2.6.9-22.ELsmp, x86_64 CPU).
For a kernel module, I wrote a ioctl call to allow user mode program to get some kernel data information. When a user program called the ioctl, most of the time the ioctl failed with EFAULT, failed at copy_to_user(). It succeeded a few times after a lot of running. Failed message indicated copy_to_user() returned 3840 (which is exactly what is asked to copy, PAGE_SIZE-256). The printed value of the user pointer were identical for successful ioctl calls and failed ioctl calls. Some relevant details are at the end of this email. I tried with calloc(PAGE_SIZE, 1), static buffer and automatic variable on stack in user mode program. They gave the same result. I appreciate any help. Best, Jasper The ioctl call structure is defined as follows, struct ioctl_get_info { ... /* some other information */ unsigned long user_pointer; unsigned user_buffer_len; unsigned returned_len; ... /* some other information */ }; Inside kernel module, a page is allocated with : static unsigned char *test_page; static init_test(void) { test_page = __get_free_pages(GFP_KERNEL, 0); if (!test_page) .... /* some error handling */ } static int test_ioctl(struct inode * inode, struct file * filp, unsigned int cmd_in, unsigned long arg) { struct ioctl_get_info igi; unsigned size; unsigned long remain; size = IOC_SIZE(cmd_in); if (size != sizeof(igi)) .... ... /* some sanity checking */ if (!access_ok(VERIFY_READ, (char *)arg, size)) { printk(KERN_INFO "..."); return -EFAULT; } if (copy_from_user(&igi, (char *)arg, size) != 0) { printk(... ...) return -EFAULT; } if (!access_ok(VERIFY_WRITE, (char *)igi.user_pointer, igi.user_buffer_len)) { printk(...); return -EFAULT; } size = PAGE_SIZE - 256; if (size > igi.user_buffer_len) size = igi.user_buffer_len; printk("igi.user_pointer %p size %u\n", igi.user_pointer, size); if ((remain = copy_to_user((char *)igi.user_pointer, page + 256, size)) != 0) { printk ("Failed to copy from user at %p remain %lu asked %u\n", igi.user_pointer, remain, asked); /* failed here */ return -EFAULT; } igi.returned_len = size; /* copy other information */ return 0; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/