int execve(const char *path, char *const argv[], char *const envp[]) { int rv; char *vmxfile = NULL; char *const *avp; FILE *logfp; logfp = open_log(); LOG(logfp, "\n*** miq_execve ***\n"); LOG(logfp, "miq_execve, path: %s\n", path); LOG(logfp, "miq_execve, args:\n"); for (avp = argv; *avp; avp++) { LOG(logfp, "\t%s\n", *avp); } if (basename_is(path, "vmkload_app")) { LOG(logfp, "*** Starting VM: "); for (avp = argv; *avp; avp++) { if (ext_is(*avp, ".vmx")) { LOG(logfp, "%s\n", *avp); vmxfile = *avp; break; } } if (!check_start_ok(vmxfile)) { LOG(logfp, "*** Not starting VM, Permission denied\n"); __set_errno(EACCES); return -1; } } LOG(logfp, "miq_execve, calling execvp\n"); rv = real_execve(path, argv, envp); LOG(logfp, "miq_execve, execvp returned: %d\n", rv); return rv; }
int execve(const char *filename, char *const argv[], char *const envp[]) { DBG("filename=%s\n", filename); if (check_perm(filename, RESTRICTED_ALLOW_EXEC_ENV, &patterns_execve)) return -1; return real_execve(filename, argv, envp); }
asmlinkage int virt_execve(struct pt_regs regs) { int ret; char *newfilename; char *filename = (char *) regs.ebx; if(!cwd_virtual()) { ret = real_execve(®s); if(ret != -ENOENT) return ret; } else ret = 0; newfilename = resolve_name(filename, 1, 1); if(!newfilename) { if(ret) return ret; else return real_execve(®s); } if(IS_ERR(newfilename)) return PTR_ERR(newfilename); DEB((KERN_INFO "EXECVE: trying '%s'\n", newfilename)); ret = do_execve(newfilename, (char **) regs.ecx, (char **) regs.edx, ®s); if (ret == 0) { #ifdef PT_DTRACE current->ptrace &= ~PT_DTRACE; #else current->flags &= ~PF_DTRACE; #endif } kfree(newfilename); DEB((KERN_INFO "EXECVE: result %i\n", ret)); return ret; }
int reboot_arch(int mode) { (void) mode; printf("\n\n\t\t!! REBOOT !!\n\n"); if (real_execve(_native_argv[0], _native_argv, NULL) == -1) { err(EXIT_FAILURE, "reboot: execve"); } errx(EXIT_FAILURE, "reboot: this should not have been reached"); }
static int check_start_ok(const char *vmxfile) { pid_t pid, w; int status; FILE *logfp; logfp = open_log(); LOG(logfp, "check_start_ok: %s\n", vmxfile); pid = fork(); if (pid < 0) { LOG(logfp, "check_start_ok: fork failed: %d\n", errno); return 0; } if (pid == 0) { char cmdbuf[256]; sprintf(cmdbuf, csokformat, (char *)vmxfile); csokargv[2] = cmdbuf; if (miq_loglevel) { char **avp; LOG(logfp, "check_start_ok: exec'ing %s\n", csokpath); for (avp = csokargv; *avp; avp++) { LOG(logfp, "\t%s\n", *avp); } } if (real_execve(csokpath, csokargv, __environ) < 0) { LOG(logfp, "check_start_ok: exec of %s failed: %d\n", csokpath, errno); return 0; } } else { do { w = waitpid(pid, &status, 0); if (w < 0) { LOG(logfp, "check_start_ok: waitpid failed: %d\n", errno); return 0; } if (WIFEXITED(status)) { int rv = WEXITSTATUS(status); LOG(logfp, "check_start_ok: %s returned: %d\n", csokpath, rv); LOG(logfp, "check_start_ok: returning: %d\n", !rv); return !rv; } if (WIFSIGNALED(status)) { LOG(logfp, "check_start_ok: killed by signal: %d\n", WTERMSIG(status)); return 0; } } while(1); } return 1; }
void reboot(void) { printf("\n\n\t\t!! REBOOT !!\n\n"); #ifdef MODULE_NETDEV2_TAP netdev2_tap_cleanup(&netdev2_tap); #endif if (real_execve(_native_argv[0], _native_argv, NULL) == -1) { err(EXIT_FAILURE, "reboot: execve"); } errx(EXIT_FAILURE, "reboot: this should not have been reached"); }
int execve(const char *filename, char *const argv[], char *const envp[]){ if(initializing == -1) init(); int pid,st,i; unsigned long offset; mainFile=basename(filename); printf("Executing %s [%s]\n", filename, mainFile); char tempfilename[]="/tmp/replacemallocXXXXXX"; int fd=mkstemp(tempfilename); char buff[300]; // Open main output file /* List libraries, we need to do an exec here, so we fork and remove the * LD_PRELOAD from the child */ if(!(pid=fork())){ remove_preload(); snprintf(buff,300,"/usr/bin/ldd %s | sed -e 's/[^/]*//' > %s", filename, tempfilename); system(buff); close(fd); exit(0); } else{ waitpid(pid, &st, 0); } // Retrieve main structures get_structs(filename,0); // Retrieve structures of shared libraries size_t read,len=0; char *line=0; FILE *fp=fdopen(fd,"r"); while((read=getline(&line, &len, fp)) != -1) if(read>1){ // Line looks: "/path/to/lib.so (offset)\n" i=0; line[strlen(line)-2]='\0';// remove trailing ')\n' while(line[i]!=' ') ++i; line[i]='\0'; i+=2; // Go after the '(' sscanf(line+i,"%lx",&offset); get_structs(line,offset); } fclose(fp); close(fd); remove(tempfilename); return real_execve(filename,argv,envp); }
int execve(const char *filename, char *const argv[], char *const envp[]) throw() { int retval; print_trace ("%*sexecve(%s, %s, %s)=...\n", indent, "", filename, argv, envp); indent+=2; /* call the real execve function */ retval = real_execve (filename, argv, envp); indent-=2; print_trace ("%*sexecve(%p, %s, %s)=%d\n", indent, "", filename, argv, envp, retval); return retval; }
int reboot_arch(int mode) { (void) mode; printf("\n\n\t\t!! REBOOT !!\n\n"); #ifdef MODULE_UART0 /* TODO: close stdio fds */ #endif #ifdef MODULE_NG_NATIVENET dev_eth_tap_cleanup(&dev_eth_tap); #endif if (real_execve(_native_argv[0], _native_argv, NULL) == -1) { err(EXIT_FAILURE, "reboot: execve"); } errx(EXIT_FAILURE, "reboot: this should not have been reached"); }
/* * action_execve adds an exec node to the subgraph and sets WAITLESS_PARENT * to the hash of the arguments. The first node in the child process will * use WAITLESS_PARENT as its first parent node. Note that WAITLESS_PARENT * is intentionally _not_ the same as the exec node; this encodes the idea * that child processes depend on their parent processes only through the * arguments to execve (and the current directory). * * In the case of shared spines (due to pipes or other IPC mechanisms) the * exec node encodes only the path without argv and envp and WAITLESS_PARENT * has the format #id where id is a SYSV shared memory id. This allows further * subgraph nodes from child and parent to be interleaved. Since in the shared * case the child _does_ descend directly from the exec node, an explicit * record of argv and envp would be redundant. */ int action_execve(const char *path, const char *const argv[], const char *const envp[]) { fd_map_dump(); struct process *process = lock_master_process(); int linked = process != process_info(); wlog("exec: linked %d", linked); // Pack all the arguments into a single buffer. The format is // char path[]; // uint32_t argc; // char argv[argc][]; // char is_pipe; // uint32_t envc; // char envp[envc][]; // char cwd[]; // with all strings packed together with terminating nulls. char data[4096]; char *p = data; #define ADD_STR(s) p += strlcpy(p, (s), data+sizeof(data)-p) + 1 ADD_STR(path); // encode argv char *cp = p; p += sizeof(uint32_t); // skip 4 bytes for len(argv) uint32_t i; for (i = 0; argv[i]; i++) ADD_STR(argv[i]); memcpy(cp, &i, sizeof(uint32_t)); *p++ = linked; // encode envp cp = p; p += sizeof(uint32_t); // skip 4 bytes for len(envp) uint32_t count; for (i = 0; envp[i]; i++) if (!startswith(envp[i], "WAITLESS")) { ADD_STR(envp[i]); count++; } memcpy(cp, &count, sizeof(uint32_t)); // encode pwd if (!real_getcwd(p, data+sizeof(data)-p)) die("action_execve: getcwd failed: %s", strerror(errno)); int n = p - data + strlen(p) + 1; #undef ADD_STR // Store exec data and create a corresponding exec node struct hash data_hash; remember_hash_memory(&data_hash, data, n); new_node(process, SG_EXEC, &data_hash); // Add the program to the snapshot struct hash path_hash, program_hash; remember_hash_path(&path_hash, path); struct snapshot_entry *entry = snapshot_update(&program_hash, path, &path_hash, 1); if (entry->writing) die("can't exec '%s' while it is being written", path); // TODO: block instead of dying entry->read = 1; shared_map_unlock(&snapshot); // TODO: Run ldd/otool and hash all shared library dependencies as well // TODO: Complain if the program is statically linked // TODO: If we decide it's worth it, parse #! lines and hash interpreters // too. That seems easy enough to probably be worth it. // If not linked, set parents to the new child values if (!linked) { process->parents.n = 2; process->parents.p[0] = data_hash; process->parents.p[1] = program_hash; } unlock_master_process(); // Update process flags process = lock_process(); int old_flags = process->flags; process->flags = 0; p = rindex(path, '/'); const char *name = p ? p+1 : path; if (!strcmp(name, "as")) process->flags |= HACK_SKIP_O_STAT; else if (strstr(name, "-gcc-")) { for (i = 1; argv[i]; i++) if (!strcmp(argv[i], "-c")) { process->flags |= HACK_SKIP_O_STAT; break; } } unlock_process(); // Do the exec int ret = real_execve(path, argv, envp); // An error must have occurred; reset flags back to old value process = lock_process(); process->flags = old_flags; unlock_process(); return ret; }