gpt4 book ai didi

copy_to_user 一个包含数组(指针)的结构

转载 作者:IT王子 更新时间:2023-10-29 01:19:29 24 4
gpt4 key购买 nike

披露:我是 C 的新手。如果您能详细解释任何答案,我将不胜感激。

我正在编写一个 linux 内核模块,在我正在编写的其中一个函数中,我需要将一个结构复制到用户空间,如下所示:

typedef struct
{
uint32_t someProperty;
uint32_t numOfFruits;
uint32_t *arrayOfFruits;
} ObjectCapabilities;

我正在实现的 API 的文档将 arrayOfFruits 成员描述为“一个大小为 numOfFruits 的数组,其中每个元素都是一个 FRUIT_TYPE 常量”。鉴于 arrayOfFruits 是一个指针,我很困惑如何做到这一点。当我copy_to_user ObjectCapabilities 结构时,它只会将指针 arrayOfFruits 复制到用户空间。

用户空间如何连续访问数组的元素?这是我的尝试:

ObjectCapabilities caps;
caps.someProperty = 1024;
caps.numOfFruits = 3;
uint32_t localArray[] = {
FRUIT_TYPE_APPLE,
FRUIT_TYPE_ORANGE,
FRUIT_TYPE_BANANA
};
caps.arrayOfFruits = localArray;

然后对于副本...我可以这样做吗?

copy_to_user((void *)destination, &caps, (sizeof(caps) + (sizeof(localArray) / sizeof((localArray)[0]))));

最佳答案

用户需要为所有被复制出来的数据提供足够的空间。理想情况下,他会告诉您他提供了多少空间,然后您检查一切是否合适。

复制出的数据应该(通常)不包含任何指针,因为它们是“本地”到不同的“进程”(内核可以被视为一个单独的进程,而内核/用户交互涉及进程到进程的 IPC,类似于通过本地甚至互联网连接的套接字发送内容)。

由于内核对进程有非常深入的了解,您可以略微绕过这些规则,例如,您可以计算用户的指针是什么,并复制出原始数据的副本,并适当修改指针。但这有点浪费。或者,您可以复制内核指针而不在用户代码中使用它,但现在您正在“泄露数据”,“坏人”有时可以通过各种方式利用这些数据。用安全人员的话来说,您留下了一个完全开放的“ secret channel ”。

最后,“正确”的做法往往是这样的:

struct user_interface_version_of_struct {
int property;
int count;
int data[]; /* of size "count" */
};

用户代码mallocs(或以其他方式安排有足够的空间)“用户界面版本”并对内核进行一些系统调用(readreceivercvmsgioctl 等等,只要它涉及执行“读取”类型的操作)并告诉内核:“这是内存持有结构,这是它有多大”(以字节为单位,或最大 count 值,或其他:用户和内核只需要就协议(protocol)达成一致)。然后,内核端代码以某种适当的方式验证用户的值,并且要么以最方便的方式进行复制,要么返回错误。

“最方便”有时是两个单独的复制操作,或一些 put_user 调用,例如,如果内核端具有您显示的数据结构,您可能会这样做:

/* let's say ulen is the user supplied length in bytes,
and uaddr is the user-supplied address */
struct user_interface_version_of_struct *p;

needed = sizeof(*p) + 3 * sizeof(int);
if (needed > ulen)
return -ENOMEM; /* user did not supply enough space */
p = uaddr;
error = put_user(1024, &p->property);
if (error == 0)
error = put_user(3, &p->count);
if (error == 0 && copy_to_user(&p->data, localArray, 3 * sizeof(int))
error = -EFAULT;

不过,您可能会遇到必须遵守一些不太好的接口(interface)的情况。


编辑:如果您要添加自己的系统调用(而不是绑定(bind)到 readioctl 等),您可以将 header 和数据分开,如在 Adam Rosenfield's answer .

关于copy_to_user 一个包含数组(指针)的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18520071/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com