I want to implement a syscall in the PM server in Minix that has access to some data in the user space, and can modify it.
I am passing data to the syscall using Minix's message passing mechanism. 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 the user program,
message m;
m.m1_p1 = &var; //data to be passed
//pass it to the syscall
In the kernel, in the syscall function, I do
char *ptr = m_in.m1_p1;
However, when I try to either read or write the data, I get an error that the kernel has panicked, and needs a reboot.
I realise that this is probably because in user space, virtual addresses specific to the user are being used, which is not recognizable in the syscall.
On searching further, I found that Linux has functions copy_from_user()
and copy_to_user()
to achieve this.
Is there an equivalent of this is Minix? If not, is there any other way to achieve this?
With the help of @osgx's suggestion in the comments, I have tried using sys_datacopy()
. While this allows me to read and write the data in the system call, the changes I make are not reflected back into the user program that called the system call.
My latest attempt is as follows:
In the 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 the syscall,
char *ptr = (char*)malloc(sizeof(char));
sys_datacopy(who_e,(vir_bytes)(m_in.m1_p1),SELF,(vir_bytes)(ptr),sizeof(char*)); //or some other version of sys_vircopy()?
printf("Read value of ptr : %c\n",*ptr); //gives correct value
*ptr = //new value
printf("New value of ptr : %c\n",*ptr); //gives modified value
Here, now I can access the value of var
inside the syscall using ptr
, and modify it inside the syscall as well. However, after returning from the syscall, I observe that the underlying value of `var' has not changed.
As per my understanding, what should have happened is that the sys_datacopy()
should have copied an equivalent virtual of m_in.m1_p1
that lies in the address space of the syscall to ptr
, that points to the same physical address. So, *ptr
should exactly reach var
, thus modifying it.
Or is it that the data corresponding to the address is copied, when I use sys_datacopy()
? If this is the case, one solution I can think of is defining a message structure that allows double pointers, and passing an char**
to the syscall. Then, dereferencing once will ensure that the address is copied to ptr
. But then again, dereferencing ptr
will attempt to dereference a virtual address that belongs to the user process's address space, which will not work.
Why is this method not working? What is the correct way to achieve this?
I am using Minix 3.2.1.
Thank you.
demonsservices, but +50 rep is +50 rep. Did you try to start from some manual like "implementing syscall for minix"? Some manuals may have useful ideas of transmitting data and may mention sys_datacopy, sys_copy, sys_vsafecopy, sys_safecopyfrom. Another source of knowlendge is source of minix services in x-ref systems like metager.de – osgx Mar 14 '17 at 06:48