2014-11-22 95 views
0

我想实现一个新的系统调用作为一个实验,但我总是得到一个段错误。我认为问题在于我试图返回一个指向不在用户空间中的char数组的指针。 我试图通过使用GFP_USER作为kmalloc的标志来分配用户空间中的内存,但问题依然如此。Linux内核系统调用返回没有给出的指针

这是我打电话给我的系统调用,我不能在此刻改变它(通常会要求退货分配内存,并提供它作为参数):

#include <errno.h> 
#include <linux/unistd.h> 
#include <linux/mysyscall.h> 

main() { 
    printf("Returned: %s\n", mycall("user string arg")); 

} 

系统调用函数的定义看起来像这样的:

#include <linux/mysyscall.h> 
#include <linux/kernel.h> 
#include <linux/unistd.h> 
#include <linux/slab.h> 
#include <asm/uaccess.h> 

asmlinkage char* sys_mycall (char * str_in) { 
    int size = 0; 

    printk(KERN_INFO "Starting mycall.\n"); 
    size = strnlen_user(str_in, 255); 
    printk(KERN_INFO "size = %d\n", size); 
    char str[size]; 
    char *ret; 
    ret = kmalloc(size, GFP_ATOMIC | GFP_USER); 

    if(str != NULL){ 
     copy_from_user(str, str_in, size); 
     printk(KERN_INFO "Copied string.\n"); 
    }else{ 
     printk(KERN_ERR "str is NULL!!!\n"); 
     return -EFAULT; 
    } 

    // Doing operations on str 

    int acc = access_ok(VERIFY_WRITE, ret, size); 
    if(acc){ 
     printk(KERN_ERR "Not accessible!\n"); 
     return -EFAULT; 
    } 

    int len = copy_to_user(ret, str, size); 
    if(len){ 
     printk(KERN_ERR "Could not copy! len = %d\n", len); 
     return -EFAULT; 
    } 

    return ret; 
} 

我测试了很多,我敢肯定,系统调用正确调用,但它与copy_to_user问题。 copy_to_user总是返回一个正值(等于大小,所以根本不复制)。
顺便说一句ret的地址就像f74ce400和str_in 080484ac。

有没有人有一个想法是什么错?

回答

1

副本的目标应该是用户空间指针,而指针ret位于内核空间中。您应该将用户提供的目标指针作为参数提供。例如见:

+0

确实如此。尼斯发现:)这是来自尝试很多。但不幸的是,segfault仍然存在。我现在纠正了我的代码。 – Thorben 2014-11-22 13:50:52

+0

好的,编辑好的答案 – 2014-11-22 14:04:18

+0

这是完全正确的,但这是我不要修改系统调用定义的要求。所以我尝试代表用户分配内存。 – Thorben 2014-11-22 14:06:21

0

你应该做之前调用copy_from_user,调用函数strlen()。通常系统调用通过传递参数的长度来获得额外的参数。

对于ex; mysyscall(str,strlen)