int get_page_fault_mem(struct rusage & ruse, pid_t & pidApp) { //java use pagefault int m_vmpeak, m_vmdata, m_minflt; m_minflt = ruse.ru_minflt * getpagesize(); if (0 && DEBUG) { m_vmpeak = get_proc_status(pidApp, "VmPeak:"); m_vmdata = get_proc_status(pidApp, "VmData:"); printf("VmPeak:%d KB VmData:%d KB minflt:%d KB\n", m_vmpeak, m_vmdata, m_minflt >> 10); }
int watch_solution(pid_t pid, int *flag) { struct rusage usage; struct user_regs_struct regs; long orig_eax, eax; int status, vm, signo, insyscall; insyscall = 1; while (1) { wait4(-1, &status, 0, &usage); vm = get_proc_status(pid, "VmPeak"); if (vm > AS_LMT) { *flag = ML; ptrace(PTRACE_KILL, pid, NULL, NULL); break; } if (WIFEXITED(status)) { break; } if (get_file_size("error.out")) { *flag = RE; ptrace(PTRACE_KILL, pid, NULL, NULL); } if (WIFSIGNALED(status)) { signo = WTERMSIG(status); switch (signo) { case SIGCHLD: case SIGALRM: case SIGKILL: case SIGXCPU: *flag = TL; break; case SIGXFSZ: *flag = OL; break; default: *flag = RE; break; } ptrace(PTRACE_KILL, pid, NULL, NULL); break; } orig_eax = ptrace(PTRACE_PEEKUSER, pid, 4*ORIG_EAX, NULL); if (insyscall && orig_eax>0) { if (call_counter[orig_eax] > syscall_limit[orig_eax]) { *flag = RE; fprintf(stderr, "process %d is calling %s which is not allowed\n", pid,\ syscall_list[orig_eax]); ptrace(PTRACE_KILL, pid, NULL, NULL); break; } else { printf("process %d is calling %s\n", pid, syscall_list[orig_eax]); } } insyscall = 1-insyscall; ptrace(PTRACE_SYSCALL, pid, NULL, NULL); }//while return 0; }
int watch_solution(pid_t pid, int *flag) { struct rusage usage; struct user_regs_struct regs; long orig_eax, eax; int status, vm, signo, insyscall, ptraceflag; insyscall = 1; while (1) { pid_t pid = wait4(-1, &status, 0, &usage); ptraceflag = 0; vm = get_proc_status(pid, "VmPeak"); if (vm > AS_LMT) { *flag = CODE_ML; ptrace(PTRACE_KILL, pid, NULL, NULL); break; } if (WIFEXITED(status)) { break; } if (get_file_size(RE_OUT)) { *flag = CODE_RE; ptrace(PTRACE_KILL, pid, NULL, NULL); } if (WIFSTOPPED(status)) { signo = WSTOPSIG(status); //psignal(signo, "in stopped"); switch (signo) { case SIGCHLD: case SIGALRM: case SIGKILL: case SIGXCPU: *flag = CODE_TL; break; case SIGXFSZ: *flag = CODE_OL; break; case SIGTRAP: ptraceflag = 1; break; default: *flag = CODE_RE; break; } if (ptraceflag == 0) { ptrace(PTRACE_KILL, pid, NULL, NULL); break; } } if (ptraceflag == 0 && WIFSIGNALED(status)) { signo = WTERMSIG(status); //psignal(signo, "in signaled"); switch (signo) { case SIGCHLD: case SIGALRM: case SIGKILL: case SIGXCPU: *flag = CODE_TL; break; case SIGXFSZ: *flag = CODE_OL; break; default: *flag = CODE_RE; break; } ptrace(PTRACE_KILL, pid, NULL, NULL); break; } orig_eax = ptrace(PTRACE_PEEKUSER, pid, 4*ORIG_EAX, NULL); if (insyscall && orig_eax>0) { if (call_counter[orig_eax] > syscall_limit[orig_eax]) { *flag = CODE_RE; write_log(LOG, 0, "process %d is calling %s which is not allowed", pid, syscall_list[orig_eax]); write_log(LOG, 0, "process %d is calling %s", pid, syscall_list[orig_eax]); ptrace(PTRACE_KILL, pid, NULL, NULL); break; } else { //write_log(LOG, 0, "process %d is calling %s\n", pid, syscall_list[orig_eax]); } } insyscall = 1-insyscall; ptrace(PTRACE_SYSCALL, pid, NULL, NULL); }//while return 0; }
void OS_get_table() { /* dir walker storage */ DIR *dir; struct dirent *dir_ent, *dir_result; /* all our storage is going to be here */ struct obstack mem_pool; /* container for scaped process values */ struct procstat *prs; /* string containing our local copy of format_str, elements will be * lower cased if we are able to figure them out */ char *format_str; /* initlize a small memory pool for this function */ obstack_init(&mem_pool); /* put the dirent on the obstack, since it's rather large */ dir_ent = obstack_alloc(&mem_pool, sizeof(struct dirent)); if ((dir = opendir("/proc")) == NULL) return; /* Iterate through all the process entries (numeric) under /proc */ while(readdir_r(dir, dir_ent, &dir_result) == 0 && dir_result) { /* Only look at this file if it's a proc id; that is, all numbers */ if(!is_pid(dir_result->d_name)) continue; /* allocate container for storing process values */ prs = obstack_alloc(&mem_pool, sizeof(struct procstat)); bzero(prs, sizeof(struct procstat)); /* intilize the format string */ obstack_printf(&mem_pool, get_string(STR_DEFAULT_FORMAT)); obstack_1grow(&mem_pool, '\0'); format_str = (char *) obstack_finish(&mem_pool); /* get process' uid/guid */ get_user_info(dir_result->d_name, format_str, prs, &mem_pool); /* scrape /proc/${pid}/stat */ if (get_proc_stat(dir_result->d_name, format_str, prs, &mem_pool) == false) { /* did the pid directory go away mid flight? */ if (pid_exists(dir_result->d_name, &mem_pool) == false) continue; } /* correct values (times) found in /proc/${pid}/stat */ fixup_stat_values(format_str, prs); /* get process' cmndline */ get_proc_cmndline(dir_result->d_name, format_str, prs, &mem_pool); /* get process' cwd & exec values from the symblink */ eval_link(dir_result->d_name, "cwd", F_CWD, &prs->cwd, format_str, &mem_pool); eval_link(dir_result->d_name, "exe", F_EXEC, &prs->exec, format_str, &mem_pool); /* scapre from /proc/{$pid}/status */ get_proc_status(dir_result->d_name, format_str, prs, &mem_pool); /* calculate precent cpu & mem values */ calc_prec(format_str, prs, &mem_pool); /* Go ahead and bless into a perl object */ bless_into_proc(format_str, field_names, prs->uid, prs->gid, prs->pid, prs->comm, prs->ppid, prs->pgrp, prs->sid, prs->tty, prs->flags, prs->minflt, prs->cminflt, prs->majflt, prs->cmajflt, prs->utime, prs->stime, prs->cutime, prs->cstime, prs->priority, prs->start_time, prs->vsize, prs->rss, prs->wchan, prs->time, prs->ctime, prs->state, prs->euid, prs->suid, prs->fuid, prs->egid, prs->sgid, prs->fgid, prs->pctcpu, prs->pctmem, prs->cmndline, prs->exec, prs->cwd ); /* we want a new prs, for the next itteration */ obstack_free(&mem_pool, prs); } closedir(dir); /* free all our tempoary memory */ obstack_free(&mem_pool, NULL); }
void trace_submit(int pid, int *status, int *usedtime, int *usedmem, int timelimit, int casetimelimit, int memlimit, int language, int spj) { int pstat, sig, ecode; struct user_regs_struct regs; struct rusage usage; int tmpmem, tmptime, sub=0; while(1) { wait4(pid, &pstat, 0, &usage); if(language==LANG_JAVA)tmpmem=(usage.ru_minflt*getpagesize())>>10; else tmpmem=get_proc_status(pid, "VmPeak:"); if(tmpmem>*usedmem)*usedmem=tmpmem; if(get_file_size("error.out")) { *status=JG_RE; ptrace(PTRACE_KILL, pid, NULL, NULL); break; } if(!spj&&get_file_size("user.out")>get_file_size("data.out")*2+1024) { *status=JG_OL; ptrace(PTRACE_KILL, pid, NULL, NULL); break; } if(WIFEXITED(pstat))break; ecode=WEXITSTATUS(pstat); if(ecode==0x05||ecode==0); else { if(*status==JG_AC) { switch(ecode) { case SIGCHLD: case SIGALRM: alarm(0); case SIGKILL: case SIGXCPU: *status=JG_TL; break; case SIGXFSZ: *status=JG_OL; break; default: *status=JG_RE; } print_runtime_error(strsignal(ecode)); } ptrace(PTRACE_KILL, pid, NULL, NULL); break; } if(WIFSIGNALED(pstat)) { sig=WTERMSIG(pstat); if(*status==JG_AC) { switch(sig) { case SIGCHLD: case SIGALRM: alarm(0); case SIGKILL: case SIGXCPU: *status=JG_TL; break; case SIGXFSZ: *status=JG_OL; break; default: *status=JG_RE; } print_runtime_error(strsignal(sig)); } break; } ptrace(PTRACE_GETREGS, pid, NULL, ®s); if(oksyscall[regs.REG_SYSCALL]==0) { *status=JG_RE; char msg[MAXLINE+1]; sprintf(msg, "does not allow syscall id:%d name:%s", (int)regs.REG_SYSCALL, syscallname[regs.REG_SYSCALL]); print_runtime_error(msg); ptrace(PTRACE_KILL, pid, NULL, NULL); break; } else if(sub==1&&oksyscall[regs.REG_SYSCALL]>0) --oksyscall[regs.REG_SYSCALL]; sub=1-sub; ptrace(PTRACE_SYSCALL, pid, NULL, NULL); }
OJ_Reinfo Sandbox::watch_cpp(pid_t pid) { OJ_Reinfo res; try{ string outfile = m_info.pro_id + "-" + m_info.title_in + ".out"; string ansfile = "../../" + PH_IO + m_info.pro_id + "/" + m_info.title_in + ".out"; int topmemory = 0; int tempmemory = 0; int status = 0 ; int sig = 0; int exitcode = 0; struct user_regs_struct reg; struct rusage ruse; if(topmemory==0) { topmemory= get_proc_status(pid, "VmRSS:") << 10; } while (1){ wait4(pid, &status, WUNTRACED, &ruse); tempmemory = get_proc_status(pid, "VmPeak:") << 10; if (tempmemory > topmemory){ topmemory = tempmemory; } if (topmemory > m_info.mem_lim * STD_KB){ throw (OJ_ERROR) OJ_MLE; ptrace(PTRACE_KILL, pid, NULL, NULL); } if (0 != WIFEXITED(status)){ //子进程正常退出 break; } if (get_file_size(outfile.c_str()) > get_file_size(ansfile.c_str()) * 2){ throw (OJ_ERROR) OJ_OLE; ptrace(PTRACE_KILL, pid, NULL, NULL); break; } exitcode = WEXITSTATUS(status); if (exitcode != 0x05 && exitcode != 0){/*exitcode == 5 waiting for next CPU allocation */ switch (exitcode) { case SIGCHLD: alarm(0); case SIGALRM: case SIGKILL: case SIGXCPU: throw (OJ_ERROR) OJ_TLE; break; case SIGXFSZ: throw (OJ_ERROR) OJ_OLE; break; default: throw (OJ_ERROR) OJ_RE; break; } } if (WIFSIGNALED(status)) { sig = WTERMSIG(status); switch (sig) { case SIGCHLD: alarm(0); case SIGALRM: case SIGKILL: case SIGXCPU: throw (OJ_ERROR) OJ_TLE; break; case SIGXFSZ: throw (OJ_ERROR) OJ_OLE; break; default: throw (OJ_ERROR) OJ_RE; break; } } /*检查系统调用*/ ptrace(PTRACE_GETREGS, pid, NULL, ®); // if (call_counter[reg.REG_SYSCALL] ){ // //call_counter[reg.REG_SYSCALL]--; // }else if (0) { // call_counter[reg.REG_SYSCALL] = 1; // }else { //do not limit JVM syscall for using different JVM // throw (OJ_ERROR) OJ_PF; // ptrace(PTRACE_KILL, pidApp, NULL, NULL); // } // int usedtime = 0; // printf("%lld\n%lld\n%lld\n%lld\n",ruse.ru_utime.tv_sec,ruse.ru_utime.tv_usec,ruse.ru_stime.tv_sec,ruse.ru_stime.tv_usec); // usedtime += (ruse.ru_stime.tv_sec * 1000 + ruse.ru_stime?? ptrace(PTRACE_SYSCALL, pid, NULL, NULL); } ptrace(PTRACE_KILL, pid, NULL, NULL); res.time = 0; res.memory = topmemory/1024; // cout<<res.memory<<endl; }catch(OJ_ERROR msg){ ptrace(PTRACE_KILL, pid, NULL, NULL); cerr<<"运行程序时出错"<<endl; throw ; } return res; }
void watch(pid_t pid,enum judge_status &judge_status,long &max_used_memory,long &used_time,long error_size) { long init_used_time = used_time; long used_memory; init_syscall_limit(); int status; struct rusage ru; while(1) { pid_t pid_ret = wait4(pid,&status,0,&ru); if(pid_ret != pid) error_report("wait4"); //TLE used_time = init_used_time + ru.ru_utime.tv_sec * 100 + ru.ru_utime.tv_usec / 1000; if(used_time >= time_limit * 1000) { judge_status = JUDGE_TLE; goto send_kill; } //MLE if (language == LANG_JAVA) { // JVM GC ask VM before need, so used kernel page fault times and page size. used_memory = get_page_fault_memory(ru, pid); } else { // other use VmPeak used_memory = get_proc_status(pid, "VmPeak:") << 10; } if(used_memory > max_used_memory) max_used_memory = used_memory; if(max_used_memory > memory_limit) { judge_status = JUDGE_MLE; goto send_kill; } //RE 判断stderr if(get_file_size(code_error_path) > error_size) { judge_status = JUDGE_RE; goto send_kill; } //进程退出 if(WIFEXITED(status)) { int exitcode = WEXITSTATUS(status); if(exitcode != 0) { judge_status = JUDGE_RE; } break; } //未捕捉到信号而中止 if(WIFSIGNALED(status)) { int sigcode = WTERMSIG(status); break; } // 未捕捉信号而暂停 // 子进程被追踪(ptrace)或调用WUN-TRACED时才可能发生 if (WIFSTOPPED(status)) { int sigcode = WSTOPSIG(status); switch (sigcode) { case SIGSTOP: // JAVA 使用 SIGSTOP 等待下次 CPU 运行 if (language != LANG_JAVA) { judge_status = JUDGE_RE; goto send_kill; } case SIGTRAP: // c++ case 语句中不能出现带初始化的变量声明 unsigned long syscall; syscall = get_syscall(pid); //printf("System call: %lu\n", syscall); switch (check_syscall(syscall)) { case 0: judge_status = JUDGE_RE; goto send_kill; case 1: ptrace(PTRACE_SYSCALL, pid, NULL, NULL); break; case 2: //ptrace(PTRACE_SETREGS, pid, NULL, NULL); break; } break; case SIGSEGV: judge_status = JUDGE_MLE; goto send_kill; case SIGCHLD: case SIGALRM: alarm(0); case SIGXCPU: case SIGKILL: judge_status = JUDGE_TLE; goto send_kill; case SIGXFSZ: judge_status = JUDGE_OLE; goto send_kill; default: judge_status = JUDGE_SE; goto send_kill; } } } return; send_kill: ptrace(PTRACE_KILL,pid,NULL,NULL); }