int main(int argc, char* argv[]){ /* * ensure the following items are proper: * - this process has cap_sys_chroot=ep * - the config files are secure * - the config files are readable * - enough arguments were provided */ /* ensure this process has the required capabilities */ ensure_capsyschroot(argv[0]); /* ensure config file is only writable by root */ ensure_config_secure(); /* ensure config file is readable */ ensure_config_readable(); /* ensure there are enough arguments */ ensure_enough_arguments(argc, argv); /* * gather the following pieces of information: * - the command (and its arguments) to run in the chroot * - the path to the chroot * - the directory to be cwd in the chroot */ /* get command to run in chroot */ char* shell[2]; char** chroot_command = get_chroot_command(argc, argv, shell); /* get path to chroot */ char chroot_path[PATH_MAX]; get_chroot_path(argv,chroot_path); /* get cwd - will attempt to make this cwd in chroot */ char* chroot_cwd = getcwd(NULL, PATH_MAX); /* * run the command in the proper context: * - if we're in a chroot, break out * - chroot the new directory, ensuring cwd is within it. * - change cwd to desired directory if it exists; remain in / otherwise. * - run command * - if needed, abort cleanly */ /* break out of chroot */ break_out_of_chroot(); /* chroot to new directory */ chdir(chroot_path); chroot("."); /* change cwd in the chroot to what it was previously, if possible */ if(chdir(chroot_cwd) != 0) fprintf(stderr,"WARNING: \"%s\" not present in target client, falling back to root directory\n", chroot_cwd); /* We need to free previously allocated memory */ free(chroot_cwd); /* run command */ execvp(chroot_command[0], chroot_command); /* if there is an error, abort cleanly */ perror("execvp"); return 2; }
int main(int argc, char** argv) { int prg_argc; char ** prg_argv; progname = argv[0]; if (argc < 3) usage(); int c, opt_index; while ((c = getopt_long(argc, argv, "f:r:", long_options, &opt_index)) != -1) { switch (c) { case 'f': { /* Special case hack for only creating files and not actually executing * the program. */ if (argc != 3) usage(); char* input_fname = optarg; input = kTest_fromFile(input_fname); if (!input) { fprintf(stderr, "%s: error: input file %s not valid.\n", progname, input_fname); exit(1); } prg_argc = input->numArgs; prg_argv = input->args; prg_argv[0] = argv[1]; klee_init_env(&prg_argc, &prg_argv); replay_create_files(&__exe_fs); return 0; } case 'r': rootdir = optarg; break; } } /* Normal execution path ... */ char* executable = argv[optind]; /* make sure this process has the CAP_SYS_CHROOT capability. */ if (rootdir) ensure_capsyschroot(progname); /* rootdir should be a prefix of executable's path. */ if (rootdir && strstr(executable, rootdir) != executable) { fprintf(stderr, "Error: chroot: root dir should be a parent dir of executable.\n"); exit(1); } /* Verify the executable exists. */ FILE *f = fopen(executable, "r"); if (!f) { fprintf(stderr, "Error: executable %s not found.\n", executable); exit(1); } fclose(f); int idx = 0; for (idx = optind + 1; idx != argc; ++idx) { char* input_fname = argv[idx]; unsigned i; input = kTest_fromFile(input_fname); if (!input) { fprintf(stderr, "%s: error: input file %s not valid.\n", progname, input_fname); exit(1); } obj_index = 0; prg_argc = input->numArgs; prg_argv = input->args; prg_argv[0] = argv[optind]; klee_init_env(&prg_argc, &prg_argv); if (idx > 2) fprintf(stderr, "\n"); fprintf(stderr, "%s: TEST CASE: %s\n", progname, input_fname); fprintf(stderr, "%s: ARGS: ", progname); for (i=0; i != (unsigned) prg_argc; ++i) { char *s = prg_argv[i]; if (s[0]=='A' && s[1] && !s[2]) s[1] = '\0'; fprintf(stderr, "\"%s\" ", prg_argv[i]); } fprintf(stderr, "\n"); /* Run the test case machinery in a subprocess, eventually this parent process should be a script or something which shells out to the actual execution tool. */ int pid = fork(); if (pid < 0) { perror("fork"); _exit(66); } else if (pid == 0) { /* Create the input files, pipes, etc., and run the process. */ replay_create_files(&__exe_fs); run_monitored(executable, prg_argc, prg_argv); _exit(0); } else { /* Wait for the test case. */ int res, status; do { res = waitpid(pid, &status, 0); } while (res < 0 && errno == EINTR); if (res < 0) { perror("waitpid"); _exit(66); } } } return 0; }