void prepare_and_run_pelog_as_child( job *pjob, int pe_io_type, int delete_job, char *specpelog, char *pelog, int which, int parent_read, int parent_write, int kid_read, int kid_write, int fd_input) { char *arg[12]; handle_pipes_as_child(parent_read, parent_write, kid_read, kid_write); close_handles_as_child(); // setup stdin for the pelog if (fd_input != 0) { close(0); if (dup(fd_input) == -1) {} close(fd_input); } setup_pelog_outputs(pjob, pe_io_type, delete_job, specpelog); change_directory_as_needed(which, pjob); /* for both prolog and epilog */ if (DEBUGMODE == 1) { char resc_list[2048]; fprintf(stderr, "PELOGINFO: script:'%s' jobid:'%s' euser:'******' egroup:'%s' jobname:'%s' SSID:'%ld' RESC:'%s'\n", pelog, pjob->ji_qs.ji_jobid, pjob->ji_wattr[JOB_ATR_euser].at_val.at_str, pjob->ji_wattr[JOB_ATR_egroup].at_val.at_str, pjob->ji_wattr[JOB_ATR_jobname].at_val.at_str, pjob->ji_wattr[JOB_ATR_session_id].at_val.at_long, resc_to_string(pjob, JOB_ATR_resource, resc_list, sizeof(resc_list))); } setup_pelog_arguments(pelog, pjob, which, arg); setup_pelog_environment(pjob, which); /* * if we want to run as user then we need to reset real user permissions * since it seems that some OSs use real not effective user id when execv'ing */ if ((which == PE_PROLOGUSER) || (which == PE_EPILOGUSER) || (which == PE_PROLOGUSERJOB) || (which == PE_EPILOGUSERJOB)) { setuid_ext(pbsuser, TRUE); setegid(pbsgroup); if (become_the_user(pjob) != PBSE_NONE) { exit(-1); } } execv(pelog,arg); /* should not be reached, but clean up if error */ sprintf(log_buffer,"execv of %s failed: %s\n", pelog, strerror(errno)); if (write_ac_socket(2, log_buffer, strlen(log_buffer)) == -1) { /* cannot write message to stderr */ /* NO-OP */ } fsync(2); exit(255); } /* END prepare_and_run_pelog_as_child() */
END_TEST #endif START_TEST(test_become_the_user) { int rc; job *pjob; int uid; int gid; // must be root to run this test if (getuid() != 0) return; pjob = (job *)calloc(1, sizeof(job)); fail_unless(pjob != NULL); pjob->ji_grpcache = (struct grpcache *)calloc(1, sizeof(struct grpcache)); fail_unless(pjob->ji_grpcache != NULL); pjob->ji_qs.ji_un.ji_momt.ji_exuid = 500; pjob->ji_qs.ji_un.ji_momt.ji_exgid = 500; pjob->ji_grpcache->gc_ngroup = 1; pjob->ji_grpcache->gc_groups[0] = 500; // fork so we can test the setxid/setexid calls in the child rc = fork(); fail_unless(rc != -1); if (rc > 0) { int status; // parent wait(&status); return; } // child rc = become_the_user(pjob, true); fail_unless(rc == PBSE_NONE); // check the group list, uid, gid uid = geteuid(); gid = getegid(); fail_unless(uid != 500); fail_unless(gid != 500); // put things back in place fail_unless(seteuid(0) == 0); fail_unless(setegid(0) == 0); rc = become_the_user(pjob, false); fail_unless(rc == PBSE_NONE); // check the uid, gid uid = getuid(); gid = getgid(); fail_unless(uid != 500); fail_unless(gid != 500); }