/* * Unshare file descriptor table if it is being shared */ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp) { struct files_struct *fd = current->files; int error = 0; if ((unshare_flags & CLONE_FILES) && (fd && atomic_read(&fd->count) > 1)) { *new_fdp = dup_fd(fd, &error); if (!*new_fdp) return error; } return 0; }
pid_t pty_fork(int *ptrfdm, char** pts_name) { pid_t pid; char* name; int master_fd, pty_fd; if ((master_fd = ptm_open()) < 0) { err_sys("ERROR: ptm_open() failed [%d]\n", master_fd); } if ((name = ptsname(master_fd)) == NULL) { close(master_fd); return -1; } // Put values to the output params *pts_name = name; *ptrfdm = master_fd; if ((pid = fork()) < 0) { printf("FAILED"); return (-1); } if (pid == 0) { /* child */ if (setsid() < 0) { err_sys("setsid error"); } if ((pty_fd = pts_open(master_fd)) < 0) { err_sys("can't open slave pty"); } close(master_fd); dup_fd(pty_fd); return (0); /* child returns 0 just like fork() */ } else { /* parent */ return (pid); /* parent returns pid of child */ } }
static int copy_files(unsigned long clone_flags, struct task_struct *tsk) { struct files_struct *oldf, *newf; int error = 0; oldf = current->files; if (!oldf) goto out; if (clone_flags & CLONE_FILES) { atomic_inc(&oldf->count); goto out; } newf = dup_fd(oldf, &error); if (!newf) goto out; tsk->files = newf; error = 0; out: return error; }
int _user_dup(int fd) { return dup_fd(fd, false); }
int _kern_dup(int fd) { return dup_fd(fd, true); }
/****** err_trace/shepherd_trace_init_intern() ******************************* * NAME * shepherd_trace_init_intern() -- Initialize shepherd's tracing. * * SYNOPSIS * static FILE* shepherd_trace_init(char *trace_file_path, * char *trace_file_name) * * FUNCTION * Opens the shepherd's trace file and sets the FD_CLOEXEC-flag so it will * be closed automatically in an exec()-call. * Must be called with euid=admin user to work properly! * * INPUTS * char *trace_file_path - either the whole path of the trace file (including * the file itself) * or NULL to retrieve the file pointer of an already * opened trace file. * char *trace_file_name - the name of the trace file itself. Ignored when * *trace_file_path is NULL. * * RESULT * FILE* - If successfully opened, the file pointer of shepherd's trace file. * - Otherwise NULL. *******************************************************************************/ static FILE* shepherd_trace_init_intern(st_shepherd_file_t shepherd_file) { static char path[SGE_PATH_MAX]; static bool called = false; SGE_STRUCT_STAT statbuf; dstring ds; char buffer[SGE_PATH_MAX+128]; char tmppath[SGE_PATH_MAX]; int fd = -1; FILE *fp = NULL; int do_chown = 0; /* * after changing into the jobs cwd we need an * absolute path to the error/trace file */ if (called == false) { getcwd(path, sizeof(path)); called=true; } snprintf(tmppath, SGE_PATH_MAX,"%s/%s",path, g_shepherd_file_name[shepherd_file]); sge_strlcpy(g_shepherd_file_path[shepherd_file], tmppath, SGE_PATH_MAX); /* If the file does not exist, create it. Otherwise just open it. */ if (SGE_STAT(tmppath, &statbuf)) { fd = SGE_OPEN3(tmppath, O_RDWR | O_CREAT | O_APPEND, 0644); if (fd<0) { sge_dstring_init(&ds, buffer, sizeof(buffer)); sge_dstring_sprintf(&ds, "creat(%s) failed: %s", tmppath, strerror(errno)); shepherd_panic(buffer); } if (getuid() == SGE_SUPERUSER_UID) { /* We must give the file to the job owner later */ do_chown = 1; } else { /* We are not root, so we have to own all files anyway. */ do_chown = 0; } } else { /* The file already exists. We get here when * a) a exec() failed or * b) after the execution of prolog/job, when the job/epilog * tries to init the error/exit status files. * * In a root system we can just open the file, because we are either * root or the job user who owns the file. * In a admin user system we must set our euid to root to open it, then * it is the same as the root system. * In a test user system we are the owner of the file and can open it. * * When we are root (masked or not), we gave this file to the * prolog user/job user right after its creation. But we can have * 3 different users for prolog, job and epilog, so we must give * the file here to the next user. * This must be done via shepherd_trace_chown() in the shepherd * before we switch to this user there. * It can't be done here because we don't know if we are in * case a) (exec failed) or case b) (after execution of prolog/job). */ int old_euid = SGE_SUPERUSER_UID; /* * Work around for CR 6293411: * See shepherd_trace_exit() for details. */ if (getuid() == SGE_SUPERUSER_UID) { old_euid = geteuid(); seteuid(SGE_SUPERUSER_UID); } fd = SGE_OPEN2(tmppath, O_RDWR | O_APPEND); if (fd<0) { sge_dstring_init(&ds, buffer, sizeof(buffer)); sge_dstring_sprintf(&ds, "open(%s) failed: %s", tmppath, strerror(errno)); shepherd_panic(buffer); } do_chown = 0; /* * Switch back to admin user? */ if (old_euid != SGE_SUPERUSER_UID) { seteuid(old_euid); } } /* Something went wrong. */ if (fd<0) { return NULL; } /* To avoid to block stdin, stdout or stderr, dup the fd until it is >= 3 */ if (fd<3) { dup_fd(&fd); } /* Set FD_CLOEXEC flag to automatically close the file in an exec() */ if (!set_cloexec(fd)) { shepherd_panic("set_cloexec() failed"); return NULL; } /* * Now open a FILE* from the file descriptor, so we can use fprintf(). */ fp = fdopen(fd, "a"); if (!fp) { sge_dstring_init(&ds, buffer, sizeof(buffer)); sge_dstring_sprintf(&ds, "can't open %s file \"%s\": %s\n", g_shepherd_file_name[shepherd_file], tmppath, strerror(errno)); shepherd_panic(buffer); return NULL; } if (do_chown && strlen(g_job_owner) > 0) { shepherd_trace_chown_intern(g_job_owner, fp, shepherd_file); } return fp; }