signal part 3 (EFAULT)
This commit is contained in:
@@ -18,10 +18,8 @@
|
|||||||
typedef unsigned long int __sigset_t;
|
typedef unsigned long int __sigset_t;
|
||||||
#define __sigmask(sig) (((__sigset_t) 1) << ((sig) - 1))
|
#define __sigmask(sig) (((__sigset_t) 1) << ((sig) - 1))
|
||||||
|
|
||||||
# define _SIGSET_NWORDS (1024 / (8 * sizeof (__sigset_t)))
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
__sigset_t __val[_SIGSET_NWORDS];
|
__sigset_t __val[_NSIG_WORDS];
|
||||||
} sigset_t;
|
} sigset_t;
|
||||||
|
|
||||||
#define SIG_BLOCK 0
|
#define SIG_BLOCK 0
|
||||||
|
|||||||
@@ -1749,7 +1749,67 @@ unsigned long virt_to_phys(void *v)
|
|||||||
return va - MAP_ST_START;
|
return va - MAP_ST_START;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *phys_to_virt(unsigned long p)
|
void *phys_to_virt(unsigned long p)
|
||||||
{
|
{
|
||||||
return (void *)(p + MAP_ST_START);
|
return (void *)(p + MAP_ST_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int copy_from_user(struct process *proc, void *dst, const void *src, size_t siz)
|
||||||
|
{
|
||||||
|
struct process_vm *vm = proc->vm;
|
||||||
|
struct vm_range *range;
|
||||||
|
size_t pos;
|
||||||
|
size_t wsiz;
|
||||||
|
unsigned long pgstart = (unsigned long)src;
|
||||||
|
|
||||||
|
wsiz = siz + (pgstart & 0x0000000000000fffUL);
|
||||||
|
pgstart &= 0xfffffffffffff000UL;
|
||||||
|
if(!pgstart || pgstart >= MAP_KERNEL_START)
|
||||||
|
return -EFAULT;
|
||||||
|
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||||
|
for(pos = 0; pos < wsiz; pos += 4096, pgstart += 4096){
|
||||||
|
range = lookup_process_memory_range(vm, pgstart, pgstart+1);
|
||||||
|
if(range == NULL){
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
if((range->flag & VR_PROT_MASK) == VR_PROT_NONE){
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||||
|
memcpy(dst, src, siz);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int copy_to_user(struct process *proc, void *dst, const void *src, size_t siz)
|
||||||
|
{
|
||||||
|
struct process_vm *vm = proc->vm;
|
||||||
|
struct vm_range *range;
|
||||||
|
size_t pos;
|
||||||
|
size_t wsiz;
|
||||||
|
unsigned long pgstart = (unsigned long)dst;
|
||||||
|
|
||||||
|
wsiz = siz + (pgstart & 0x0000000000000fffUL);
|
||||||
|
pgstart &= 0xfffffffffffff000UL;
|
||||||
|
if(!pgstart || pgstart >= MAP_KERNEL_START)
|
||||||
|
return -EFAULT;
|
||||||
|
ihk_mc_spinlock_lock_noirq(&vm->memory_range_lock);
|
||||||
|
for(pos = 0; pos < wsiz; pos += 4096, pgstart += 4096){
|
||||||
|
range = lookup_process_memory_range(vm, pgstart, pgstart+1);
|
||||||
|
if(range == NULL){
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
if(((range->flag & VR_PROT_MASK) == VR_PROT_NONE) ||
|
||||||
|
!(range->flag & VR_PROT_WRITE)){
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&vm->memory_range_lock);
|
||||||
|
memcpy(dst, src, siz);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -121,7 +121,9 @@ struct process {
|
|||||||
} thread;
|
} thread;
|
||||||
|
|
||||||
int tid;
|
int tid;
|
||||||
|
volatile int sigevent;
|
||||||
sigset_t sigmask;
|
sigset_t sigmask;
|
||||||
|
sigset_t supmask;
|
||||||
ihk_spinlock_t sigpendinglock;
|
ihk_spinlock_t sigpendinglock;
|
||||||
struct list_head sigpending;
|
struct list_head sigpending;
|
||||||
struct sig_shared *sigshared;
|
struct sig_shared *sigshared;
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ static char *syscall_name[] MCKERNEL_UNUSED = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void check_signal(long rc, unsigned long *regs);
|
void check_signal(long rc, unsigned long *regs);
|
||||||
|
int copy_from_user(struct process *, void *, const void *, size_t);
|
||||||
|
int copy_to_user(struct process *, void *, const void *, size_t);
|
||||||
|
|
||||||
#ifdef DCFA_KMOD
|
#ifdef DCFA_KMOD
|
||||||
static void do_mod_exit(int status);
|
static void do_mod_exit(int status);
|
||||||
@@ -1041,32 +1043,38 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
|
|||||||
k = proc->sighandler->action + sig - 1;
|
k = proc->sighandler->action + sig - 1;
|
||||||
if(oact)
|
if(oact)
|
||||||
memcpy(oact, k, sizeof(struct k_sigaction));
|
memcpy(oact, k, sizeof(struct k_sigaction));
|
||||||
if(act){
|
if(act)
|
||||||
memcpy(k, act, sizeof(struct k_sigaction));
|
memcpy(k, act, sizeof(struct k_sigaction));
|
||||||
}
|
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigaction)
|
SYSCALL_DECLARE(rt_sigaction)
|
||||||
{
|
{
|
||||||
|
struct process *proc = cpu_local_var(current);
|
||||||
int sig = ihk_mc_syscall_arg0(ctx);
|
int sig = ihk_mc_syscall_arg0(ctx);
|
||||||
const struct sigaction *act = (const struct sigaction *)ihk_mc_syscall_arg1(ctx);
|
const struct sigaction *act = (const struct sigaction *)ihk_mc_syscall_arg1(ctx);
|
||||||
struct sigaction *oact = (struct sigaction *)ihk_mc_syscall_arg2(ctx);
|
struct sigaction *oact = (struct sigaction *)ihk_mc_syscall_arg2(ctx);
|
||||||
//size_t sigsetsize = ihk_mc_syscall_arg3(ctx);
|
size_t sigsetsize = ihk_mc_syscall_arg3(ctx);
|
||||||
struct k_sigaction new_sa, old_sa;
|
struct k_sigaction new_sa, old_sa;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
//if (sigsetsize != sizeof(sigset_t))
|
if (sigsetsize != sizeof(sigset_t))
|
||||||
//return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if(act)
|
if(act)
|
||||||
memcpy(&new_sa.sa, act, sizeof new_sa.sa);
|
if(copy_from_user(proc, &new_sa.sa, act, sizeof new_sa.sa)){
|
||||||
|
goto fault;
|
||||||
|
}
|
||||||
rc = do_sigaction(sig, act? &new_sa: NULL, oact? &old_sa: NULL);
|
rc = do_sigaction(sig, act? &new_sa: NULL, oact? &old_sa: NULL);
|
||||||
if(oact)
|
if(rc == 0 && oact)
|
||||||
memcpy(oact, &old_sa.sa, sizeof old_sa.sa);
|
if(copy_to_user(proc, oact, &old_sa.sa, sizeof old_sa.sa)){
|
||||||
|
goto fault;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
fault:
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigprocmask)
|
SYSCALL_DECLARE(rt_sigprocmask)
|
||||||
@@ -1074,8 +1082,13 @@ SYSCALL_DECLARE(rt_sigprocmask)
|
|||||||
int how = ihk_mc_syscall_arg0(ctx);
|
int how = ihk_mc_syscall_arg0(ctx);
|
||||||
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg1(ctx);
|
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg1(ctx);
|
||||||
sigset_t *oldset = (sigset_t *)ihk_mc_syscall_arg2(ctx);
|
sigset_t *oldset = (sigset_t *)ihk_mc_syscall_arg2(ctx);
|
||||||
|
size_t sigsetsize = (size_t)ihk_mc_syscall_arg3(ctx);
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
int flag;
|
int flag;
|
||||||
|
__sigset_t wsig;
|
||||||
|
|
||||||
|
if(sigsetsize != sizeof(sigset_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if(set &&
|
if(set &&
|
||||||
how != SIG_BLOCK &&
|
how != SIG_BLOCK &&
|
||||||
@@ -1084,23 +1097,32 @@ SYSCALL_DECLARE(rt_sigprocmask)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
flag = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
flag = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
||||||
if(oldset)
|
if(oldset){
|
||||||
oldset->__val[0] = proc->sigmask.__val[0];
|
wsig = proc->sigmask.__val[0];
|
||||||
|
if(copy_to_user(proc, oldset->__val, &wsig, sizeof wsig))
|
||||||
|
goto fault;
|
||||||
|
}
|
||||||
if(set){
|
if(set){
|
||||||
|
if(copy_from_user(proc, &wsig, set->__val, sizeof wsig))
|
||||||
|
goto fault;
|
||||||
switch(how){
|
switch(how){
|
||||||
case SIG_BLOCK:
|
case SIG_BLOCK:
|
||||||
proc->sigmask.__val[0] |= set->__val[0];
|
proc->sigmask.__val[0] |= wsig;
|
||||||
break;
|
break;
|
||||||
case SIG_UNBLOCK:
|
case SIG_UNBLOCK:
|
||||||
proc->sigmask.__val[0] &= ~set->__val[0];
|
proc->sigmask.__val[0] &= ~wsig;
|
||||||
break;
|
break;
|
||||||
case SIG_SETMASK:
|
case SIG_SETMASK:
|
||||||
proc->sigmask.__val[0] = set->__val[0];
|
proc->sigmask.__val[0] = wsig;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
proc->supmask = proc->sigmask;
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, flag);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, flag);
|
||||||
return 0;
|
return 0;
|
||||||
|
fault:
|
||||||
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, flag);
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigpending)
|
SYSCALL_DECLARE(rt_sigpending)
|
||||||
@@ -1112,6 +1134,10 @@ SYSCALL_DECLARE(rt_sigpending)
|
|||||||
__sigset_t w = 0;
|
__sigset_t w = 0;
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
sigset_t *set = (sigset_t *)ihk_mc_syscall_arg0(ctx);
|
sigset_t *set = (sigset_t *)ihk_mc_syscall_arg0(ctx);
|
||||||
|
size_t sigsetsize = (size_t)ihk_mc_syscall_arg1(ctx);
|
||||||
|
|
||||||
|
if (sigsetsize > sizeof(sigset_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
lock = &proc->sigshared->lock;
|
lock = &proc->sigshared->lock;
|
||||||
head = &proc->sigshared->sigpending;
|
head = &proc->sigshared->sigpending;
|
||||||
@@ -1129,23 +1155,39 @@ SYSCALL_DECLARE(rt_sigpending)
|
|||||||
}
|
}
|
||||||
ihk_mc_spinlock_unlock(lock, flag);
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
|
|
||||||
set->__val[0] = w;
|
if(copy_to_user(proc, set->__val, &w, sizeof w))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigtimedwait)
|
SYSCALL_DECLARE(rt_sigtimedwait)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
sigset_t *
|
||||||
|
siginfo_t *
|
||||||
|
struct timespec *
|
||||||
|
size_t
|
||||||
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigqueueinfo)
|
SYSCALL_DECLARE(rt_sigqueueinfo)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
pid_t
|
||||||
|
int
|
||||||
|
siginfo_t *
|
||||||
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigsuspend)
|
SYSCALL_DECLARE(rt_sigsuspend)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
sigset_t *
|
||||||
|
size_t
|
||||||
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1276,8 +1318,10 @@ SYSCALL_DECLARE(getrlimit)
|
|||||||
|
|
||||||
case RLIMIT_STACK:
|
case RLIMIT_STACK:
|
||||||
dkprintf("[%d] getrlimit() RLIMIT_STACK\n", ihk_mc_get_processor_id());
|
dkprintf("[%d] getrlimit() RLIMIT_STACK\n", ihk_mc_get_processor_id());
|
||||||
rlm->rlim_cur = proc->rlimit_stack.rlim_cur;
|
if(copy_to_user(proc, &rlm->rlim_cur, &proc->rlimit_stack.rlim_cur, sizeof rlm->rlim_cur))
|
||||||
rlm->rlim_max = proc->rlimit_stack.rlim_max;
|
return -EFAULT;
|
||||||
|
if(copy_to_user(proc, &rlm->rlim_max, &proc->rlimit_stack.rlim_max, sizeof rlm->rlim_max))
|
||||||
|
return -EFAULT;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user