【问题标题】:Linux kernel syscall return not given pointerLinux内核系统调用返回未给定的指针
【发布时间】:2014-11-22 13:10:40
【问题描述】:

我正在尝试实现一个新的系统调用作为实验,但我总是遇到段错误。我认为问题在于我尝试返回一个指向不在用户空间中的 char 数组的指针。 我尝试通过使用 GFP_USER 作为 kmalloc 的标志来分配用户空间中的内存,但问题仍然存在。

这就是我调用系统调用的方式,目前我无法更改它(通常会为返回分配内存并将其作为参数提供):

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

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

}

syscall函数的定义如下:

#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。

有人知道出了什么问题吗?

【问题讨论】:

    标签: c memory-management linux-kernel userspace


    【解决方案1】:

    副本的目标应该是用户空间指针,而指针ret 在内核空间中。您应该从用户那里提供目标指针作为参数。例如:

    【讨论】:

    • 确实如此。很好的发现 :) 那来自于尝试了很多。但不幸的是,段错误仍然存​​在。我现在更正了问题中的代码。
    • 好的,也编辑了答案
    • 完全正确,但我要求不要修改系统调用定义。所以我尝试代表用户分配内存。
    • 你能用指针变量调用函数,让输入作为输出(char *input_p = "input"; mycall(input_p))吗?
    • 这将是一个替代方案,但不幸的是,这在此设置中也是不可能的-.-
    【解决方案2】:

    您应该在调用 strlen() 之前执行 copy_from_user。通常,系统调用会获得一个额外的参数,其中包含传递的参数长度。

    例如; mysyscall(str,strlen)

    【讨论】:

      猜你喜欢
      • 2013-09-30
      • 2010-09-20
      • 2012-02-11
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      • 2011-01-07
      • 2018-09-15
      相关资源
      最近更新 更多