process_read/write_vm(): fix LTP bugs
This commit is contained in:
108
kernel/syscall.c
108
kernel/syscall.c
@@ -48,6 +48,7 @@
|
|||||||
#include <shm.h>
|
#include <shm.h>
|
||||||
#include <prio.h>
|
#include <prio.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
/* Headers taken from kitten LWK */
|
/* Headers taken from kitten LWK */
|
||||||
#include <lwk/stddef.h>
|
#include <lwk/stddef.h>
|
||||||
@@ -5930,13 +5931,45 @@ static int do_process_vm_read_writev(int pid,
|
|||||||
unsigned long rphys;
|
unsigned long rphys;
|
||||||
unsigned long rpage_left;
|
unsigned long rpage_left;
|
||||||
void *rva;
|
void *rva;
|
||||||
|
struct vm_range *range;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
if (flags) {
|
if (flags) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: IOV_MAX and PTRACE_ATTACH permission checks.. */
|
if (liovcnt > IOV_MAX || riovcnt > IOV_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if parameters are okay */
|
||||||
|
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
||||||
|
|
||||||
|
range = lookup_process_memory_range(lthread->vm,
|
||||||
|
(uintptr_t)local_iov,
|
||||||
|
(uintptr_t)(local_iov + liovcnt * sizeof(struct iovec)));
|
||||||
|
|
||||||
|
if (!range) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto arg_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
range = lookup_process_memory_range(lthread->vm,
|
||||||
|
(uintptr_t)remote_iov,
|
||||||
|
(uintptr_t)(remote_iov + riovcnt * sizeof(struct iovec)));
|
||||||
|
|
||||||
|
if (!range) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto arg_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
arg_out:
|
||||||
|
ihk_mc_spinlock_unlock_noirq(<hread->vm->memory_range_lock);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
for (li = 0; li < liovcnt; ++li) {
|
for (li = 0; li < liovcnt; ++li) {
|
||||||
llen += local_iov[li].iov_len;
|
llen += local_iov[li].iov_len;
|
||||||
@@ -5977,6 +6010,16 @@ static int do_process_vm_read_writev(int pid,
|
|||||||
ret = -ESRCH;
|
ret = -ESRCH;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rthread->proc->ruid != lthread->proc->ruid ||
|
||||||
|
rthread->proc->euid != lthread->proc->euid ||
|
||||||
|
rthread->proc->rgid != lthread->proc->rgid ||
|
||||||
|
rthread->proc->egid != lthread->proc->egid) {
|
||||||
|
|
||||||
|
ret = -EPERM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dkprintf("pid %d found, doing %s \n", pid,
|
dkprintf("pid %d found, doing %s \n", pid,
|
||||||
(op == PROCESS_VM_READ) ? "PROCESS_VM_READ" : "PROCESS_VM_WRITE");
|
(op == PROCESS_VM_READ) ? "PROCESS_VM_READ" : "PROCESS_VM_WRITE");
|
||||||
@@ -5994,10 +6037,21 @@ static int do_process_vm_read_writev(int pid,
|
|||||||
|
|
||||||
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
ihk_mc_spinlock_lock_noirq(<hread->vm->memory_range_lock);
|
||||||
|
|
||||||
|
/* Is base valid? */
|
||||||
|
range = lookup_process_memory_range(lthread->vm,
|
||||||
|
(uintptr_t)local_iov[li].iov_base,
|
||||||
|
(uintptr_t)(local_iov[li].iov_base + 1));
|
||||||
|
|
||||||
|
if (!range) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto pli_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is length valid? */
|
||||||
range = lookup_process_memory_range(lthread->vm,
|
range = lookup_process_memory_range(lthread->vm,
|
||||||
(uintptr_t)local_iov[li].iov_base,
|
(uintptr_t)local_iov[li].iov_base,
|
||||||
(uintptr_t)(local_iov[li].iov_base + local_iov[li].iov_len));
|
(uintptr_t)(local_iov[li].iov_base + local_iov[li].iov_len));
|
||||||
|
|
||||||
if (range == NULL) {
|
if (range == NULL) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto pli_out;
|
goto pli_out;
|
||||||
@@ -6005,7 +6059,7 @@ static int do_process_vm_read_writev(int pid,
|
|||||||
|
|
||||||
if (!(range->flag & ((op == PROCESS_VM_READ) ?
|
if (!(range->flag & ((op == PROCESS_VM_READ) ?
|
||||||
VR_PROT_WRITE : VR_PROT_READ))) {
|
VR_PROT_WRITE : VR_PROT_READ))) {
|
||||||
ret = -EPERM;
|
ret = -EFAULT;
|
||||||
goto pli_out;
|
goto pli_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6024,22 +6078,60 @@ pli_out:
|
|||||||
if (pri != ri) {
|
if (pri != ri) {
|
||||||
uint64_t reason = PF_POPULATE | PF_WRITE | PF_USER;
|
uint64_t reason = PF_POPULATE | PF_WRITE | PF_USER;
|
||||||
void *addr;
|
void *addr;
|
||||||
|
struct vm_range *range;
|
||||||
|
|
||||||
|
ihk_mc_spinlock_lock_noirq(&rthread->vm->memory_range_lock);
|
||||||
|
|
||||||
|
/* Is base valid? */
|
||||||
|
range = lookup_process_memory_range(rthread->vm,
|
||||||
|
(uintptr_t)remote_iov[li].iov_base,
|
||||||
|
(uintptr_t)(remote_iov[li].iov_base + 1));
|
||||||
|
|
||||||
|
if (!range) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto pri_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is length valid? */
|
||||||
|
range = lookup_process_memory_range(lthread->vm,
|
||||||
|
(uintptr_t)remote_iov[li].iov_base,
|
||||||
|
(uintptr_t)(remote_iov[li].iov_base + remote_iov[li].iov_len));
|
||||||
|
|
||||||
|
if (range == NULL) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto pri_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(range->flag & ((op == PROCESS_VM_READ) ?
|
||||||
|
VR_PROT_READ : VR_PROT_WRITE))) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto pri_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
pri_out:
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&rthread->vm->memory_range_lock);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fault in pages */
|
||||||
for (addr = (void *)
|
for (addr = (void *)
|
||||||
((unsigned long)remote_iov[ri].iov_base & PAGE_MASK);
|
((unsigned long)remote_iov[ri].iov_base & PAGE_MASK);
|
||||||
addr < (remote_iov[ri].iov_base + remote_iov[ri].iov_len);
|
addr < (remote_iov[ri].iov_base + remote_iov[ri].iov_len);
|
||||||
addr += PAGE_SIZE) {
|
addr += PAGE_SIZE) {
|
||||||
|
|
||||||
ret = page_fault_process_vm(rthread->vm, addr, reason);
|
ret = page_fault_process_vm(rthread->vm, addr, reason);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ret = -EINVAL;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pri = ri;
|
pri = ri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Figure out how much we can copy at most in this iteration */
|
/* Figure out how much we can copy at most in this iteration */
|
||||||
to_copy = (local_iov[li].iov_len - loff);
|
to_copy = (local_iov[li].iov_len - loff);
|
||||||
if ((remote_iov[ri].iov_len - roff) < to_copy) {
|
if ((remote_iov[ri].iov_len - roff) < to_copy) {
|
||||||
@@ -6058,7 +6150,7 @@ pli_out:
|
|||||||
remote_iov[ri].iov_base + roff, &rphys);
|
remote_iov[ri].iov_base + roff, &rphys);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ret = -EINVAL;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,5 +15,6 @@
|
|||||||
|
|
||||||
#define INT_MAX 0x7fffffff
|
#define INT_MAX 0x7fffffff
|
||||||
#define INT_MIN -0x80000000
|
#define INT_MIN -0x80000000
|
||||||
|
#define IOV_MAX 1024
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user