static int stop_program_impl(CodeRunInstance *instance, time_t current_tstamp) { if( (PROGRAM_LIFECYCLE_NORMAL == instance->_life_cycle_status) || (current_tstamp < instance->tstamp_onstop_sigint) ) { instance->_life_cycle_status = PROGRAM_LIFECYCLE_SIGINTED; if(0 != killpg(instance->child_pid, SIGINT)) { RECORD_ERR("cannot send SIGINT to child process", __FILE__, __LINE__); return 1; } } else if( (PROGRAM_LIFECYCLE_SIGINTED == instance->_life_cycle_status) || (current_tstamp < instance->tstamp_onstop_sigterm) ) { instance->_life_cycle_status = PROGRAM_LIFECYCLE_SIGTERMED; if(0 != killpg(instance->child_pid, SIGTERM)) { RECORD_ERR("cannot send SIGTERM to child process", __FILE__, __LINE__); return 2; } } else { instance->_life_cycle_status = PROGRAM_LIFECYCLE_SIGKILLED; if(0 != killpg(instance->child_pid, SIGKILL)) { RECORD_ERR("cannot send SIGKILL to child process", __FILE__, __LINE__); return 3; } } return 0; }
__kernel void kernel_modtest_read(__global char* ptr, unsigned long memsize, unsigned int offset, TYPE p1, TYPE p2, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global TYPE* buf = (__global TYPE*)ptr; int idx = get_global_id(0); unsigned long n = memsize/sizeof(TYPE); int total_num_threads = get_global_size(0); TYPE localp; for(i=idx;i < n; i+= total_num_threads){ localp = buf[i]; if ( (i+MOD_SZ-offset)%MOD_SZ == 0){ if(localp != p1){ RECORD_ERR(err_count, &buf[i], p1, localp); } }else{ if (localp != p2){ RECORD_ERR(err_count, &buf[i], p2, localp); } } } return; }
static int change_account(CodeRunInstance *instance, uid_t runner_uid, gid_t runner_gid) { if(0 != setgid(runner_gid)) { RECORD_ERR("cannot set Group ID", __FILE__, __LINE__); return 1; } if(0 != setegid(runner_gid)) { RECORD_ERR("cannot set Effective Group ID", __FILE__, __LINE__); return 2; } if(0 != setuid(runner_uid)) { RECORD_ERR("cannot set User ID", __FILE__, __LINE__); return 3; } if(0 != seteuid(runner_uid)) { RECORD_ERR("cannot set Effective User ID", __FILE__, __LINE__); return 4; } return 0; }
__kernel void kernel0_local_read(__global char* ptr, unsigned long memsize, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global unsigned long* buf = (__global unsigned long*)ptr; int idx = get_global_id(0); unsigned long n = memsize/BLOCKSIZE; int total_num_threads = get_global_size(0); for(i=idx; i < n; i+= total_num_threads){ __global unsigned long * start_p= (__global unsigned long)(ptr + i*BLOCKSIZE); __global unsigned long* end_p = (__global unsigned long*)(ptr + (i+1)*BLOCKSIZE); __global unsigned long * p =start_p; unsigned int pattern = 1; unsigned int mask = 8; if (*p != pattern){ RECORD_ERR(err_count, p, pattern, *p); } pattern = (pattern << 1); while(p< end_p){ p = (__global unsigned long*)( ((unsigned long)start_p)|mask); if(p == start_p){ mask = (mask << 1); if (mask == 0){ break; } continue; } if (p >= end_p){ break; } if (*p != pattern){ RECORD_ERR(err_count, p, pattern, *p); } pattern = pattern <<1; mask = (mask << 1); if (mask == 0){ break; } } } return; }
__kernel void kernel_readwrite(__global char* ptr, unsigned long memsize, TYPE p1, TYPE p2, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global TYPE* buf = (__global TYPE*) ptr; int idx = get_global_id(0); unsigned long n = memsize/sizeof(TYPE); int total_num_threads = get_global_size(0); TYPE localp; for(i=idx;i < n;i += total_num_threads){ localp = buf[i]; if (localp != p1){ RECORD_ERR(err_count, &buf[i], p1, localp); } buf[i] = p2; } }
int wait_program(CodeRunInstance *instance, int blocking_wait) { time_t current_tstamp; pid_t retpid; int prg_status; if((time_t)(0) != instance->tstamp_finish) { return 0; } current_tstamp = update_lastcheck_tstamp(instance); if( ((pid_t)(-1)) == (retpid = waitpid(instance->child_pid, &prg_status, ((0 == blocking_wait) ? WNOHANG : 0))) ) { RECORD_ERR("failed on waitpid", __FILE__, __LINE__); return 2; } if( ((pid_t)(0)) == retpid) { if(current_tstamp > instance->tstamp_bound) { stop_program_impl(instance, current_tstamp); } return 1; } update_exit_code(instance, prg_status); instance->tstamp_finish = current_tstamp; return 0; }
__kernel void kernel7_read(__global char* ptr, unsigned long memsize, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global TYPE* buf = (__global TYPE*) ptr; int idx = get_global_id(0); unsigned long n = memsize/sizeof(TYPE); int total_num_threads = get_global_size(0); TYPE localp, expected; int rand_data_num =BLOCKSIZE/sizeof(TYPE); for(i=idx;i < n;i += total_num_threads){ if (i < rand_data_num){ continue; } localp = buf[i]; expected = ~(buf[i%rand_data_num]); if (localp != expected){ RECORD_ERR(err_count, &buf[i], expected, localp); } } }
__kernel void kernel0_global_read(__global char* ptr, unsigned long memsize, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { __global unsigned int* p = (__global unsigned int*)ptr; __global unsigned int* end_p = (__global unsigned int*)(ptr + memsize); unsigned int pattern = 1; unsigned int mask = 4; if ( *p != ((unsigned int)pattern)){ RECORD_ERR(err_count, p, pattern, *p); } pattern = (pattern << 1); while(p< end_p){ p = (__global unsigned int*)( ((unsigned int)ptr)|mask); if(p == ptr){ mask = (mask << 1); if (mask == 0){ break; } continue; } if (p >= end_p){ break; } if (*p != ((unsigned int)pattern)){ RECORD_ERR(err_count, p, pattern, *p); } pattern = pattern <<1; mask = (mask << 1); if (mask == 0){ break; } } return; }
static int set_file_owner(CodeRunInstance *instance, int fd, uid_t runner_uid, gid_t runner_gid, const char *errmsg) { if( (runner_uid == geteuid()) && (runner_gid == getegid()) ) { return 0; } if(-1 == fchown(fd, runner_uid, runner_gid)) { RECORD_ERR(errmsg, __FILE__, __LINE__); } return 0; }
static time_t get_current_tstamp(CodeRunInstance *instance) { time_t current_tstamp; if( ((time_t)(-1)) == time(¤t_tstamp) ) { RECORD_ERR("cannot get current timestamp", __FILE__, __LINE__); return (time_t)(0); } return current_tstamp; }
static int close_fd_impl_procfs_fdfolder(CodeRunInstance *instance, const char *fdfolder_path) { int dirfd_val; DIR *dirp; struct dirent *p; if(NULL == (dirp = opendir(fdfolder_path))) { RECORD_ERR("cannot open file descriptor proc list", __FILE__, __LINE__); return 1; } dirfd_val = dirfd(dirp); while(NULL != (p = readdir(dirp))) { int fd_val; char *endp; fd_val = (int)(strtol(p->d_name, &endp, 10)); if( (p->d_name != endp) && ('\0' == *endp) && (fd_val != dirfd_val) && (fd_val > 2) ) { if(0 != close(fd_val)) { char buf[64]; snprintf(buf, 63, "failed on close file descriptor (fd=%d)", fd_val); buf[63] = '\0'; RECORD_ERR(buf, __FILE__, __LINE__); } } } if(0 != closedir(dirp)) { RECORD_ERR("failed on close procfs file descriptor folder", __FILE__, __LINE__); } return 0; }
int adapt_preserved_runtime_environment(CodeRunInstance *instance) { if(0 != chdir(instance->fullpath_working_directory)) { RECORD_ERR("failed on adapt work directory", __FILE__, __LINE__); return 1; } if( (instance->runner_uid != geteuid()) || (instance->runner_gid != getegid()) ) { if(0 != change_account(instance, instance->runner_uid, instance->runner_gid)) { return 3; } } return 0; }
static int lookup_runner_account(CodeRunInstance *instance, const char *run_as_user, uid_t *p_runner_uid, gid_t *p_runner_gid) { struct passwd *p; if(NULL == run_as_user) { *p_runner_uid = geteuid(); *p_runner_gid = getegid(); return 0; } if(NULL == (p = getpwnam(run_as_user))) { RECORD_ERR("cannot found subject runner account", __FILE__, __LINE__); return 1; } *p_runner_uid = p->pw_uid; *p_runner_gid = p->pw_gid; return 0; }
//here we use 32 bit pattern __kernel void kernel_movinv32_readwrite(__global char* ptr, unsigned long memsize, unsigned int pattern, unsigned int lb, unsigned int sval, unsigned int offset, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global unsigned int* buf = (__global unsigned int*)ptr; int idx = get_global_id(0); unsigned long n = memsize/sizeof(unsigned int); int total_num_threads = get_global_size(0); //assume total_num_threads can be devided by 32, which is true for our purpose //then all memories written by this thread will have the same data unsigned int pat = pattern; unsigned int k=offset; for(i=0;i < idx % 32; i++){ if (k >= 32){ k=0; pat = lb; }else{ pat = pat << 1; pat |= sval; } } for(i=idx;i < n; i+= total_num_threads){ unsigned int localp = buf[i]; if (localp != pat){ RECORD_ERR(err_count, &buf[i], pat, localp); } buf[i] = ~pat; } return; }
__kernel void kernel5_check(__global char* ptr, unsigned long memsize, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global unsigned int * buf = (__global unsigned int*)ptr; int idx = get_global_id(0); unsigned long n = memsize/(2*sizeof(unsigned int)); int total_num_threads = get_global_size(0); for(i=idx;i < n; i+= total_num_threads){ if (buf[2*i] != buf[2*i+1]){ RECORD_ERR(err_count, &buf[2*i], buf[2*i+1], buf[2*i]); } } return; }
__kernel void kernel1_read(__global char* ptr, unsigned long memsize, volatile __global unsigned int* err_count, __global unsigned long* err_addr, __global unsigned long* err_expect, __global unsigned long* err_current, __global unsigned long* err_second_read) { int i; __global unsigned long* buf = (__global unsigned long*)ptr; int idx = get_global_id(0); unsigned long n = memsize/sizeof(unsigned long); int total_num_threads = get_global_size(0); for(i=idx;i < n; i+= total_num_threads){ if( buf[i] != (unsigned long)(buf+i)){ RECORD_ERR(err_count, &buf[i], (buf+i), buf[i]); } } return; }
static int prepare_log_files(CodeRunInstance *instance, const char *datafilename_stdin, const char *logfilename_stdout, const char *logfilename_stderr, char **p_fullpath_datafile_stdin, char **p_fullpath_logfile_stdout, char **p_fullpath_logfile_stderr) { int fd; char *p; if(NULL != datafilename_stdin) { if(-1 == (fd = open(datafilename_stdin, O_RDONLY))) { RECORD_ERR("failed on attempting to open STDIN file", __FILE__, __LINE__); return 1; } if(-1 == close(fd)) { RECORD_ERR("failed on attempting to close STDIN file", __FILE__, __LINE__); return 2; } if(NULL == (p = x_realpath(datafilename_stdin))) { RECORD_ERR("failed on getting path of STDIN file", __FILE__, __LINE__); return 3; } *p_fullpath_datafile_stdin = p; } else { *p_fullpath_datafile_stdin = NULL; } if(NULL != logfilename_stdout) { if(-1 == (fd = open(logfilename_stdout, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) { RECORD_ERR("failed on attempting to open STDOUT file", __FILE__, __LINE__); return 11; } if(-1 == close(fd)) { RECORD_ERR("failed on attempting to close STDOUT file", __FILE__, __LINE__); return 12; } if(NULL == (p = x_realpath(logfilename_stdout))) { RECORD_ERR("failed on getting path of STDOUT file", __FILE__, __LINE__); return 13; } *p_fullpath_logfile_stdout = p; } else { *p_fullpath_logfile_stdout = NULL; } if(NULL != logfilename_stderr) { if( (NULL == logfilename_stdout) || (0 != strcmp(logfilename_stdout, logfilename_stderr)) ) { if(-1 == (fd = open(logfilename_stderr, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) { RECORD_ERR("failed on attempting to open STDERR file", __FILE__, __LINE__); return 21; } if(-1 == close(fd)) { RECORD_ERR("failed on attempting to close STDERR file", __FILE__, __LINE__); return 22; } } if(NULL == (p = x_realpath(logfilename_stderr))) { RECORD_ERR("failed on getting path of STDERR file", __FILE__, __LINE__); return 23; } *p_fullpath_logfile_stderr = p; } else { *p_fullpath_logfile_stderr = NULL; } return 0; }
int run_program(CodeRunInstance *instance, const char *filename, char *const argv[], char *const envp[], const char *working_directory, const char *run_as_user, const char *datafilename_stdin, const char *logfilename_stdout, const char *logfilename_stderr, uint32_t max_running_second, uint32_t overtime_sigint_second, uint32_t overtime_sigterm_second) { char *fullpath_working_directory; char *fullpath_datafile_stdin; char *fullpath_logfile_stdout; char *fullpath_logfile_stderr; uid_t runner_uid; gid_t runner_gid; pid_t child_pid; fullpath_working_directory = NULL; fullpath_datafile_stdin = NULL; fullpath_logfile_stdout = NULL; fullpath_logfile_stderr = NULL; #define RELEASE_ALLOCATED_RESOURCE { \ release_allocated_memory(fullpath_working_directory, fullpath_datafile_stdin, fullpath_logfile_stdout, fullpath_logfile_stderr); \ } memset(instance, 0, sizeof(CodeRunInstance)); #if ENABLE_RUNTIMEENV_PRESERVE instance->fullpath_working_directory = NULL; instance->fullpath_datafile_stdin = NULL; instance->fullpath_logfile_stdout = NULL; instance->fullpath_logfile_stderr = NULL; instance->runner_uid = 0; instance->runner_gid = 0; #endif /* ENABLE_RUNTIMEENV_PRESERVE */ if(0 != check_working_directory(instance, working_directory, &fullpath_working_directory)) { RECORD_ERR("cannot have real path of given working directory", __FILE__, __LINE__); RELEASE_ALLOCATED_RESOURCE; return 1; } if(0 != prepare_log_files(instance, datafilename_stdin, logfilename_stdout, logfilename_stderr, &fullpath_datafile_stdin, &fullpath_logfile_stdout, &fullpath_logfile_stderr)) { RELEASE_ALLOCATED_RESOURCE; return 2; } if(0 != lookup_runner_account(instance, run_as_user, &runner_uid, &runner_gid)) { RELEASE_ALLOCATED_RESOURCE; return 3; } child_pid = fork(); if(-1 == child_pid) { RECORD_ERR("failed on perform fork()", __FILE__, __LINE__); RELEASE_ALLOCATED_RESOURCE; return 4; } else if(0 != child_pid) { fill_instance_structure(instance, max_running_second, overtime_sigint_second, overtime_sigterm_second, child_pid); #if ENABLE_RUNTIMEENV_PRESERVE instance->fullpath_working_directory = fullpath_working_directory; instance->fullpath_datafile_stdin = fullpath_datafile_stdin; instance->fullpath_logfile_stdout = fullpath_logfile_stdout; instance->fullpath_logfile_stderr = fullpath_logfile_stderr; instance->runner_uid = runner_uid; instance->runner_gid = runner_gid; #else /* ENABLE_RUNTIMEENV_PRESERVE */ RELEASE_ALLOCATED_RESOURCE; #endif /* ENABLE_RUNTIMEENV_PRESERVE */ return 0; } /* {{{ child process code */ if(0 != setpgid(0, 0)) { RECORD_ERR("failed on creating independent process group", __FILE__, __LINE__); } if(0 != chdir(working_directory)) { RECORD_ERR("failed on changing work directory", __FILE__, __LINE__); exit(17); return 1; } if(0 != open_log_files(instance, fullpath_datafile_stdin, fullpath_logfile_stdout, fullpath_logfile_stderr, runner_uid, runner_gid)) { exit(18); return 2; } close_fd(instance); if( (NULL != run_as_user) && (0 != change_account(instance, runner_uid, runner_gid)) ) { exit(19); return 3; } fprintf(stdout, "PID: %d\n", (int)(getpid())); fprintf(stdout, "WorkDirectory: [%s]\n", fullpath_working_directory); fprintf(stdout, "Runner: UID=%d; GID=%d\n", (int)(runner_uid), (int)(runner_gid)); fprintf(stdout, "----------------\n"); execve(filename, argv, envp); RECORD_ERR("cannot execute target program", __FILE__, __LINE__); exit(20); /* }}} child process code */ #undef RELEASE_ALLOCATED_RESOURCE return -1; }
static int open_log_files(CodeRunInstance *instance, const char *fullpath_datafilename_stdin, const char *fullpath_logfilename_stdout, const char *fullpath_logfilename_stderr, uid_t runner_uid, gid_t runner_gid) { int fd; if(NULL != fullpath_datafilename_stdin) { if(-1 == (fd = open(fullpath_datafilename_stdin, O_RDONLY))) { RECORD_ERR("failed on open STDIN file", __FILE__, __LINE__); return 1; } if(STDIN_FILENO != fd) { if(STDIN_FILENO != dup2(fd, STDIN_FILENO)) { RECORD_ERR("failed on dup file descriptor to STDIN", __FILE__, __LINE__); return 2; } if(-1 == close(fd)) { RECORD_ERR("failed on close user STDIN file descriptor", __FILE__, __LINE__); return 3; } } } if(NULL != fullpath_logfilename_stdout) { if(-1 == (fd = open(fullpath_logfilename_stdout, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) { RECORD_ERR("failed on open STDOUT file", __FILE__, __LINE__); return 11; } if(0 != set_file_owner(instance, fd, runner_uid, runner_gid, "cannot change file owner for STDOUT file")) { return 15; } if(STDOUT_FILENO != fd) { if(STDOUT_FILENO != dup2(fd, STDOUT_FILENO)) { RECORD_ERR("failed on dup file descriptor to STDOUT", __FILE__, __LINE__); return 12; } if(-1 == close(fd)) { RECORD_ERR("failed on close user STDOUT file descriptor", __FILE__, __LINE__); return 13; } } } if(NULL != fullpath_logfilename_stderr) { if( (NULL != fullpath_logfilename_stdout) && (0 == strcmp(fullpath_logfilename_stdout, fullpath_logfilename_stderr)) ) { if(STDERR_FILENO != dup2(STDOUT_FILENO, STDERR_FILENO)) { RECORD_ERR("failed on dup STDOUT to STDERR", __FILE__, __LINE__); return 24; } } else { if(-1 == (fd = open(fullpath_logfilename_stderr, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))) { RECORD_ERR("failed on open STDERR file", __FILE__, __LINE__); return 21; } if(0 != set_file_owner(instance, fd, runner_uid, runner_gid, "cannot change file owner for STDERR file")) { return 25; } if(STDERR_FILENO != fd) { if(STDERR_FILENO != dup2(fd, STDERR_FILENO)) { RECORD_ERR("failed on dup file descriptor to STDERR", __FILE__, __LINE__); return 22; } if(-1 == close(fd)) { RECORD_ERR("failed on close user STDERR file descriptor", __FILE__, __LINE__); return 23; } } } } return 0; }