I want to implement syscall on a PM server on Minix, which has access to some data in user space and can change it.
I pass data to syscall using the Minix messaging engine. In the message structure that is being passed, I assign one of the pointers to the address of the variable from the user space that I want to pass.
For example, in a user program
message m; m.m1_p1 = &var;
In the kernel, in the syscall function, I do
char *ptr = m_in.m1_p1;
However, when I try to either read or write data, I get an error message that the kernel has panicked and requires a reboot.
I understand that this is probably because user space uses user-specific virtual addresses that are not recognized in syscall.
Looking for further, I found that Linux has the functions copy_from_user() and copy_to_user() to achieve this.
Is there an equivalent to this minix? If not, is there any other way to achieve this?
Using the @osgx suggestion in the comments, I tried using sys_datacopy() . Although this allows me to read and write data in a system call, the changes I make are not reflected back to the user program that calls the system call.
My last attempt is as follows:
In user program
message m; m.m1_p1 = &var; //data to be passed printf("%c\n",*(m.m1_p1)); //gives the value in var //pass it to the syscall printf("%c\n",var); //gives the old value of var
Inside syscall,
char *ptr = (char*)malloc(sizeof(char)); sys_datacopy(who_e,(vir_bytes)(m_in.m1_p1),SELF,(vir_bytes)(ptr),sizeof(char*));
Here now I can access the var value inside syscall with ptr and change it inside syscall. However, after returning from syscall, I noticed that the base value of `var 'has not changed.
According to my understanding, what was supposed to happen was that sys_datacopy() was supposed to copy the equivalent virtual object m_in.m1_p1 , which is in the syscall address space on ptr , which points to the same physical address. Thus, *ptr must exactly reach var , thereby changing it.
Or is it that the data corresponding to the address is copied when I use sys_datacopy() ? If so, one solution that I can think of is to define a message structure that allows double pointers and passes char** to syscall. Then dereferencing will ensure that the address is copied to ptr . But again, dereferencing ptr will try to dereference a virtual address belonging to the address space of a user process that will not work.
Why does this method not work? What is the right way to achieve this?
I am using Minix 3.2.1.
Thanks.