support sigaltstack
This commit is contained in:
@ -33,31 +33,28 @@ struct sigaction {
|
|||||||
sigset_t sa_mask;
|
sigset_t sa_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
//// work in progress
|
#define SA_NOCLDSTOP 0x00000001u
|
||||||
struct sigbackup {
|
#define SA_NOCLDWAIT 0x00000002u
|
||||||
unsigned long rc; // return code of rt_sigreturn (rax)
|
#define SA_NODEFER 0x40000000u
|
||||||
void *uctx;
|
#define SA_ONSTACK 0x08000000u
|
||||||
sigset_t mask;
|
#define SA_RESETHAND 0x80000000u
|
||||||
double fpregs[16];
|
#define SA_RESTART 0x10000000u
|
||||||
|
#define SA_SIGINFO 0x00000004u
|
||||||
};
|
|
||||||
////
|
|
||||||
|
|
||||||
struct k_sigaction {
|
struct k_sigaction {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sigstack {
|
|
||||||
void *ss_sp;
|
|
||||||
int ss_onstack;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct sigaltstack {
|
typedef struct sigaltstack {
|
||||||
void *ss_sp;
|
void *ss_sp;
|
||||||
int ss_flags;
|
int ss_flags;
|
||||||
size_t ss_size;
|
size_t ss_size;
|
||||||
} stack_t;
|
} stack_t;
|
||||||
|
|
||||||
|
#define MINSIGSTKSZ 2048
|
||||||
|
#define SS_ONSTACK 1
|
||||||
|
#define SS_DISABLE 2
|
||||||
|
|
||||||
typedef union sigval {
|
typedef union sigval {
|
||||||
int sival_int;
|
int sival_int;
|
||||||
void *sival_ptr;
|
void *sival_ptr;
|
||||||
|
|||||||
@ -121,6 +121,8 @@ fault:
|
|||||||
struct sigsp {
|
struct sigsp {
|
||||||
struct x86_regs regs;
|
struct x86_regs regs;
|
||||||
unsigned long sigrc;
|
unsigned long sigrc;
|
||||||
|
unsigned long sigmask;
|
||||||
|
int ssflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigreturn)
|
SYSCALL_DECLARE(rt_sigreturn)
|
||||||
@ -133,8 +135,9 @@ SYSCALL_DECLARE(rt_sigreturn)
|
|||||||
asm("movq %%gs:132, %0" : "=r" (regs));
|
asm("movq %%gs:132, %0" : "=r" (regs));
|
||||||
--regs;
|
--regs;
|
||||||
|
|
||||||
proc->sigmask.__val[0] = proc->supmask.__val[0];
|
|
||||||
sigsp = (struct sigsp *)regs->rsp;
|
sigsp = (struct sigsp *)regs->rsp;
|
||||||
|
proc->sigmask.__val[0] = sigsp->sigmask;
|
||||||
|
proc->sigstack.ss_flags = sigsp->ssflags;
|
||||||
if(copy_from_user(proc, regs, &sigsp->regs, sizeof(struct x86_regs)))
|
if(copy_from_user(proc, regs, &sigsp->regs, sizeof(struct x86_regs)))
|
||||||
return rc;
|
return rc;
|
||||||
copy_from_user(proc, &rc, &sigsp->sigrc, sizeof(long));
|
copy_from_user(proc, &rc, &sigsp->sigrc, sizeof(long));
|
||||||
@ -178,8 +181,20 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
|
|||||||
else if(k->sa.sa_handler){
|
else if(k->sa.sa_handler){
|
||||||
unsigned long *usp; /* user stack */
|
unsigned long *usp; /* user stack */
|
||||||
struct sigsp *sigsp;
|
struct sigsp *sigsp;
|
||||||
|
int ssflags = proc->sigstack.ss_flags;
|
||||||
|
unsigned long mask = (unsigned long)proc->sigmask.__val[0];
|
||||||
|
|
||||||
|
if((k->sa.sa_flags & SA_ONSTACK) &&
|
||||||
|
!(proc->sigstack.ss_flags & SS_DISABLE) &&
|
||||||
|
!(proc->sigstack.ss_flags & SS_ONSTACK)){
|
||||||
|
unsigned long lsp;
|
||||||
|
lsp = ((unsigned long)(((char *)proc->sigstack.ss_sp) + proc->sigstack.ss_size)) & 0xfffffffffffffff8UL;
|
||||||
|
usp = (unsigned long *)lsp;
|
||||||
|
proc->sigstack.ss_flags |= SS_ONSTACK;
|
||||||
|
}
|
||||||
|
else{
|
||||||
usp = (unsigned long *)regs->rsp;
|
usp = (unsigned long *)regs->rsp;
|
||||||
|
}
|
||||||
sigsp = ((struct sigsp *)usp) - 1;
|
sigsp = ((struct sigsp *)usp) - 1;
|
||||||
if(copy_to_user(proc, &sigsp->regs, regs, sizeof(struct x86_regs)) ||
|
if(copy_to_user(proc, &sigsp->regs, regs, sizeof(struct x86_regs)) ||
|
||||||
copy_to_user(proc, &sigsp->sigrc, &rc, sizeof(long))){
|
copy_to_user(proc, &sigsp->sigrc, &rc, sizeof(long))){
|
||||||
@ -188,6 +203,8 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
|
|||||||
terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp);
|
terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
sigsp->sigmask = mask;
|
||||||
|
sigsp->ssflags = ssflags;
|
||||||
|
|
||||||
usp = (unsigned long *)sigsp;
|
usp = (unsigned long *)sigsp;
|
||||||
usp--;
|
usp--;
|
||||||
@ -197,8 +214,8 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
|
|||||||
regs->rip = (unsigned long)k->sa.sa_handler;
|
regs->rip = (unsigned long)k->sa.sa_handler;
|
||||||
regs->rsp = (unsigned long)usp;
|
regs->rsp = (unsigned long)usp;
|
||||||
|
|
||||||
kfree(pending);
|
|
||||||
proc->sigmask.__val[0] |= pending->sigmask.__val[0];
|
proc->sigmask.__val[0] |= pending->sigmask.__val[0];
|
||||||
|
kfree(pending);
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -342,7 +359,7 @@ do_kill(int pid, int tid, int sig)
|
|||||||
mask = __sigmask(sig);
|
mask = __sigmask(sig);
|
||||||
pending = NULL;
|
pending = NULL;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if(sig < 34){
|
if(sig < 33){ // SIGRTMIN - SIGRTMAX
|
||||||
list_for_each_entry(pending, head, list){
|
list_for_each_entry(pending, head, list){
|
||||||
if(pending->sigmask.__val[0] == mask)
|
if(pending->sigmask.__val[0] == mask)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -173,7 +173,7 @@ struct process {
|
|||||||
int tid;
|
int tid;
|
||||||
volatile int sigevent;
|
volatile int sigevent;
|
||||||
sigset_t sigmask;
|
sigset_t sigmask;
|
||||||
sigset_t supmask;
|
stack_t sigstack;
|
||||||
ihk_spinlock_t sigpendinglock;
|
ihk_spinlock_t sigpendinglock;
|
||||||
struct list_head sigpending;
|
struct list_head sigpending;
|
||||||
struct sig_shared *sigshared;
|
struct sig_shared *sigshared;
|
||||||
|
|||||||
@ -148,6 +148,10 @@ struct process *create_process(unsigned long user_pc)
|
|||||||
ihk_mc_spinlock_init(&proc->sigpendinglock);
|
ihk_mc_spinlock_init(&proc->sigpendinglock);
|
||||||
INIT_LIST_HEAD(&proc->sigpending);
|
INIT_LIST_HEAD(&proc->sigpending);
|
||||||
|
|
||||||
|
proc->sigstack.ss_sp = NULL;
|
||||||
|
proc->sigstack.ss_flags = SS_DISABLE;
|
||||||
|
proc->sigstack.ss_size = 0;
|
||||||
|
|
||||||
ihk_mc_init_user_process(&proc->ctx, &proc->uctx,
|
ihk_mc_init_user_process(&proc->ctx, &proc->uctx,
|
||||||
((char *)proc) +
|
((char *)proc) +
|
||||||
KERNEL_STACK_NR_PAGES * PAGE_SIZE, user_pc, 0);
|
KERNEL_STACK_NR_PAGES * PAGE_SIZE, user_pc, 0);
|
||||||
@ -219,6 +223,10 @@ struct process *clone_process(struct process *org, unsigned long pc,
|
|||||||
ihk_atomic_inc(&org->vm->refcount);
|
ihk_atomic_inc(&org->vm->refcount);
|
||||||
proc->vm = org->vm;
|
proc->vm = org->vm;
|
||||||
|
|
||||||
|
proc->sigstack.ss_sp = NULL;
|
||||||
|
proc->sigstack.ss_flags = SS_DISABLE;
|
||||||
|
proc->sigstack.ss_size = 0;
|
||||||
|
|
||||||
proc->sighandler = org->sighandler;
|
proc->sighandler = org->sighandler;
|
||||||
ihk_atomic_inc(&org->sighandler->use);
|
ihk_atomic_inc(&org->sighandler->use);
|
||||||
|
|
||||||
|
|||||||
@ -1424,7 +1424,6 @@ SYSCALL_DECLARE(rt_sigprocmask)
|
|||||||
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:
|
fault:
|
||||||
@ -1587,15 +1586,28 @@ SYSCALL_DECLARE(sigaltstack)
|
|||||||
stack_t *oss = (stack_t *)ihk_mc_syscall_arg1(ctx);
|
stack_t *oss = (stack_t *)ihk_mc_syscall_arg1(ctx);
|
||||||
stack_t wss;
|
stack_t wss;
|
||||||
|
|
||||||
memset(&wss, '\0', sizeof wss);
|
|
||||||
if(oss)
|
if(oss)
|
||||||
if(copy_to_user(proc, oss, &wss, sizeof wss))
|
if(copy_to_user(proc, oss, &proc->sigstack, sizeof wss))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if(ss)
|
if(ss){
|
||||||
if(copy_from_user(proc, &wss, ss, sizeof wss))
|
if(copy_from_user(proc, &wss, ss, sizeof wss))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
if(wss.ss_flags != 0 && wss.ss_flags != SS_DISABLE)
|
||||||
|
return -EINVAL;
|
||||||
|
if(wss.ss_flags == SS_DISABLE){
|
||||||
|
proc->sigstack.ss_sp = NULL;
|
||||||
|
proc->sigstack.ss_flags = SS_DISABLE;
|
||||||
|
proc->sigstack.ss_size = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(wss.ss_size < MINSIGSTKSZ)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
memcpy(&proc->sigstack, &wss, sizeof wss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(madvise)
|
SYSCALL_DECLARE(madvise)
|
||||||
|
|||||||
Reference in New Issue
Block a user