I'm writing a linux kernel driver and for every function that sends data up to userspace or reads data from userspace, I am using copy_to_user() and copy_from_user(). My question is: do I need to use these calls if I am just copying a basic data type such as a u32 or an int?
If the function receives a pointer to user-space data, you have to use copy_from_user()
to copy the pointed-to data from user space into kernel space (and vice versa).
Note that the pointer value itself is passed by value (like all C parameters), so you don't have to do a copy_from_user()
to obtain the pointer value before you can copy_from_user()
the data it points to.
Numeric arguments work the same way as pointer arguments; in C terms, they're both scalars. You don't have to use copy_from_user()
to copy the value of the parameter; that's already been copied. You only have to use it to copy data that's pointed to by a passed pointer.
So if you have a parameter of type int
, you can use it directly. If your parameter points to an int
, then the int
object will be in user space, and you need to use copy_to_user
to copy the value of that object into kernel space.
void*
parameter, the kernel function that handles the system call receives a copy of the pointer; the alignment of the pointer object on the caller side is irrelevant. –
Shiau int*
), put_user
and get_user
may also be used. –
Bugloss When a user passes data to kernel space, this data can be split on several pages, and these pages can be even in swapped out memory. In these cases, you'll have to wait for the kernel to swap in the page and get access to the page where the data is in. In the case of elementary data types (like int or pointers) it is also true that some architectures (notably x86 intel) don't force the user to align the data so even an integer can be split around a page border. You can have access to the first part of you integer, but to wait for the second to get swapped in by the memory manager before the whole thing is accessed.
You can save some roundtrips by putting all user data in a structure whose pointer is passed to the kernel. You can copy_from_user it as a block and save accesses (and running into the risk of being blocked several times)
So, and as a conclusion, use the functions even for basic types, as there are plenty of them. Don't assume anything about where the user data can be when running in kernel mode. You have access to it, but the kernel virtual addresses of user data have nothing to do with the virtual addresses seen in user mode.
int a; write(fc, &a, sizeof a);
... –
Marquet This is how I do it (works but I'm not sure if this is the right way): First make an array of that datatype, then fill the array with the data, then pass the reference to that array, for example to pass only an integer:
int *from_user = (int *)kmalloc(sizeof(int), GFP_KERNEL);
if (copy_from_user(from_user, buff, count))
return -EFAULT;
printk(KERN_INFO "The value copied from user = %d", *from_user);
return sizeof(buff);
And the code for user space:
int to_be_passed[1];
to_be_passed[0] = 4; // 4 is just an example
int fd = open(DEVICE_NAME, O_RDWR);
write(fd, to_be_passed, sizeof(to_be_passed));
© 2022 - 2024 — McMap. All rights reserved.
int
or a pointer toint
, would be helpful. The two answers posted so far are based on two different interpretations of your question. – Shiau