fix general protection fault caused by SIGALARM

This commit is contained in:
Tomoki Shirasawa
2013-12-16 13:45:45 +09:00
parent 8e4cbfeea1
commit 96576aaee7
3 changed files with 75 additions and 13 deletions

View File

@@ -98,6 +98,8 @@ SYSCALL_DECLARE(rt_sigreturn)
}
extern struct cpu_local_var *clv;
extern unsigned long do_kill(int pid, int sig);
extern void interrupt_syscall();
void
check_signal(unsigned long rc, unsigned long *regs)
@@ -123,7 +125,6 @@ check_signal(unsigned long rc, unsigned long *regs)
else{
rc = regs[9]; /* rax */
}
k = proc->sighandler->action + sig - 1;
if(k->sa.sa_handler == (void *)1){
@@ -133,6 +134,13 @@ check_signal(unsigned long rc, unsigned long *regs)
else if(k->sa.sa_handler){
unsigned long *usp; /* user stack */
if(regs[14] & 0x8000000000000000){ // kernel addr
proc->signal = sig;
interrupt_syscall();
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
return;
}
usp = (void *)regs[14];
memcpy(proc->sigstack, regs, 128);
proc->sigrc = rc;
@@ -153,8 +161,6 @@ check_signal(unsigned long rc, unsigned long *regs)
}
}
extern unsigned long do_kill(int pid, int sig);
unsigned long
do_kill(int pid, int sig)
{
@@ -187,4 +193,5 @@ set_signal(int sig, unsigned long *regs)
if(proc == NULL || proc->pid == 0)
return;
proc->signal = sig;
interrupt_syscall();
}

View File

@@ -116,6 +116,11 @@ static int fd;
static char *altroot;
static const char rlimit_stack_envname[] = "MCKERNEL_RLIMIT_STACK";
pid_t gettid(void)
{
return syscall(SYS_gettid);
}
struct program_load_desc *load_elf(FILE *fp, char **interp_pathp)
{
Elf64_Ehdr hdr;
@@ -483,6 +488,8 @@ struct thread_data_s {
int ret;
pthread_mutex_t *lock;
} *thread_data;
int ncpu;
pid_t master_tid;
static void *main_loop_thread_func(void *arg)
{
@@ -498,6 +505,9 @@ sendsig(int sig)
{
unsigned long param;
if(gettid() != master_tid)
return;
param = ((unsigned long)sig) << 32 | ((unsigned long)getpid());
if (ioctl(fd, MCEXEC_UP_SEND_SIGNAL, param) != 0) {
perror("send_signal");
@@ -562,7 +572,6 @@ int main(int argc, char **argv)
char **a;
char *p;
int i;
int ncpu;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
FILE *interp = NULL;
char *interp_path;
@@ -766,6 +775,18 @@ int main(int argc, char **argv)
__dprint("mccmd server initialized\n");
#endif
master_tid = gettid();
for (i = 1; i <= 64; i++)
if (i != SIGCHLD && i != SIGCONT && i != SIGSTOP &&
i != SIGTSTP && i != SIGTTIN && i != SIGTTOU){
struct sigaction act;
sigaction(i, NULL, &act);
act.sa_handler = sendsig;
act.sa_flags &= ~(SA_RESTART);
sigaction(i, &act, NULL);
}
for (i = 0; i <= ncpu; ++i) {
int ret;
@@ -787,11 +808,6 @@ int main(int argc, char **argv)
return 1;
}
for (i = 1; i <= 64; i++)
if (i != SIGCHLD && i != SIGCONT && i != SIGSTOP &&
i != SIGTSTP && i != SIGTTIN && i != SIGTTOU)
signal(i, sendsig);
for (i = 0; i <= ncpu; ++i) {
pthread_join(thread_data[i].thread_id, NULL);
}
@@ -851,6 +867,21 @@ do_generic_syscall(
return ret;
}
static void
kill_thread(unsigned long cpu)
{
if(cpu >= 0 && cpu < ncpu){
pthread_kill(thread_data[cpu].thread_id, SIGINT);
}
else{
int i;
for (i = 0; i < ncpu; ++i) {
pthread_kill(thread_data[i].thread_id, SIGINT);
}
}
}
#define SET_ERR(ret) if (ret == -1) ret = -errno
int main_loop(int fd, int cpu, pthread_mutex_t *lock)
@@ -860,10 +891,10 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock)
char *fn;
int sig;
int term;
w.cpu = cpu;
while (ioctl(fd, MCEXEC_UP_WAIT_SYSCALL, (unsigned long)&w) == 0) {
while (((ret = ioctl(fd, MCEXEC_UP_WAIT_SYSCALL, (unsigned long)&w)) == 0) || (ret == -1 && errno == EINTR)) {
/* Don't print when got a msg to stdout */
if (!(w.sr.number == __NR_write && w.sr.args[0] == 1))
@@ -909,6 +940,10 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock)
w.sr.args[0], sizeof(struct timeval));
break;
case __NR_kill: // interrupt syscall
kill_thread(w.sr.args[0]);
do_syscall_return(fd, cpu, 0, 0, 0, 0, 0);
break;
case __NR_exit:
case __NR_exit_group:
sig = 0;
@@ -963,6 +998,8 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock)
}
#endif
default:
fprintf(stderr, "syscall=%ld\n", w.sr.number);
fflush(stderr);
ret = do_generic_syscall(&w);
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
break;

View File

@@ -108,7 +108,8 @@ static void send_syscall(struct syscall_request *req)
struct ihk_ikc_channel_desc *syscall_channel;
int cpu;
if(req->number == __NR_exit_group){
if(req->number == __NR_exit_group ||
req->number == __NR_kill){ // interrupt syscall
extern int num_processors;
scp = &get_cpu_local_var(0)->scp2;
@@ -160,7 +161,8 @@ int do_syscall(struct syscall_request *req, ihk_mc_user_context_t *ctx)
ihk_mc_get_processor_id(),
req->number);
if(req->number == __NR_exit_group){
if(req->number == __NR_exit_group ||
req->number == __NR_kill){ // interrupt syscall
scp = &get_cpu_local_var(0)->scp2;
}
else{
@@ -250,6 +252,22 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
schedule();
}
void
interrupt_syscall()
{
ihk_mc_user_context_t ctx;
long lerror;
ihk_mc_syscall_arg0(&ctx) = ihk_mc_get_processor_id();
ihk_mc_syscall_arg1(&ctx) = 0;
lerror = syscall_generic_forwarding(__NR_kill, &ctx);
if (lerror) {
kprintf("clear_host_pte failed. %ld\n", lerror);
}
return;
}
SYSCALL_DECLARE(exit_group)
{
#if 0