I'm trying to make a custom system call.
my system call takes 2 parameters struct buffer **mybuffer
& int size
.
it's imposed any change that happens to **mybuffer
should reflect in the user-space, but it seems it doesn't work.
so I've seen somewhere else that i can use copy_to_user(void *dest, void *src, int size)
to copy data from kernel space to user space.
in user-space i have a struct called buffer, also this struct appears the same in the system call.
typedef struct buffer {
int n;
}buffer;
int main(void)
{
buffer **buf = malloc(sizeof(buffer *));
int i = 0
for(;i<8;i++)
buf[i] = malloc(sizeof(buffer));
long int sys = systemcall(801,buf,8)
//print out buf
return 0;
}
In system call i have
asmlinkage long sys_something(buffer **buf,int size)
{
//allocate buffer same as it appears in int main
//fill buf with some data
for(i = 0; i<size,i++)
copy_to_user(buf[i],buf[i],sizeof(buffer));
I'm pretty sure that i'm doing something wrong. how actually to copy data from kernel space to user space ?
P.s. I'm using linux kernel 3.16.0
The function copy_to_user
is used to copy data from the kernel address space to the address space of the user program. For example, to copy a buffer which has been allocated with kmalloc
to the buffer provided by the user.
EDIT: Your example is a little bit more complex, because you pass an array of pointers to the system-call. To access these pointers
you have to copy the array buf
to kernel space first using copy_from_user
.
Thus, your kernel code should look like this:
asmlinkage long sys_something(buffer **buf, int size)
{
/* Allocate buffers_in_kernel on stack just for demonstration.
* These buffers would normally allocated by kmalloc.
*/
buffer buffers_in_kernel[size];
buffer *user_pointers[size];
int i;
unsigned long res;
/* Fill buffers_in_kernel with some data */
for (i = 0; i < size; i++)
buffers_in_kernel[i].n = i; /* just some example data */
/* Get user pointers for access in kernel space.
* This is a shallow copy, so that, the entries in user_pointers
* still point to the user space.
*/
res = copy_from_user(user_pointers, buf, sizeof(buffer *) * size);
/* TODO: check result here */
/* Now copy data to user space. */
for (i = 0; i < size; i++) {
res = copy_to_user(user_pointers[i], &buffers_in_kernel[i], sizeof(buffer));
/* TODO: check result here */
}
}
Last but not least, there is a mistake in your main
function. At the first malloc
call, it allocates only enough space for 1 pointer instead of 8. It should be:
int main(void)
{
const int size = 8;
buffer **buf = malloc(sizeof(buffer *) * size);
for(int i=0; i<size; i++) buf[i] = malloc(sizeof(buffer));
long int sys = systemcall(801,buf,size)
//print out buf
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With