c - 如何在 Linux 内核中为 char* 类型的字符串分配内存?

标签 c memory linux-kernel

我正在尝试为 char* 分配一些内存,如下所示。

static ssize_t memo_write(struct file *filp, const char __user *buf, 
   size_t count, loff_t *f_pos){
    ssize_t retval = -ENOMEM;
    printk("write function\n");

    if((data = kmalloc(strlen(buf), GFP_KERNEL)) == NULL)
        printk("kmalloc fail\n");

    if(copy_from_user(data, buf, strlen(buf))){
        retval = -EFAULT;
        goto out;
    }
    *f_pos += strlen(buf);
    retval = strlen(buf);

    out:
        return retval;
}

“数据”在头文件中声明为

char *data;

当我调用 write 函数时,没有到达 'kmalloc fail' 行,这让我相信 kmalloc 成功了,但是当我再次尝试从 'data' 变量中读取数据时没有显示数据。

更令人困惑的是,如果我完全摆脱 kmalloc 位,则可以从驱动程序中读取数据。虽然问题是紧随其后的是大量其他数据,因为我没有机会 memset() 它。

我是否正确使用 kmalloc?大概不会。我该怎么做?

另外,我的读取函数如下。

static ssize_t memo_read(struct file *f, char __user *buf, 
    size_t count, loff_t *f_pos){
    ssize_t retval = 0;

    printk("read function\n");
    printk("data = %s\n", data);

    if(*f_pos >= strlen(data)){
        printk("EOF\n");
        goto out;
    }

    if(copy_to_user(buf, data, strlen(data))){
        retval = -EFAULT;
        goto out;
    }
    printk("copy_to_user success\n");
    *f_pos += strlen(data);
    retval = strlen(data);
    out:
        return retval;
}

谢谢。

最佳答案

你应该在用户空间指针上使用 strlen_user(),而不是 strlen() - 你应该只调用一次,并保留结果(否则,您有潜在的内核漏洞,因为第二个用户空间线程可能会在您处理缓冲区时更改缓冲区)。

或者,您可以使用 strncpy_from_user()

除此之外,kmalloc 看起来还不错。


(但实际上,正如 ephemient 所说,您应该重新考虑整个方法并使用 count 参数而不是将输入视为字符串)。


由于您不能将写入文件的数据依赖为以 nul 结尾的字符串,因此您需要在 data 旁边保留一个 data_len 长度参数.那么您的 read/write 实现将遵循以下原则:

static char *data = NULL;
static size_t data_len;
static DEFINE_MUTEX(data_mutex);

static ssize_t memo_read(struct file *f, char __user *buf, size_t count, loff_t *f_pos
{
    ssize_t retval = 0;
    char *start;

    mutex_lock(&data_mutex);

    if (!data)
    {
        retval = -EINVAL; /* Or whatever you want to do here... */
        goto out;
    }

    if (*f_pos >= data_len)
        goto out; /* EOF */

    start = data + *f_pos;
    retval = data_len - *f_pos;

    if (retval > count)
        retval = count;

    if (copy_to_user(buf, start, retval))
    {
        retval = -EFAULT;
        goto out;
    }

    *f_pos += retval;

out:
    mutex_unlock(&data_mutex);
    return retval;
}

static ssize_t memo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    ssize_t retval = -ENOMEM;

    mutex_lock(&data_mutex);

    if (data)
        kfree(data);

    data = kmalloc(count, GFP_KERNEL);

    if (!data)
        goto out;

    if (copy_from_user(data, buf, count))
    {
        kfree(data);
        retval = -EFAULT;
        goto out;
    }

    *f_pos = count;
    retval = count;
    data_len = count;

out:
    mutex_unlock(&data_mutex);
    return retval;
}

关于c - 如何在 Linux 内核中为 char* 类型的字符串分配内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2099070/

相关文章:

c - 处理 QEMU 设备中配置空间的 PCI 读/写

c - printf 字段宽度 : bytes or chars?

c - 矩阵乘法动态分配矩阵错误: segmentation fault (core dump)

c - 将指针分配给列表中的下一个节点

linux - "Unknown symbol in module"在模块插入时尽管有 EXPORT_SYMBOL

c - 如何编写一个内核模块来查找内核中的路由表和arp缓存?

c - 归并排序中的逻辑错误

performance - 我应该养成删除 R 中未使用的变量的习惯吗?

c++ - Xeon 每次内存访问会将多少字节带入缓存?

memory - 如何基准测试函数的内存使用情况?