int main(int argc, char* argv[]) { int f; struct bson_info* bson; int ret; fprintf_blue(stdout, "BSON Printer -- By: Wolfgang Richter " "<*****@*****.**>\n"); if (argc < 2) { fprintf_light_red(stderr, "Usage: %s <BSON file>\n", argv[0]); return EXIT_FAILURE; } fprintf_cyan(stdout, "Analyzing BSON File: %s\n", argv[1]); f = open(argv[1], O_RDONLY); if (f < 0) { fprintf_light_red(stderr, "Error opening BSON file.\n"); return EXIT_FAILURE; } bson = bson_init(); while ((ret = bson_readf(bson, f)) == 1) bson_print(stdout, bson); bson_cleanup(bson); check_syscall(close(f)); return EXIT_SUCCESS; }
static void sanity_check(const struct syscalltable *table, unsigned int nr) { unsigned int i; for (i = 0; i < nr; i++) check_syscall(table[i].entry); }
static void* reader_thread(void* dontcare) { char token = '!'; int sock = sockfds[1]; struct timeval ts; char c = '\0'; int i; gettimeofday(&ts, NULL); atomic_puts("r: acquiring mutex ..."); pthread_mutex_lock(&lock); atomic_puts("r: ... releasing mutex"); pthread_mutex_unlock(&lock); for (i = 0; i < 2; ++i) { atomic_puts("r: reading socket ..."); gettimeofday(&ts, NULL); check_syscall(1, read(sock, &c, sizeof(c))); atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); ++token; } /* TODO: readv() support */ atomic_puts("r: recv'ing socket ..."); gettimeofday(&ts, NULL); check_syscall(1, recv(sock, &c, sizeof(c), 0)); atomic_printf("r: ... recv'd '%c'\n", c); test_assert(c == token); ++token; atomic_puts("r: recvfrom'ing socket ..."); check_syscall(1, recvfrom(sock, &c, sizeof(c), 0, NULL, NULL)); atomic_printf("r: ... recvfrom'd '%c'\n", c); test_assert(c == token); ++token; { struct sockaddr_un addr; socklen_t addrlen = sizeof(addr); atomic_puts("r: recvfrom(&sock)'ing socket ..."); check_syscall(1, recvfrom(sock, &c, sizeof(c), 0, &addr, &addrlen)); atomic_printf("r: ... recvfrom'd '%c' from sock len:%d\n", c, addrlen); test_assert(c == token); /* socketpair() AF_LOCAL sockets don't identify * themselves. */ test_assert(addrlen == 0); ++token; } { struct mmsghdr mmsg = { { 0 } }; struct iovec data = { 0 }; int magic = ~msg_magic; int err, ret; data.iov_base = &magic; data.iov_len = sizeof(magic); mmsg.msg_hdr.msg_iov = &data; mmsg.msg_hdr.msg_iovlen = 1; struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN); mmsg.msg_hdr.msg_control = cmptr; mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN; atomic_puts("r: recvmsg with DONTWAIT ..."); ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT); err = errno; atomic_printf("r: ... returned %d (%s/%d)\n", ret, strerror(err), err); check_syscall(-1, ret); test_assert(EWOULDBLOCK == err); atomic_puts("r: recmsg'ing socket ..."); test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0)); atomic_printf("r: ... recvmsg'd 0x%x\n", magic); test_assert(msg_magic == magic); int fd = *(int*)CMSG_DATA(cmptr); struct stat fs_new, fs_old; fstat(fd, &fs_new); fstat(STDERR_FILENO, &fs_old); // check if control msg was send successfully test_assert( fs_old.st_dev == fs_new.st_dev && fs_old.st_ino == fs_new.st_ino && fs_old.st_uid == fs_new.st_uid && fs_old.st_gid == fs_new.st_gid && fs_old.st_rdev == fs_new.st_rdev && fs_old.st_size == fs_new.st_size); magic = ~msg_magic; atomic_puts("r: recmmsg'ing socket ..."); breakpoint(); check_syscall(1, recvmmsg(sock, &mmsg, 1, 0, NULL)); atomic_printf("r: ... recvmmsg'd 0x%x (%u bytes)\n", magic, mmsg.msg_len); test_assert(msg_magic == magic); magic = ~msg_magic; #if defined(SYS_socketcall) struct recvmmsg_arg arg = { 0 }; arg.sockfd = sock; arg.msgvec = &mmsg; arg.vlen = 1; check_syscall(1, syscall(SYS_socketcall, SYS_RECVMMSG, (void*)&arg)); #elif defined(SYS_recvmmsg) check_syscall(1, syscall(SYS_recvmmsg, sock, &mmsg, 1, 0, NULL)); #else #error unable to call recvmmsg #endif atomic_printf("r: ... recvmmsg'd(by socketcall) 0x%x (%u bytes)\n", magic, mmsg.msg_len); test_assert(msg_magic == magic); free(cmptr); } { struct msghdr msg = { 0 }; struct iovec iovs[2]; char c1 = '\0', c2 = '\0'; iovs[0].iov_base = &c1; iovs[0].iov_len = sizeof(c1); iovs[1].iov_base = &c2; iovs[1].iov_len = sizeof(c2); msg.msg_iov = iovs; msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]); atomic_puts("r: recmsg'ing socket with two iovs ..."); check_syscall(2, recvmsg(sock, &msg, 0)); atomic_printf("r: ... recvmsg'd '%c' and '%c'\n", c1, c2); test_assert(c1 == token); token++; test_assert(c2 == token); token++; } { struct pollfd pfd; atomic_puts("r: polling socket ..."); pfd.fd = sock; pfd.events = POLLIN; gettimeofday(&ts, NULL); poll(&pfd, 1, -1); atomic_puts("r: ... done, doing nonblocking read ..."); check_syscall(1, read(sock, &c, sizeof(c))); atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); ++token; } { struct pollfd pfd; atomic_puts("r: polling socket ..."); pfd.fd = sock; pfd.events = POLLIN; gettimeofday(&ts, NULL); ppoll(&pfd, 1, NULL, NULL); atomic_puts("r: ... done, doing nonblocking read ..."); check_syscall(1, read(sock, &c, sizeof(c))); atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); ++token; } { fd_set fds; const struct timeval infinity = { 1 << 30, 0 }; struct timeval tv = infinity; int ret; atomic_puts("r: select()ing socket ..."); FD_ZERO(&fds); FD_SET(sock, &fds); #if defined(__i386__) struct select_arg arg = { 0 }; arg.n_fds = sock + 1; arg.read = &fds; arg.write = NULL; arg.except = NULL; arg.timeout = &tv; ret = syscall(SYS_select, &arg); #else ret = syscall(SYS_select, sock + 1, &fds, NULL, NULL, &tv); #endif atomic_printf("r: ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec, tv.tv_usec); check_syscall(1, ret); test_assert(FD_ISSET(sock, &fds)); test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec); atomic_puts("r: ... done, doing nonblocking read ..."); check_syscall(1, read(sock, &c, sizeof(c))); atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); ++token; } { fd_set fds; const struct timeval infinity = { 1 << 30, 0 }; struct timeval tv = infinity; int ret; atomic_puts("r: select()ing socket ..."); FD_ZERO(&fds); FD_SET(sock, &fds); ret = select(sock + 1, &fds, NULL, NULL, &tv); atomic_printf("r: ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec, tv.tv_usec); check_syscall(1, ret); test_assert(FD_ISSET(sock, &fds)); test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec); atomic_puts("r: ... done, doing nonblocking read ..."); check_syscall(1, read(sock, &c, sizeof(c))); atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); ++token; } { int epfd; struct epoll_event ev; atomic_puts("r: epolling socket ..."); test_assert(0 <= (epfd = epoll_create(1 /*num events*/))); ev.events = EPOLLIN; ev.data.fd = sock; gettimeofday(&ts, NULL); check_syscall(0, epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev)); check_syscall(1, epoll_wait(epfd, &ev, 1, -1)); atomic_puts("r: ... done, doing nonblocking read ..."); test_assert(sock == ev.data.fd); check_syscall(1, epoll_wait(epfd, &ev, 1, -1)); check_syscall(1, read(sock, &c, sizeof(c))); atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); ++token; close(epfd); } { char* buf = (char*)malloc(num_sockbuf_bytes); ssize_t nwritten = 0; struct iovec iov; ++token; memset(buf, token, num_sockbuf_bytes); atomic_printf("r: writing outbuf of size %zd ...\n", num_sockbuf_bytes); while (nwritten < num_sockbuf_bytes) { ssize_t this_write = write(sock, buf, num_sockbuf_bytes - nwritten); atomic_printf("r: wrote %zd bytes this time\n", this_write); nwritten += this_write; } ++token; memset(buf, token, num_sockbuf_bytes); iov.iov_base = buf; iov.iov_len = num_sockbuf_bytes; atomic_printf("r: writev()ing outbuf of size %zd ...\n", num_sockbuf_bytes); while (iov.iov_len > 0) { ssize_t this_write = writev(sock, &iov, 1); atomic_printf("r: wrote %zd bytes this time\n", this_write); iov.iov_len -= this_write; } free(buf); } atomic_puts("r: reading socket with masked signals ..."); { sigset_t old_mask, mask; sigfillset(&mask); check_syscall(0, pthread_sigmask(SIG_BLOCK, &mask, &old_mask)); check_syscall(1, read(sock, &c, sizeof(c))); check_syscall(0, pthread_sigmask(SIG_SETMASK, &old_mask, NULL)); } ++token; atomic_printf("r: ... read '%c'\n", c); test_assert(c == token); /* Make the main thread wait on our join() */ atomic_puts("r: sleeping ..."); usleep(500000); return NULL; }
int main(int argc, char* argv[]) { char token = '!'; struct timeval ts; pthread_t reader; int sock; gettimeofday(&ts, NULL); socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds); sock = sockfds[0]; pthread_mutex_lock(&lock); pthread_create(&reader, NULL, reader_thread, NULL); /* Make the reader thread wait on its pthread_mutex_lock() */ atomic_puts("M: sleeping ..."); usleep(500000); atomic_puts("M: unlocking mutex ..."); pthread_mutex_unlock(&lock); atomic_puts("M: ... done"); /* Force a wait on read() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); check_syscall(1, write(sock, &token, sizeof(token))); ++token; atomic_puts("M: ... done"); /* Force a wait on readv() */ { struct iovec v = { .iov_base = &token, .iov_len = sizeof(token) }; atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("r: writev('%c')'ing socket ...\n", token); check_syscall(1, writev(sock, &v, 1)); ++token; atomic_puts("M: ... done"); } /* Force a wait on recv() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); /* Force a wait on recvfrom() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); /* Force a wait on recvfrom(&sock) */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); { struct mmsghdr mmsg = { { 0 } }; struct iovec data = { 0 }; int magic = msg_magic; data.iov_base = &magic; data.iov_len = sizeof(magic); mmsg.msg_hdr.msg_iov = &data; mmsg.msg_hdr.msg_iovlen = 1; struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN); // send a fd cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CTRLMSG_LEN; mmsg.msg_hdr.msg_control = cmptr; mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN; *(int*)CMSG_DATA(cmptr) = STDERR_FILENO; // send stderr as fd /* Force a wait on recvmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmsg'ing 0x%x to socket ...\n", msg_magic); sendmsg(sock, &mmsg.msg_hdr, 0); atomic_puts("M: ... done"); /* Force a wait on recvmmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmmsg'ing 0x%x to socket ...\n", msg_magic); breakpoint(); sendmmsg(sock, &mmsg, 1, 0); atomic_printf("M: ... sent %u bytes\n", mmsg.msg_len); /* Force a wait on recvmmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmmsg'ing(by socketcall) 0x%x to socket ...\n", msg_magic); #if defined(SYS_socketcall) struct sendmmsg_arg arg = { 0 }; arg.sockfd = sock; arg.msgvec = &mmsg; arg.vlen = 1; syscall(SYS_socketcall, SYS_SENDMMSG, (void*)&arg); #elif defined(SYS_sendmmsg) syscall(SYS_sendmmsg, sock, &mmsg, 1, 0); #else #error unable to call sendmmsg #endif free(cmptr); } { struct msghdr msg = { 0 }; struct iovec iovs[2]; char c1 = token++; char c2 = token++; iovs[0].iov_base = &c1; iovs[0].iov_len = sizeof(c1); iovs[1].iov_base = &c2; iovs[1].iov_len = sizeof(c2); msg.msg_iov = iovs; msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]); /* Force a wait on recvmsg(). */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing { '%c', '%c' } to socket ...\n", c1, c2); check_syscall(2, sendmsg(sock, &msg, 0)); atomic_puts("M: ... done"); } /* Force a wait on poll() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on ppoll() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on select(), raw syscall */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on select(), library call */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on epoll_wait() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on write() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: reading socket ...\n"); ++token; { char* buf = (char*)malloc(num_sockbuf_bytes); int i; for (i = 0; i < 2; ++i) { read_all_chunks(sock, buf, num_sockbuf_bytes, token); ++token; } free(buf); } atomic_puts("M: ... done"); /* Force a wait on read() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); atomic_puts("M: ... done"); pthread_join(reader, NULL); atomic_puts("EXIT-SUCCESS"); return 0; }
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); }
enum result execute(struct request * req, struct run_result * rused) { pid_t pid; char outfile[EOJ_PATH_MAX]; char complete_fname[EOJ_PATH_MAX]; char fstdout[EOJ_PATH_MAX]; unsigned int ltime = req->time_limit, lmem = req->mem_limit; //reset syscall times check_syscall(-1, req); snprintf(outfile, EOJ_PATH_MAX, "%s%s", req->fname_nosx, req->cpl->execsuffix); snprintf(complete_fname, EOJ_PATH_MAX, "%s%s", req->out_dir, outfile); snprintf(fstdout, EOJ_PATH_MAX, "%s%s%s", req->out_dir, req->fname_nosx, ".result"); //add record only at first time if (access(fstdout, F_OK)) add_file_records(&fcreat_record, fstdout); pid = fork(); if (pid == 0) { if (set_limit(ltime, 1024)) { eoj_log("set rlimit error: %s", strerror(errno)); exit(1); } if (io_redirect(req->input_file, fstdout)) { eoj_log("ioredirect error: %s", strerror(errno)); exit(1); } ptrace(PTRACE_TRACEME, 0, NULL, NULL ); if (execl(complete_fname, outfile, NULL ) == -1) { eoj_log("exec fail: %s", strerror(errno)); exit(1); } } enum result result; int status; struct rusage rusage; long orig_ax; while (1) { if (wait4(pid, &status, 0, &rusage) < 0) { eoj_log("wait error: %s", strerror(errno)); return SYS_ERROR; } result = check_mem_rusage(&rusage, rused, lmem); if (result == MEM_LIMIT_EXCEED) { kill(pid, SIGKILL); //eoj_log("memory limit exceed"); break; } if (WIFEXITED(status)) { result = RNORMAL; break; } else if (WSTOPSIG(status) != 5) { int sig = WSTOPSIG(status); switch (sig) { case SIGXCPU: case SIGKILL: //eoj_log("time limt exceed"); result = TIME_LIMIT_EXCEED; break; case SIGXFSZ: //eoj_log("output limit exceed"); result = OUTPUT_LIMIT_EXCEED; break; default: eoj_log("unknown error,sig %s", strsignal(sig)); result = RUN_TIME_ERR; break; } kill(pid, SIGKILL); break; } /* it doesn't work.very strange */ // else if (WIFSIGNALED(status)) { // int sig = WTERMSIG(status); // switch (sig) { // case SIGKILL: // case SIGXCPU: // eoj_log("%s time limt exceed", req->fname_nosx); // result = TIME_LIMIT_EXCEED; // break; // case SIGXFSZ: // result = OUTPUT_LIMIT_EXCEED; // eoj_log("%s output limit exceed", req->fname_nosx); // break; // default: // result = RUN_TIME_ERR; // break; // } // break; // } orig_ax = ptrace(PTRACE_PEEKUSER, pid, WORDLEN * ORIG_AX, NULL ); if (orig_ax >= 0 && check_syscall(orig_ax, req)) { eoj_log("run illegal system call %ld", orig_ax); kill(pid, SIGKILL); result = RUN_TIME_ERR; break; } if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL ) < 0) { eoj_log("ptrace error: %s", strerror(errno)); kill(pid, SIGKILL); result = SYS_ERROR; break; } } return result; }