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 struct cpu_local_var *clv;
extern unsigned long do_kill(int pid, int sig);
extern void interrupt_syscall();
void void
check_signal(unsigned long rc, unsigned long *regs) check_signal(unsigned long rc, unsigned long *regs)
@@ -123,7 +125,6 @@ check_signal(unsigned long rc, unsigned long *regs)
else{ else{
rc = regs[9]; /* rax */ rc = regs[9]; /* rax */
} }
k = proc->sighandler->action + sig - 1; k = proc->sighandler->action + sig - 1;
if(k->sa.sa_handler == (void *)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){ else if(k->sa.sa_handler){
unsigned long *usp; /* user stack */ 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]; usp = (void *)regs[14];
memcpy(proc->sigstack, regs, 128); memcpy(proc->sigstack, regs, 128);
proc->sigrc = rc; 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 unsigned long
do_kill(int pid, int sig) do_kill(int pid, int sig)
{ {
@@ -187,4 +193,5 @@ set_signal(int sig, unsigned long *regs)
if(proc == NULL || proc->pid == 0) if(proc == NULL || proc->pid == 0)
return; return;
proc->signal = sig; proc->signal = sig;
interrupt_syscall();
} }

View File

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

View File

@@ -108,7 +108,8 @@ static void send_syscall(struct syscall_request *req)
struct ihk_ikc_channel_desc *syscall_channel; struct ihk_ikc_channel_desc *syscall_channel;
int cpu; int cpu;
if(req->number == __NR_exit_group){ if(req->number == __NR_exit_group ||
req->number == __NR_kill){ // interrupt syscall
extern int num_processors; extern int num_processors;
scp = &get_cpu_local_var(0)->scp2; 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(), ihk_mc_get_processor_id(),
req->number); 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; scp = &get_cpu_local_var(0)->scp2;
} }
else{ else{
@@ -250,6 +252,22 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
schedule(); 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) SYSCALL_DECLARE(exit_group)
{ {
#if 0 #if 0