change copy-in routines

- restrict copy_from_user() to only current process.
- add read_process_vm() to read specified process space.
This commit is contained in:
NAKAMURA Gou
2015-03-03 17:14:38 +09:00
parent a6488adcc1
commit 063fa963c3
3 changed files with 75 additions and 25 deletions

View File

@ -20,6 +20,7 @@
#include <list.h>
#include <process.h>
#include <page.h>
#include <cls.h>
#define dkprintf(...) do { if (0) kprintf(__VA_ARGS__); } while (0)
#define ekprintf(...) kprintf(__VA_ARGS__)
@ -2117,9 +2118,9 @@ void *phys_to_virt(unsigned long p)
return (void *)(p + MAP_ST_START);
}
int copy_from_user(struct process *proc, void *dst, const void *src, size_t siz)
int copy_from_user(void *dst, const void *src, size_t siz)
{
struct process_vm *vm = proc->vm;
struct process_vm *vm = cpu_local_var(current)->vm;
struct vm_range *range;
size_t pos;
size_t wsiz;
@ -2146,6 +2147,59 @@ int copy_from_user(struct process *proc, void *dst, const void *src, size_t siz)
return 0;
}
int read_process_vm(struct process_vm *vm, void *kdst, const void *usrc, size_t siz)
{
const uintptr_t ustart = (uintptr_t)usrc;
const uintptr_t uend = ustart + siz;
uint64_t reason;
uintptr_t addr;
int error;
const void *from;
void *to;
size_t remain;
size_t cpsize;
unsigned long pa;
void *va;
if ((ustart < vm->region.user_start)
|| (vm->region.user_end <= ustart)
|| ((vm->region.user_end - ustart) < siz)) {
return -EFAULT;
}
reason = PF_USER; /* page not present */
for (addr = ustart & PAGE_MASK; addr < uend; addr += PAGE_SIZE) {
error = page_fault_process_vm(vm, (void *)addr, reason);
if (error) {
return error;
}
}
from = usrc;
to = kdst;
remain = siz;
while (remain > 0) {
cpsize = PAGE_SIZE - ((uintptr_t)from & (PAGE_SIZE - 1));
if (cpsize > remain) {
cpsize = remain;
}
error = ihk_mc_pt_virt_to_phys(vm->page_table, from, &pa);
if (error) {
return error;
}
va = phys_to_virt(pa);
memcpy(to, va, cpsize);
from += cpsize;
to += cpsize;
remain -= cpsize;
}
return 0;
} /* read_process_vm() */
int copy_to_user(struct process *proc, void *dst, const void *src, size_t siz)
{
struct process_vm *vm = proc->vm;

View File

@ -25,7 +25,7 @@
#include <kmalloc.h>
void terminate(int, int, ihk_mc_user_context_t *);
int copy_from_user(struct process *proc, void *dst, const void *src, size_t siz);
int copy_from_user(void *dst, const void *src, size_t siz);
int copy_to_user(struct process *proc, void *dst, const void *src, size_t siz);
long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
@ -117,7 +117,7 @@ SYSCALL_DECLARE(rt_sigaction)
return -EINVAL;
if(act)
if(copy_from_user(proc, &new_sa.sa, act, sizeof new_sa.sa)){
if(copy_from_user(&new_sa.sa, act, sizeof new_sa.sa)){
goto fault;
}
rc = do_sigaction(sig, act? &new_sa: NULL, oact? &old_sa: NULL);
@ -152,9 +152,9 @@ SYSCALL_DECLARE(rt_sigreturn)
sigsp = (struct sigsp *)regs->gpr.rsp;
proc->sigmask.__val[0] = sigsp->sigmask;
proc->sigstack.ss_flags = sigsp->ssflags;
if(copy_from_user(proc, regs, &sigsp->regs, sizeof(struct x86_user_context)))
if(copy_from_user(regs, &sigsp->regs, sizeof(struct x86_user_context)))
return rc;
copy_from_user(proc, &rc, &sigsp->sigrc, sizeof(long));
copy_from_user(&rc, &sigsp->sigrc, sizeof(long));
return rc;
}

View File

@ -98,7 +98,8 @@ void check_signal(unsigned long rc, void *regs);
void do_signal(long rc, void *regs, struct process *proc, struct sig_pending *pending);
extern unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info, int ptracecont);
extern struct sigpending *hassigpending(struct process *proc);
int copy_from_user(struct process *, void *, const void *, size_t);
int copy_from_user(void *, const void *, size_t);
int read_process_vm(struct process_vm *, void *, const void *, size_t);
int copy_to_user(struct process *, void *, const void *, size_t);
void do_setpgid(int, int);
extern long alloc_debugreg(struct process *proc);
@ -2096,7 +2097,7 @@ SYSCALL_DECLARE(rt_sigprocmask)
goto fault;
}
if(set){
if(copy_from_user(proc, &wsig, set->__val, sizeof wsig))
if(copy_from_user(&wsig, set->__val, sizeof wsig))
goto fault;
switch(how){
case SIG_BLOCK:
@ -2184,10 +2185,10 @@ SYSCALL_DECLARE(rt_sigtimedwait)
if(set == NULL)
return -EFAULT;
memset(&winfo, '\0', sizeof winfo);
if(copy_from_user(proc, &wset, set, sizeof wset))
if(copy_from_user(&wset, set, sizeof wset))
return -EFAULT;
if(timeout)
if(copy_from_user(proc, wtimeout, timeout, sizeof wtimeout))
if(copy_from_user(wtimeout, timeout, sizeof wtimeout))
return -EFAULT;
@ -2203,13 +2204,12 @@ SYSCALL_DECLARE(rt_sigqueueinfo)
int pid = (int)ihk_mc_syscall_arg0(ctx);
int sig = (int)ihk_mc_syscall_arg1(ctx);
void *winfo = (void *)ihk_mc_syscall_arg2(ctx);
struct process *proc = cpu_local_var(current);
struct siginfo info;
if(pid <= 0)
return -ESRCH;
if(copy_from_user(proc, &info, winfo, sizeof info))
if(copy_from_user(&info, winfo, sizeof info))
return -EFAULT;
return do_kill(pid, -1, sig, &info, 0);
@ -2285,7 +2285,7 @@ SYSCALL_DECLARE(rt_sigsuspend)
if (sigsetsize > sizeof(sigset_t))
return -EINVAL;
if(copy_from_user(proc, &wset, set, sizeof wset))
if(copy_from_user(&wset, set, sizeof wset))
return -EFAULT;
return do_sigsuspend(proc, &wset);
@ -2302,7 +2302,7 @@ SYSCALL_DECLARE(sigaltstack)
if(copy_to_user(proc, oss, &proc->sigstack, sizeof wss))
return -EFAULT;
if(ss){
if(copy_from_user(proc, &wss, ss, sizeof wss))
if(copy_from_user(&wss, ss, sizeof wss))
return -EFAULT;
if(wss.ss_flags != 0 && wss.ss_flags != SS_DISABLE)
return -EINVAL;
@ -2636,7 +2636,7 @@ SYSCALL_DECLARE(setrlimit)
if(i >= sizeof(rlimits) / sizeof(int))
return -EINVAL;
if(copy_from_user(proc, proc->rlimit + mcresource, rlm, sizeof(struct rlimit)))
if(copy_from_user(proc->rlimit + mcresource, rlm, sizeof(struct rlimit)))
return -EFAULT;
return 0;
@ -2828,7 +2828,6 @@ static long ptrace_setregs(int pid, long data)
struct user_regs_struct *regs = (struct user_regs_struct *)data;
long rc = -EIO;
struct process *child;
struct process *proc = cpu_local_var(current);
ihk_spinlock_t *savelock;
unsigned long irqstate;
@ -2837,7 +2836,7 @@ static long ptrace_setregs(int pid, long data)
return -ESRCH;
if(child->ftn->status == PS_TRACED){
struct user_regs_struct user_regs;
rc = copy_from_user(proc, &user_regs, regs, sizeof(struct user_regs_struct));
rc = copy_from_user(&user_regs, regs, sizeof(struct user_regs_struct));
if (rc == 0) {
long addr;
unsigned long *p;
@ -2926,9 +2925,7 @@ static long ptrace_peektext(int pid, long addr, long data)
return -ESRCH;
if(child->ftn->status == PS_TRACED){
unsigned long value;
ihk_mc_load_page_table(child->vm->page_table);
rc = copy_from_user(child, &value, (void *)addr, sizeof(value));
ihk_mc_load_page_table(proc->vm->page_table);
rc = read_process_vm(child->vm, &value, (void *)addr, sizeof(value));
if (rc != 0) {
dkprintf("ptrace_peektext: bad area addr=0x%llx\n", addr);
} else {
@ -3283,7 +3280,6 @@ ptrace_setsiginfo(int pid, siginfo_t *data)
ihk_spinlock_t *savelock;
unsigned long irqstate;
struct process *child;
struct process *proc = cpu_local_var(current);
int rc = 0;
kprintf("ptrace_setsiginfo: sig=%d errno=%d code=%d\n", data->si_signo, data->si_errno, data->si_code);
@ -3304,7 +3300,7 @@ kprintf("ptrace_setsiginfo: sig=%d errno=%d code=%d\n", data->si_signo, data->si
}
if (!rc &&
copy_from_user(proc, &child->ptrace_sendsig->info, data, sizeof(siginfo_t))) {
copy_from_user(&child->ptrace_sendsig->info, data, sizeof(siginfo_t))) {
rc = -EFAULT;
}
}
@ -3491,7 +3487,7 @@ SYSCALL_DECLARE(sched_setparam)
}
}
retval = copy_from_user(proc, &param, uparam, sizeof(param));
retval = copy_from_user(&param, uparam, sizeof(param));
if (retval < 0) {
return -EFAULT;
}
@ -3564,7 +3560,7 @@ SYSCALL_DECLARE(sched_setscheduler)
}
}
retval = copy_from_user(proc, &param, uparam, sizeof(param));
retval = copy_from_user(&param, uparam, sizeof(param));
if (retval < 0) {
return -EFAULT;
}
@ -3711,7 +3707,7 @@ SYSCALL_DECLARE(sched_setaffinity)
}
len = MIN2(len, sizeof(k_cpu_set));
if (copy_from_user(cpu_local_var(current), &k_cpu_set, u_cpu_set, len)) {
if (copy_from_user(&k_cpu_set, u_cpu_set, len)) {
kprintf("%s:%d copy_from_user failed.\n", __FILE__, __LINE__);
return -EFAULT;
}