int main(int argc, char *argv[]) { char *user = getpwuid(getuid())->pw_name; char *competition, *problem, *file; FILE *f; int i, c; if (argc != 4) { puts("Error: Not enough arguments"); exit(-1); } competition = basename(argv[1]); problem = basename(argv[2]); file = basename(argv[3]); chdir(PROBLEMS_LOC); safe_chdir(competition); safe_chdir(problem); chdir("submissions/queued"); mkdir(user, S_IRWXU|S_IRGRP|S_IXGRP); safe_chdir(user); f = fopen(file, "w+"); for (i = 0; i < MAX_FILESIZE && (c = getchar()) != EOF; i++) fputc(c, f); if (i == MAX_FILESIZE) printf("Error: File was too large. Max filesize is: %d", MAX_FILESIZE); fclose(f); }
void changedir(const char *path) { static int round = 0; printf("------------------------\n"); safe_chdir(path); safe_getcwd(round); safe_lsdir(round); round ++; }
/** * pm_execute * @params * int should_wait - Indicates if this execute should be inline or asynchronous * const char* command - The command to run * const char* cd - Run in this directory unless it's a NULL pointer * int nice - Special nice level * const char** env - Environment variables to run in the shell * @output pid_t pid - output pid of the new process **/ pid_t pm_execute( int should_wait, const char* command, const char *cd, int nice, const char** env, int *child_stdin, const char* p_stdout, const char *p_stderr ) { // Setup execution char **command_argv = {0}; int command_argc = 0; int running_script = 0; int countdown = 200; // If there is nothing here, don't run anything :) if (strlen(command) == 0) return -1; char* chomped_string = str_chomp(command); char* safe_chomped_string = str_safe_quote(chomped_string); if (expand_command((const char*)safe_chomped_string, &command_argc, &command_argv, &running_script, env)) ; command_argv[command_argc] = 0; // Now actually RUN it! pid_t pid; #if USE_PIPES int child_fd[2]; if ( pipe(child_fd) < 0 ) {// Create a pipe to the child (do we need this? I doubt it) perror("pipe failed"); } // Setup the stdin so the parent can communicate! (*child_stdin) = child_fd[0]; #endif // Let's name it so we can get to it later int child_dev_null; #if DEBUG if ((child_dev_null = open("debug.log", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { syslog(LOG_ERR, "babysitter (fatal): Could not open debug.log: errno: %d\n", errno); }; #else if ((child_dev_null = open("/dev/null", O_RDWR)) < 0) { syslog(LOG_ERR, "babysitter (fatal): Could not open /dev/null: errno: %d\n", errno); }; #endif // Setup fork pm_setup_fork(); if (should_wait) pid = vfork(); else pid = fork(); switch (pid) { case -1: return -1; case 0: { // Child process pm_setup_child(); if (cd != NULL && cd[0] != '\0') safe_chdir(cd); else safe_chdir("/tmp"); int child_stdout, child_stderr; // Set everything to dev/null first child_stdout = child_stderr = child_dev_null; // If we've passed in a stdout filename, then open it if(p_stdout) if ((child_stdout = open(p_stdout, O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { perror("child stdout"); child_stdout = child_dev_null; } // If we've been passed a stderr filename, then open that if(p_stderr) if ((child_stderr = open(p_stderr, O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { perror("child stderr"); child_stderr = child_dev_null; } // Parent doesn't write anything to the child, so just close this right away // REDIRECT TO DEV/NULL // Replace the stdout/stderr with the child_write fd #if USE_PIPES if (dup2(child_fd[0], STDIN_FILENO) < 0) FATAL_ERROR("could not dup STDIN_FILENO", -1); close(child_fd[1]); // We are using a different stdout #endif #if DEBUG #else // Setup the different stdout/stderr if (dup2(child_stdout, STDOUT_FILENO) < 0) FATAL_ERROR("could not dup STDOUT_FILENO", -1); if (dup2(child_stderr, STDERR_FILENO) < 0) FATAL_ERROR("could not dup STDERR_FILENO", -1); if (child_stdout != child_dev_null) close(child_stdout); if (child_stderr != child_dev_null) close(child_stderr); #endif if (execve((const char*)command_argv[0], command_argv, (char* const*) env) < 0) { perror("execve"); exit(-1); } } default: // In parent process // set the stdout back close(child_dev_null); // Child write never gets used outside the child #if USE_PIPES if (dup2(child_fd[1], STDOUT_FILENO) < 0) perror("dup2"); close(child_fd[0]); #endif if (nice != INT_MAX && setpriority(PRIO_PROCESS, pid, nice) < 0) ; if (running_script) { while (countdown > 0) { if (kill(pid, 0) != 0) break; usleep(100); countdown--; } struct stat buffer; if (stat(command_argv[0], &buffer) != 0) { printf("file doesn't exist when it should because: %s\n", strerror(errno)); } if( unlink( command_argv[0] ) != 0 ) perror( "Error deleting file" ); } // These are free'd later, anyway // if (chomped_string) free(chomped_string); // if (safe_chomped_string) free(safe_chomped_string); return pid; } }
static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp) { struct stat osb, oslb, dsb; CfLock thislock; int exists; Attributes a = GetFilesAttributes(ctx, pp); if (!FileSanityChecks(ctx, path, a, pp)) { return PROMISE_RESULT_NOOP; } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", path, DATA_TYPE_STRING, "source=promise"); thislock = AcquireLock(ctx, path, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } LoadSetuid(a); PromiseResult result = PROMISE_RESULT_NOOP; if (lstat(path, &oslb) == -1) /* Careful if the object is a link */ { if ((a.create) || (a.touch)) { if (!CfCreateFile(ctx, path, pp, a, &result)) { goto exit; } else { exists = (lstat(path, &oslb) != -1); } } exists = false; } else { if ((a.create) || (a.touch)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' exists as promised", path); } exists = true; } if ((a.havedelete) && (!exists)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' does not exist as promised", path); goto exit; } if (!a.havedepthsearch) /* if the search is trivial, make sure that we are in the parent dir of the leaf */ { char basedir[CF_BUFSIZE]; Log(LOG_LEVEL_DEBUG, "Direct file reference '%s', no search implied", path); snprintf(basedir, sizeof(basedir), "%s", path); if (strcmp(ReadLastNode(basedir), ".") == 0) { // Handle /. notation for deletion of directories ChopLastNode(basedir); ChopLastNode(path); } ChopLastNode(basedir); if (safe_chdir(basedir)) { Log(LOG_LEVEL_ERR, "Failed to chdir into '%s'", basedir); } } /* If file or directory exists but it is not selected by body file_select * (if we have one) then just exit. But continue if it's a directory and * depth_search is on, so that we can file_select into it. */ if (exists && (!VerifyFileLeaf(ctx, path, &oslb, a, pp, &result)) && !(a.havedepthsearch && S_ISDIR(oslb.st_mode))) { goto exit; } if (stat(path, &osb) == -1) { if ((a.create) || (a.touch)) { if (!CfCreateFile(ctx, path, pp, a, &result)) { goto exit; } else { exists = true; } } else { exists = false; } } else { if (!S_ISDIR(osb.st_mode)) { if (a.havedepthsearch) { Log(LOG_LEVEL_WARNING, "depth_search (recursion) is promised for a base object '%s' that is not a directory", path); goto exit; } } exists = true; } if (a.link.link_children) { if (stat(a.link.source, &dsb) != -1) { if (!S_ISDIR(dsb.st_mode)) { Log(LOG_LEVEL_ERR, "Cannot promise to link the children of '%s' as it is not a directory!", a.link.source); goto exit; } } } /* Phase 1 - */ if (exists && ((a.havedelete) || (a.haverename) || (a.haveperms) || (a.havechange) || (a.transformer))) { lstat(path, &oslb); /* if doesn't exist have to stat again anyway */ DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result); /* normally searches do not include the base directory */ if (a.recursion.include_basedir) { int save_search = a.havedepthsearch; /* Handle this node specially */ a.havedepthsearch = false; DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result); a.havedepthsearch = save_search; } else { /* unless child nodes were repaired, set a promise kept class */ if (!IsDefinedClass(ctx, "repaired")) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Basedir '%s' not promising anything", path); } } if (((a.change.report_changes) == FILE_CHANGE_REPORT_CONTENT_CHANGE) || ((a.change.report_changes) == FILE_CHANGE_REPORT_ALL)) { if (a.havedepthsearch) { PurgeHashes(ctx, NULL, a, pp); } else { PurgeHashes(ctx, path, a, pp); } } } /* Phase 2a - copying is potentially threadable if no followup actions */ if (a.havecopy) { result = PromiseResultUpdate(result, ScheduleCopyOperation(ctx, path, a, pp)); } /* Phase 2b link after copy in case need file first */ if ((a.havelink) && (a.link.link_children)) { result = PromiseResultUpdate(result, ScheduleLinkChildrenOperation(ctx, path, a.link.source, 1, a, pp)); } else if (a.havelink) { result = PromiseResultUpdate(result, ScheduleLinkOperation(ctx, path, a.link.source, a, pp)); } /* Phase 3 - content editing */ if (a.haveedit) { if (exists) { result = PromiseResultUpdate(result, ScheduleEditOperation(ctx, path, a, pp)); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to edit '%s', but file does not exist", path); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } // Once more in case a file has been created as a result of editing or copying exists = (stat(path, &osb) != -1); if (exists && (S_ISREG(osb.st_mode))) { VerifyFileLeaf(ctx, path, &osb, a, pp, &result); } if (!exists && a.havechange) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to monitor '%s' for changes, but file does not exist", path); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } exit: if (AttrHasNoAction(a)) { Log(LOG_LEVEL_INFO, "No action was requested for file '%s'. Maybe a typo in the policy?", path); } result = PromiseResultUpdate(result, SaveSetuid(ctx, a, pp)); YieldCurrentLock(thislock); return result; }
FILE *cf_popen_shsetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, ARG_UNUSED int background) { int pd[2]; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chroot to '%s'. (chroot: %s)", chrootv, GetErrorStr()); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (safe_chdir(chdirv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chdir to '%s'. (chdir: %s)", chdirv, GetErrorStr()); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(EXIT_FAILURE); } execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; }