涉及的结构如下。 struct node { int a; int b; }
struct ioctl_node {
struct node **ptr;
int count; //Stores the no of pointers this ptr is pointing to.
};
在用户空间中,我使用count = 3
填充了ioctl_node的结构。
ptr[0]
和ptr[2]
指向节点类型的两个结构,而ptr[1]
是NULL
。我想将它传递给内核。
我发出了ioctl调用,将此信息从用户空间传递到内核空间。
我在内核空间中做了以下内容。
struct ioctl_node k_node;
copy_from_user(&k_node, arg, sizeof(struct ioctl_node)) //arg is the source
//k_node.count is showing the right value what I have set in the user space.
struct node *tmp = NULL;
然后我做了copy_from_user(&tmp, k_node.ptr, sizeof(struct node *)
,这个电话也恢复了成功。
但是,我很难在内核空间中正确地复制**ptr
的全部内容。
任何人都能得到帮助,我怎么能做到这一点。我该怎么做下一个copy_from_user来复制所有内容。我试过,但它给出了复制错误。
答案 0 :(得分:1)
copy_from_user
将一个连续字节块从用户空间复制到内核空间。您需要先复制struct ioctl_node
,然后将指针复制到各个节点,然后在循环中复制struct node
。一定要分配适量的内存。由于您事先知道节点数,因此可以分配它们的数组。
struct node_data {
size_t node_count;
struct nodes *nodes;
};
struct node_data *read_nodes(struct ioctl_node_user_pointer *arg)
{
struct node_data *nd = NULL;
struct ioctl_node kin = {0};
struct node *node_user_pointers = NULL;
int i;
int err;
/* Step 1: retrieve the root node */
nd = kmalloc(sizeof(*nd), GFP_KERNEL);
if (!nd) {
err = -ENOMEM;
goto error;
}
if (copy_from_user(ioctl_node_user_pointer, &kin, sizeof(kin))) {
err = -EFAULT;
goto error;
}
if (kin->count < 0 || kin->count > ((size_t)-1)/sizeof(*nodes)) {
err = -EINVAL;
goto error;
}
nd->node_count = kin.count;
/* Step 2: retrieve the pointers to individual nodes */
node_user_pointers = kmalloc(sizeof(*node_user_pointers) * nd->node_count, GFP_KERNEL);
if (node_user_pointers) {
err = -ENOMEM;
goto error;
}
if (copy_from_user(kin->nodes, node_user_pointers, sizeof(*node_user_pointers) * nd->node_count)) {
err = -EFAULT;
goto error;
}
/* Step 3: retrieve the nodes themselves */
nd->nodes = kmalloc(sizeof(*nodes) * nd->node_count, GFP_KERNEL);
if (!nd->nodes) {
err = -ENOMEM;
goto error;
}
for (i = 0; i < head.count; i++) {
if (copy_from_user(node_user_pointers[i], nd->nodes + i, sizeof(nd->nodes[0]))) {
err = -EFAULT;
goto error;
}
}
kfree(node_user_pointers);
return nd;
error:
if (nd) {
kfree(nd->nodes);
kfree(nd);
}
kfree(node_user_pointers);
return ERR_PTR(err);
}