Reputation: 900
I have a rather big project in Linux kernel (h.w).
part of needs to use the copy_to_user function, for some reason, no matter what is the buffer size it will alyways return the buffer size (and not 0).
can you please help?
here is part of my code:
asmlinkage int sys_receive_mpi_message(int rank, char *message, ssize_t message_size)
{
int reader_rank =-10;
struct task_struct* p = NULL;
struct my_message_list* tmp;
struct list_head *pos, *q;
struct blabla* tmp1;
int bufSize = 0;
int res =0;
int i=0;
if ((rank < 0) || (rank > counter))
{
return -ESRCH;
}
list_for_each(pos, &(my_api_list->list))
{
tmp1 = list_entry(pos, struct blabla, list);
if (tmp1->pid == (current->pid))
{
reader_rank = tmp1->place;
p = tmp1->task_struct_p;
break;
}
}
if (reader_rank == -10)
{
return -ESRCH;
}
list_for_each_safe(pos,q, &(p->message_list->list))
{
tmp=list_entry(pos, struct my_message_list, list);
if (tmp->sender_rank == rank)
{
if (message_size > (tmp->meesage_size))
{
bufSize = tmp->meesage_size;
}
else
{
bufSize = message_size;
}
res = copy_to_user(message,tmp->message,bufSize);
if(res != 0)
{
return -EFAULT;
}
kfree(tmp->message);
list_del(pos);
kfree(tmp);
return (bufSize);
}
return -EFAULT;
}
return -EFAULT;
}
also, I have this struct :
struct my_message_list{
char* message;
int meesage_size;
int sender_rank;
struct list_head list;
};
Update- I foundout that the message I'm geting from the user points to 0 all the time! does this tells me that the problem is in the wrapper function? here is my rapper function(the relevent part):
#include <errno.h>
int receive_mpi_message(int rank, char* message, int message_size)
{
int res;
__asm__
(
"pushl %%eax;"
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%edx;"
"movl $245, %%eax;"
"movl %1, %%ebx;"
"int $0x80;"
"movl %%eax,%0;"
"popl %%edx;"
"popl %%ecx;"
"popl %%ebx;"
"popl %%eax;"
: "=m" (res)
:"m"(rank),"m"(message),"m"(message_size)
);
if (res >= (unsigned long)(-125))
{
errno = -res;
res = -1;
}
return (int) res;
}
Upvotes: 1
Views: 1346
Reputation: 900
I had a problem with my rapper function, forogot to store data to all the registers:
int receive_mpi_message(int rank, char* message, int message_size)
{
int res;
__asm__
(
"pushl %%eax;"
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%edx;"
"movl $245, %%eax;"
"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"
"int $0x80;"
"movl %%eax,%0;"
"popl %%edx;"
"popl %%ecx;"
"popl %%ebx;"
"popl %%eax;"
: "=m" (res)
:"m"(rank),"m"(message),"m"(message_size)
);
if (res >= (unsigned long)(-125))
{
errno = -res;
res = -1;
}
return (int) res;
}
Upvotes: 0
Reputation: 6193
What user-space interface do you use for communication? Regardless what user space interface you use (chardev, ioctl, ...), the signature of the function definitions where you hook in should have a __user
attribute.
eg: fs.h
struct file_operations {
...
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
...
}
So the char *message
variable should be char __user *message
, just take a look at the user space interface you use.
Another thing could be that you are calling the method in the wrong place. As far is i know, the copy_*_user
functions are only allowed on invocation from the user space. Please someone correct me if i am wrong.
Upvotes: 1
Reputation: 3677
Somehow the date you want to copy could not be copied, as for example, you cannot read the source or write to destination. It is explained at arch/x86/lib/usercopy_32.c:
/*
* Returns number of bytes that could not be copied.
* On success, this will be zero.
*/
Upvotes: 0