add MCEXEC_UP_STRNCPY_FROM_USER
It allows a mcexec to execute the strncpy_from_user().
This commit is contained in:
@ -37,6 +37,7 @@
|
||||
#define MCEXEC_UP_LOAD_SYSCALL 0x30a02905
|
||||
#define MCEXEC_UP_SEND_SIGNAL 0x30a02906
|
||||
#define MCEXEC_UP_GET_CPU 0x30a02907
|
||||
#define MCEXEC_UP_STRNCPY_FROM_USER 0x30a02908
|
||||
|
||||
#define MCEXEC_UP_PREPARE_DMA 0x30a02910
|
||||
#define MCEXEC_UP_FREE_DMA 0x30a02911
|
||||
@ -115,6 +116,13 @@ struct syscall_ret_desc {
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct strncpy_from_user_desc {
|
||||
void *dest;
|
||||
void *src;
|
||||
unsigned long n;
|
||||
long result;
|
||||
};
|
||||
|
||||
struct prepare_dma_desc {
|
||||
unsigned long size;
|
||||
unsigned long pa;
|
||||
|
||||
@ -573,6 +573,58 @@ long mcexec_ret_syscall(ihk_os_t os, struct syscall_ret_desc *__user arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_strncpy_from_user(ihk_os_t os, struct strncpy_from_user_desc * __user arg)
|
||||
{
|
||||
struct strncpy_from_user_desc desc;
|
||||
void *buf;
|
||||
void *dest;
|
||||
void *src;
|
||||
unsigned long remain;
|
||||
long want;
|
||||
long copied;
|
||||
|
||||
if (copy_from_user(&desc, arg, sizeof(desc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
buf = (void *)__get_free_page(GFP_KERNEL);
|
||||
if (!buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dest = desc.dest;
|
||||
src = desc.src;
|
||||
remain = desc.n;
|
||||
want = 0;
|
||||
copied = 0;
|
||||
|
||||
while ((remain > 0) && (want == copied)) {
|
||||
want = (remain > PAGE_SIZE)? PAGE_SIZE: remain;
|
||||
copied = strncpy_from_user(buf, src, want);
|
||||
if (copied == want) {
|
||||
if (copy_to_user(dest, buf, copied)) {
|
||||
copied = -EFAULT;
|
||||
}
|
||||
}
|
||||
else if (copied >= 0) {
|
||||
if (copy_to_user(dest, buf, copied+1)) {
|
||||
copied = -EFAULT;
|
||||
}
|
||||
}
|
||||
dest += copied;
|
||||
src += copied;
|
||||
remain -= copied;
|
||||
}
|
||||
|
||||
desc.result = (copied >= 0)? (desc.n - remain): copied;
|
||||
free_page((unsigned long)buf);
|
||||
|
||||
if (copy_to_user(arg, &desc, sizeof(*arg))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg)
|
||||
{
|
||||
switch (req) {
|
||||
@ -600,6 +652,9 @@ long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg)
|
||||
case MCEXEC_UP_GET_CPU:
|
||||
return mcexec_get_cpu(os);
|
||||
|
||||
case MCEXEC_UP_STRNCPY_FROM_USER:
|
||||
return mcexec_strncpy_from_user(os, (struct strncpy_from_user_desc *)arg);
|
||||
|
||||
case MCEXEC_UP_PREPARE_DMA:
|
||||
return mcexec_pin_region(os, (unsigned long *)arg);
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ static struct ihk_os_user_call_handler mcctrl_uchs[] = {
|
||||
{ .request = MCEXEC_UP_LOAD_SYSCALL, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_SEND_SIGNAL, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_GET_CPU, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_STRNCPY_FROM_USER, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_PREPARE_DMA, .func = mcctrl_ioctl },
|
||||
{ .request = MCEXEC_UP_FREE_DMA, .func = mcctrl_ioctl },
|
||||
};
|
||||
|
||||
@ -883,6 +883,25 @@ kill_thread(unsigned long cpu)
|
||||
}
|
||||
}
|
||||
|
||||
static long do_strncpy_from_user(int fd, void *dest, void *src, unsigned long n)
|
||||
{
|
||||
struct strncpy_from_user_desc desc;
|
||||
int ret;
|
||||
|
||||
desc.dest = dest;
|
||||
desc.src = src;
|
||||
desc.n = n;
|
||||
|
||||
ret = ioctl(fd, MCEXEC_UP_STRNCPY_FROM_USER, (unsigned long)&desc);
|
||||
if (ret) {
|
||||
ret = -errno;
|
||||
perror("strncpy_from_user:ioctl");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return desc.result;
|
||||
}
|
||||
|
||||
#define SET_ERR(ret) if (ret == -1) ret = -errno
|
||||
|
||||
int main_loop(int fd, int cpu, pthread_mutex_t *lock)
|
||||
|
||||
Reference in New Issue
Block a user