int pty_open (int *pid, struct winsize *winsize, char **chargv, char **chenvp) { int pty = -1; int i; char line[20]; int c; int tty, devtty; for (c = 'a'; c <= 'z'; c++) { for (i = 0; i < 16; i++) { sprintf (line, "/dev/pty%c%x", c, i); pty = open (line, O_RDWR | O_NOCTTY); if (pty >= 0) break; } if (pty >= 0) break; } if (pty < 0) { fprintf (stderr, "Out of pty\n"); return -1; } ioctl (pty, TIOCEXCL, NULL); if ((*pid = fork ()) != 0) { /* Father */ return pty; } /* Child */ close (pty); setenv ("TERM", "linux", 1); line[5] = 't'; tty = open (line, O_RDWR); if (tty < 0) { fprintf (stderr, "Cannot open slave side\n"); close (pty); return -1; } (void) chown (line, getuid (), getgid ()); (void) chmod (line, 0600); setsid (); /* will break terminal affiliation */ ioctl (tty, TIOCSCTTY, (char *) 0); setuid (getuid ()); setgid (getgid ()); devtty = open ("/dev/tty", O_RDWR); if (devtty < 0) { perror ("cannot open /dev/tty"); exit (1); } /* if (ioctl(devtty, TIOCNOTTY, (char *)0)) { perror("cannot do iotctl TIOCNOTTY"); exit(1); } */ ioctl (devtty, TIOCSWINSZ, winsize); close (tty); dup2 (devtty, 0); dup2 (devtty, 1); dup2 (devtty, 2); execve (chargv[0], chargv, chenvp); exit (0); }
BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { pid_t pid; int flags; int numArgs; LPSTR* pArgs = NULL; char** envp = NULL; char* filename = NULL; HANDLE thread; HANDLE process; WINPR_ACCESS_TOKEN* token; LPTCH lpszEnvironmentBlock; BOOL ret = FALSE; pid = 0; numArgs = 0; lpszEnvironmentBlock = NULL; pArgs = CommandLineToArgvA(lpCommandLine, &numArgs); flags = 0; token = (WINPR_ACCESS_TOKEN*) hToken; if (lpEnvironment) { envp = EnvironmentBlockToEnvpA(lpEnvironment); } else { lpszEnvironmentBlock = GetEnvironmentStrings(); envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock); } filename = FindApplicationPath(pArgs[0]); if (NULL == filename) goto finish; /* fork and exec */ pid = fork(); if (pid < 0) { /* fork failure */ goto finish; } if (pid == 0) { /* child process */ #ifdef __sun closefrom(3); #else int maxfd; #ifdef F_MAXFD // on some BSD derivates maxfd = fcntl(0, F_MAXFD); #else maxfd = sysconf(_SC_OPEN_MAX); #endif int fd; for(fd=3; fd<maxfd; fd++) close(fd); #endif // __sun if (token) { if (token->GroupId) { int rc = setgid((gid_t) token->GroupId); if (rc < 0) { } else { initgroups(token->Username, (gid_t) token->GroupId); } } if (token->UserId) setuid((uid_t) token->UserId); /* TODO: add better cwd handling and error checking */ if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0) chdir(lpCurrentDirectory); } if (execve(filename, pArgs, envp) < 0) { /* execve failed - end the process */ _exit(1); } } else { /* parent process */ } process = CreateProcessHandle(pid); if (!process) { goto finish; } thread = CreateNoneHandle(); if (!thread) { ProcessHandleCloseHandle(process); goto finish; } lpProcessInformation->hProcess = process; lpProcessInformation->hThread = thread; lpProcessInformation->dwProcessId = (DWORD) pid; lpProcessInformation->dwThreadId = (DWORD) pid; ret = TRUE; finish: if (filename) { free(filename); } if (pArgs) { HeapFree(GetProcessHeap(), 0, pArgs); } if (lpszEnvironmentBlock) FreeEnvironmentStrings(lpszEnvironmentBlock); if (envp) { int i = 0; while (envp[i]) { free(envp[i]); i++; } free(envp); } return ret; }
int startup(int argc, char* argv[]) { const char* tmp; const char* end; const char* cwdstr; char* ptr; unsigned long session_timeout; unsigned startup_code; if ((tmp = getenv("TCPLOCALIP")) == 0) FAIL("Missing $TCPLOCALIP."); if (!parse_localip(tmp)) FAIL("Could not parse $TCPLOCALIP."); if ((tmp = getenv("TCPREMOTEIP")) == 0) FAIL("Missing $TCPREMOTEIP."); if (!parse_remoteip(tmp)) FAIL("Could not parse $TCPREMOTEIP."); if ((tmp = getenv("UID")) == 0) FAIL("Missing $UID."); if (!(uid = strtou(tmp, &end)) || *end) FAIL("Invalid $UID."); if ((tmp = getenv("GID")) == 0) FAIL("Missing $GID."); if (!(gid = strtou(tmp, &end)) || *end) FAIL("Invalid $GID."); if ((home = getenv("HOME")) == 0) FAIL("Missing $HOME."); if ((tmp = getenv("GIDS")) != 0 && !parse_gids(tmp)) FAIL("Could not parse or set supplementary group IDs."); /* Strip off trailing slashes in $HOME */ ptr = (char*)home + strlen(home)-1; while (ptr > home && *ptr == '/') *ptr-- = 0; if ((user = getenv("USER")) == 0) FAIL("Missing $USER."); if ((group = getenv("GROUP")) == 0) group = "mygroup"; if (chdir(home)) FAIL("Could not chdir to $HOME."); if (!load_tables()) FAIL("Loading startup tables failed."); if (getenv("CHROOT") != 0) { cwdstr = "/"; if (chroot(".")) FAIL("Could not chroot."); } else if (getenv("SOFTCHROOT") != 0) { cwdstr = "/"; } else { cwdstr = home; if (chdir("/")) FAIL("Could not chdir to '/'."); } if (!str_copys(&cwd, cwdstr)) FAIL("Could not set CWD string"); if (setgid(gid)) FAIL("Could not set GID."); if (setuid(uid)) FAIL("Could not set UID."); if ((user_len = strlen(user)) > MAX_NAME_LEN) { user_len = MAX_NAME_LEN; ((char*)user)[MAX_NAME_LEN] = 0; } if ((group_len = strlen(group)) > MAX_NAME_LEN) { group_len = MAX_NAME_LEN; ((char*)group)[MAX_NAME_LEN] = 0; } lockhome = (getenv("LOCKHOME") != 0); nodotfiles = (getenv("NODOTFILES") != 0); list_options = (nodotfiles ? 0 : PATH_MATCH_DOTFILES); session_timeout = 0; if ((tmp = getenv("SESSION_TIMEOUT")) != 0) session_timeout = strtou(tmp, &tmp); alarm(session_timeout); connect_timeout = timeout; if ((tmp = getenv("CONNECT_TIMEOUT")) != 0) connect_timeout = strtou(tmp, &tmp); if ((tmp = getenv("TWOFTPD_BIND_PORT_FD")) != 0) { if ((bind_port_fd = strtou(tmp, &end)) == 0 || *end != 0) FAIL("Invalid $TWOFTPD_BIND_PORT_FD"); } else bind_port_fd = -1; startup_code = (getenv("AUTHENTICATED") != 0) ? 230 : 220; if ((tmp = getenv("BANNER")) != 0) show_banner(startup_code, tmp); message_file = getenv("MESSAGEFILE"); show_message_file(startup_code); return respond(startup_code, 1, "Ready to transfer files."); (void)argc; (void)argv; }
int os_server_start_2(const char *user, int close_stdfiles) { int istat; gid_t gid, old_egid, old_gid; uid_t uid, old_euid, old_uid; /* * Close all open files but stdout & stderr */ if (close_stdfiles) { if (stderr) { fflush(stderr); fclose(stderr); } else { fsync(2); close(2); } if (stdout) { fflush(stdout); fclose(stdout); } else { fsync(1); close(1); } if (stdin) fclose(stdin); else close(0); os_close_files(3, 20); } /* * Change our uid & gid */ if (user && *user) { if (os_uinfo(&uid, &gid, user)) return(-1); /* * In case things fail.... */ old_euid = geteuid(); old_uid = getuid(); old_egid = getegid(); old_gid = getgid(); /* * On some platforms you first have to elevate the effective UID to * root before changing real & effective UID to a non-root UID. */ seteuid(0); /* * Now do an irreversible change of our UID and GID */ if (setgid(gid)) { int save_errno = errno; seteuid(old_euid); errno = save_errno; return(-1); } if (setuid(uid)) { int save_errno = errno; seteuid(old_euid); setgid(old_gid); setegid(old_egid); errno = save_errno; return(-1); } } return(0); }
int main(int ac, char *av[]) { int ret; struct stat buf; struct group *group; struct passwd *user1; char DIR_A[MSGSIZE], DIR_B[MSGSIZE]; char setgid_A[MSGSIZE], nosetgid_A[MSGSIZE]; char setgid_B[MSGSIZE], nosetgid_B[MSGSIZE], root_setgid_B[MSGSIZE]; gid_t group1_gid, group2_gid, mygid; uid_t save_myuid, user1_uid; pid_t mypid; int lc; int fail_count = 0; tst_parse_opts(ac, av, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { local_flag = PASSED; save_myuid = getuid(); mypid = getpid(); sprintf(DIR_A, DIR_A_TEMP, mypid); sprintf(DIR_B, DIR_B_TEMP, mypid); sprintf(setgid_A, "%s/%s", DIR_A, SETGID); sprintf(nosetgid_A, "%s/%s", DIR_A, NOSETGID); sprintf(setgid_B, "%s/%s", DIR_B, SETGID); sprintf(nosetgid_B, "%s/%s", DIR_B, NOSETGID); sprintf(root_setgid_B, "%s/%s", DIR_B, ROOT_SETGID); /* Get the uid of user1 */ user1 = getpwnam("nobody"); if (user1 == NULL) tst_brkm(TBROK, cleanup, "nobody not in /etc/passwd"); user1_uid = user1->pw_uid; /* * Get the group IDs of group1 and group2. */ group = getgrnam("nobody"); if (group == NULL) { group = getgrnam("nogroup"); if (group == NULL) { tst_brkm(TBROK, cleanup, "nobody/nogroup not in /etc/group"); } } group1_gid = group->gr_gid; group = getgrnam("bin"); if (group == NULL) tst_brkm(TBROK, cleanup, "bin not in /etc/group"); group2_gid = group->gr_gid; /* * Create a directory with group id the same as this process * and with no setgid bit. */ if (mkdir(DIR_A, MODE_RWX) < 0) { tst_resm(TFAIL | TERRNO, "mkdir(%s) failed", DIR_A); local_flag = FAILED; } if (chown(DIR_A, user1_uid, group2_gid) < 0) { tst_resm(TFAIL | TERRNO, "chown(%s) failed", DIR_A); local_flag = FAILED; } if (stat(DIR_A, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", DIR_A); local_flag = FAILED; } /* Verify modes */ if (buf.st_mode & S_ISGID) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit set", DIR_A); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != group2_gid) { tst_resm(TFAIL, "%s: Incorrect group (got %d and %d)", DIR_A, buf.st_gid, group2_gid); local_flag = FAILED; } /* * Create a directory with group id different from that of * this process and with the setgid bit set. */ if (mkdir(DIR_B, MODE_RWX) < 0) { tst_resm(TFAIL | TERRNO, "mkdir(%s) failed", DIR_B); local_flag = FAILED; } if (chown(DIR_B, user1_uid, group2_gid) < 0) { tst_resm(TFAIL | TERRNO, "chown(%s) failed", DIR_B); local_flag = FAILED; } if (chmod(DIR_B, MODE_SGID) < 0) { tst_resm(TFAIL | TERRNO, "chmod(%s) failed", DIR_B); local_flag = FAILED; } if (stat(DIR_B, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", DIR_B); local_flag = FAILED; } /* Verify modes */ if (!(buf.st_mode & S_ISGID)) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set", DIR_B); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != group2_gid) { tst_resm(TFAIL, "%s: Incorrect group (got %d and %d)", DIR_B, buf.st_gid, group2_gid); local_flag = FAILED; } if (local_flag == PASSED) { tst_resm(TPASS, "Test passed in block0."); } else { tst_resm(TFAIL, "Test failed in block0."); fail_count++; } local_flag = PASSED; /* * Create two files in testdir.A, one with the setgid * bit set in the creation modes and the other without. * Both should inherit the group ID of the process and * maintain the setgid bit as specified in the creation * modes. */ if (setgid(group1_gid) < 0) { tst_resm(TINFO, "Unable to set process group ID to group1"); } if (setreuid(-1, user1_uid) < 0) tst_resm(TINFO, "Unable to set process uid to user1"); mygid = getgid(); /* * Create the file with setgid not set */ ret = open(nosetgid_A, O_CREAT | O_EXCL | O_RDWR, MODE_RWX); if (ret < 0) { tst_resm(TFAIL | TERRNO, "open(%s) failed", nosetgid_A); local_flag = FAILED; } close(ret); if (stat(nosetgid_A, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", nosetgid_A); local_flag = FAILED; } /* Verify modes */ if (buf.st_mode & S_ISGID) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit set", nosetgid_A); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != mygid) { tst_resm(TFAIL, "%s: Incorrect group (got %d and %d)", nosetgid_A, buf.st_gid, mygid); local_flag = FAILED; } /* * Create the file with setgid set */ ret = open(setgid_A, O_CREAT | O_EXCL | O_RDWR, MODE_SGID); if (ret < 0) { tst_resm(TFAIL | TERRNO, "open(%s) failed", setgid_A); local_flag = FAILED; } close(ret); if (stat(setgid_A, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", setgid_A); local_flag = FAILED; } /* Verify modes */ if (!(buf.st_mode & S_ISGID)) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set", setgid_A); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != mygid) { tst_resm(TFAIL, "%s: Incorrect group (%d and %d)", setgid_A, buf.st_gid, mygid); local_flag = FAILED; } if (local_flag == PASSED) { tst_resm(TPASS, "Test passed in block1."); } else { tst_resm(TFAIL, "Test failed in block1."); fail_count++; } local_flag = PASSED; /* * Create two files in testdir.B, one with the setgid * bit set in the creation modes and the other without. * Both should inherit the group ID of the parent * directory, group2. Either file should have the segid * bit set in the modes. */ /* * Create the file with setgid not set */ ret = open(nosetgid_B, O_CREAT | O_EXCL | O_RDWR, MODE_RWX); if (ret < 0) { tst_resm(TFAIL | TERRNO, "open(%s) failed", nosetgid_B); local_flag = FAILED; } close(ret); if (stat(nosetgid_B, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", nosetgid_B); local_flag = FAILED; } /* Verify modes */ if (buf.st_mode & S_ISGID) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit should be set", nosetgid_B); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != group2_gid) { tst_resm(TFAIL, "%s: Incorrect group (got %d and %d)", nosetgid_B, buf.st_gid, group2_gid); local_flag = FAILED; } /* * Create the file with setgid set */ ret = open(setgid_B, O_CREAT | O_EXCL | O_RDWR, MODE_SGID); if (ret < 0) { tst_resm(TFAIL | TERRNO, "open(%s) failed", setgid_B); local_flag = FAILED; } close(ret); if (stat(setgid_B, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", setgid_B); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != group2_gid) { tst_resm(TFAIL, "%s: Incorrect group (got %d and %d)", setgid_B, buf.st_gid, group2_gid); local_flag = FAILED; } /* Verify modes */ if (!(buf.st_mode & S_ISGID)) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set", setgid_B); local_flag = FAILED; } if (local_flag == PASSED) { tst_resm(TPASS, "Test passed in block2."); } else { tst_resm(TFAIL, "Test failed in block2."); fail_count++; } local_flag = PASSED; /* * Create a file in testdir.B, with the setgid bit set * in the creation modes and do so as root. The file * should inherit the group ID of the parent directory, * group2 and should have the setgid bit set. */ /* Become root again */ if (setreuid(-1, save_myuid) < 0) { tst_resm(TFAIL | TERRNO, "Changing back to root failed"); local_flag = FAILED; } /* Create the file with setgid set */ ret = open(root_setgid_B, O_CREAT | O_EXCL | O_RDWR, MODE_SGID); if (ret < 0) { tst_resm(TFAIL | TERRNO, "open(%s) failed", root_setgid_B); local_flag = FAILED; } close(ret); if (stat(root_setgid_B, &buf) < 0) { tst_resm(TFAIL | TERRNO, "stat(%s) failed", root_setgid_B); local_flag = FAILED; } /* Verify modes */ if (!(buf.st_mode & S_ISGID)) { tst_resm(TFAIL, "%s: Incorrect modes, setgid bit not set", root_setgid_B); local_flag = FAILED; } /* Verify group ID */ if (buf.st_gid != group2_gid) { tst_resm(TFAIL, "%s: Incorrect group (got %d and %d)", root_setgid_B, buf.st_gid, group2_gid); local_flag = FAILED; } if (local_flag == PASSED) { tst_resm(TPASS, "Test passed in block3."); } else { tst_resm(TFAIL, "Test failed in block3."); fail_count++; } /* * Clean up any files created by test before call to anyfail. * Remove the directories. */ if (unlink(setgid_A) < 0) tst_resm(TWARN | TERRNO, "unlink(%s) failed", setgid_A); if (unlink(nosetgid_A) < 0) tst_resm(TWARN | TERRNO, "unlink(%s) failed", nosetgid_A); if (rmdir(DIR_A) < 0) tst_resm(TWARN | TERRNO, "rmdir(%s) failed", DIR_A); if (unlink(setgid_B) < 0) tst_resm(TWARN | TERRNO, "unlink(%s) failed", setgid_B); if (unlink(root_setgid_B) < 0) tst_resm(TWARN | TERRNO, "unlink(%s) failed", root_setgid_B); if (unlink(nosetgid_B) < 0) tst_resm(TWARN | TERRNO, "unlink(%s) failed", nosetgid_B); if (rmdir(DIR_B) < 0) tst_resm(TWARN | TERRNO, "rmdir(%s) failed", DIR_B); if (fail_count == 0) { tst_resm(TPASS, "Test passed."); } else { tst_resm(TFAIL, "Test failed because of above failures."); } } cleanup(); tst_exit(); }
static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) { sigset_t set; uint64_t cpu_affinity; ngx_int_t n; ngx_uint_t i; struct rlimit rlmt; ngx_core_conf_t *ccf; ngx_listening_t *ls; if (ngx_set_environment(cycle, NULL) == NULL) { /* fatal */ exit(2); } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (worker >= 0 && ccf->priority != 0) { if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setpriority(%d) failed", ccf->priority); } } if (ccf->rlimit_nofile != NGX_CONF_UNSET) { rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile; rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile; if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setrlimit(RLIMIT_NOFILE, %i) failed", ccf->rlimit_nofile); } } if (ccf->rlimit_core != NGX_CONF_UNSET) { rlmt.rlim_cur = (rlim_t) ccf->rlimit_core; rlmt.rlim_max = (rlim_t) ccf->rlimit_core; if (setrlimit(RLIMIT_CORE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setrlimit(RLIMIT_CORE, %O) failed", ccf->rlimit_core); } } #ifdef RLIMIT_SIGPENDING if (ccf->rlimit_sigpending != NGX_CONF_UNSET) { rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending; rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending; if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setrlimit(RLIMIT_SIGPENDING, %i) failed", ccf->rlimit_sigpending); } } #endif if (geteuid() == 0) { if (setgid(ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setgid(%d) failed", ccf->group); /* fatal */ exit(2); } if (initgroups(ccf->username, ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "initgroups(%s, %d) failed", ccf->username, ccf->group); } if (setuid(ccf->user) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setuid(%d) failed", ccf->user); /* fatal */ exit(2); } } if (worker >= 0) { cpu_affinity = ngx_get_cpu_affinity(worker); if (cpu_affinity) { ngx_setaffinity(cpu_affinity, cycle->log); } } #if (NGX_HAVE_PR_SET_DUMPABLE) /* allow coredump after setuid() in Linux 2.4.x */ if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "prctl(PR_SET_DUMPABLE) failed"); } #endif if (ccf->working_directory.len) { if (chdir((char *) ccf->working_directory.data) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "chdir(\"%s\") failed", ccf->working_directory.data); /* fatal */ exit(2); } } sigemptyset(&set); if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } srandom((ngx_pid << 16) ^ ngx_time()); /* * disable deleting previous events for the listening sockets because * in the worker processes there are no events at all at this point */ ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].previous = NULL; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_process) { if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } } } for (n = 0; n < ngx_last_process; n++) { if (ngx_processes[n].pid == -1) { continue; } if (n == ngx_process_slot) { continue; } if (ngx_processes[n].channel[1] == -1) { continue; } if (close(ngx_processes[n].channel[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "close() channel failed"); } } if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "close() channel failed"); } #if 0 ngx_last_process = 0; #endif if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler) == NGX_ERROR) { /* fatal */ exit(2); } }
int daemon_start(int allow_root, const char* user) { pid_t pid; struct passwd *pwd; struct sigaction phan; /* running as root ?*/ if((0 == allow_root) && (0 == getuid() || 0 == getgid())) { pwd = getpwnam(user); if (NULL == pwd) { zbx_error("User %s does not exist.", user); zbx_error("Cannot run as root !"); exit(FAIL); } if(setgid(pwd->pw_gid) ==-1) { zbx_error("Cannot setgid to %s [%s].", user, strerror(errno)); exit(FAIL); } #ifdef HAVE_FUNCTION_INITGROUPS if(initgroups(user, pwd->pw_gid) == -1) { zbx_error("Cannot initgroups to %s [%s].", user, strerror(errno)); exit(FAIL); } #endif /* HAVE_FUNCTION_INITGROUPS */ if(setuid(pwd->pw_uid) == -1) { zbx_error("Cannot setuid to %s [%s].", user, strerror(errno)); exit(FAIL); } #ifdef HAVE_FUNCTION_SETEUID if( (setegid(pwd->pw_gid) ==-1) || (seteuid(pwd->pw_uid) == -1) ) { zbx_error("Cannot setegid or seteuid to zabbix [%s].", strerror(errno)); exit(FAIL); } #endif /* HAVE_FUNCTION_SETEUID */ } if( (pid = zbx_fork()) != 0 ) { exit( 0 ); } setsid(); signal( SIGHUP, SIG_IGN ); if( (pid = zbx_fork()) !=0 ) { exit( 0 ); } /* This is to eliminate warning: ignoring return value of chdir */ if(-1 == chdir("/")) { assert(0); } umask(0002); redirect_std(CONFIG_LOG_FILE); #ifdef HAVE_SYS_RESOURCE_SETPRIORITY if(setpriority(PRIO_PROCESS,0,5)!=0) { zbx_error("Unable to set process priority to 5. Leaving default."); } #endif /* HAVE_SYS_RESOURCE_SETPRIORITY */ /*------------------------------------------------*/ if( FAIL == create_pid_file(APP_PID_FILE)) { exit(FAIL); } phan.sa_handler = child_signal_handler; sigemptyset(&phan.sa_mask); phan.sa_flags = 0; sigaction(SIGINT, &phan, NULL); sigaction(SIGQUIT, &phan, NULL); sigaction(SIGTERM, &phan, NULL); sigaction(SIGPIPE, &phan, NULL); zbx_setproctitle("main process"); return MAIN_ZABBIX_ENTRY(); }
int main(int argc, char *argv[]) { struct group *gp; struct passwd *pw; char *endp, *p, *user, *group, *grouplist; const char *shell; gid_t gid, *gidlist; uid_t uid; int ch, gids; long ngroups_max; gid = 0; uid = 0; user = group = grouplist = NULL; while ((ch = getopt(argc, argv, "G:g:u:")) != -1) { switch(ch) { case 'u': user = optarg; if (*user == '\0') usage(); break; case 'g': group = optarg; if (*group == '\0') usage(); break; case 'G': grouplist = optarg; if (*grouplist == '\0') usage(); break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc < 1) usage(); if (group != NULL) { if (isdigit((unsigned char)*group)) { gid = (gid_t)strtoul(group, &endp, 0); if (*endp != '\0') goto getgroup; } else { getgroup: if ((gp = getgrnam(group)) != NULL) gid = gp->gr_gid; else errx(1, "no such group `%s'", group); } } ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL) err(1, "malloc"); for (gids = 0; (p = strsep(&grouplist, ",")) != NULL && gids < ngroups_max; ) { if (*p == '\0') continue; if (isdigit((unsigned char)*p)) { gidlist[gids] = (gid_t)strtoul(p, &endp, 0); if (*endp != '\0') goto getglist; } else { getglist: if ((gp = getgrnam(p)) != NULL) gidlist[gids] = gp->gr_gid; else errx(1, "no such group `%s'", p); } gids++; } if (p != NULL && gids == ngroups_max) errx(1, "too many supplementary groups provided"); if (user != NULL) { if (isdigit((unsigned char)*user)) { uid = (uid_t)strtoul(user, &endp, 0); if (*endp != '\0') goto getuser; } else { getuser: if ((pw = getpwnam(user)) != NULL) uid = pw->pw_uid; else errx(1, "no such user `%s'", user); } } if (chdir(argv[0]) == -1 || chroot(".") == -1) err(1, "%s", argv[0]); if (gids && setgroups(gids, gidlist) == -1) err(1, "setgroups"); if (group && setgid(gid) == -1) err(1, "setgid"); if (user && setuid(uid) == -1) err(1, "setuid"); if (argv[1]) { execvp(argv[1], &argv[1]); err(1, "%s", argv[1]); } if (!(shell = getenv("SHELL"))) shell = _PATH_BSHELL; execlp(shell, shell, "-i", (char *)NULL); err(1, "%s", shell); /* NOTREACHED */ }
static int drop_root(void) { struct passwd *pw; struct group * gr; int r; //Edison modify username 20131023 char dut_user[128]; memset(dut_user, 0, 128); strncpy(dut_user, nvram_safe_get("http_username"), 128); if (!(pw = getpwnam(dut_user))) { avahi_log_error( "Failed to find user '%s'.",dut_user); return -1; } if (!(gr = getgrnam(AVAHI_GROUP))) { avahi_log_error( "Failed to find group '"AVAHI_GROUP"'."); return -1; } avahi_log_info("Found user '%s' (UID %lu) and group '"AVAHI_GROUP"' (GID %lu).",dut_user ,(unsigned long) pw->pw_uid, (unsigned long) gr->gr_gid); if (initgroups(dut_user, gr->gr_gid) != 0) { avahi_log_error("Failed to change group list: %s", strerror(errno)); return -1; } #if defined(HAVE_SETRESGID) r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid); #elif defined(HAVE_SETEGID) if ((r = setgid(gr->gr_gid)) >= 0) r = setegid(gr->gr_gid); #elif defined(HAVE_SETREGID) r = setregid(gr->gr_gid, gr->gr_gid); #else #error "No API to drop privileges" #endif if (r < 0) { avahi_log_error("Failed to change GID: %s", strerror(errno)); return -1; } #if defined(HAVE_SETRESUID) r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); #elif defined(HAVE_SETEUID) if ((r = setuid(pw->pw_uid)) >= 0) r = seteuid(pw->pw_uid); #elif defined(HAVE_SETREUID) r = setreuid(pw->pw_uid, pw->pw_uid); #else #error "No API to drop privileges" #endif if (r < 0) { avahi_log_error("Failed to change UID: %s", strerror(errno)); return -1; } set_env("USER", pw->pw_name); set_env("LOGNAME", pw->pw_name); set_env("HOME", pw->pw_dir); avahi_log_info("Successfully dropped root privileges."); return 0; }
/*{{{ main*/ int main(int argc, char *argv[]) { /*{{{ variables*/ int x, login_y, password_y; char loginstr[9], passwordstr[9], ret; char ttystr[_POSIX_PATH_MAX]; char *background = NULL; char *fontname = NULL; /*}}} */ /*{{{ parse arguments*/ { int c; while ((c = getopt(argc, argv, "b:f:")) != EOF) switch (c) { case 'b': background = optarg; break; case 'f': fontname = optarg; break; } /*{{{ parse tty*/ { int tty; if (optind + 1 > argc) { fprintf(stderr, "Usage: %s tty\n", argv[0]); exit(1); } else { strcpy(ttystr, "/dev/"); strcat(ttystr, argv[optind++]); } close(0); close(1); close(2); setsid(); if ((tty = open(ttystr, O_RDWR)) != 0) { fprintf(stderr, "%s: Can't open controlling terminal on fd 0.\n", argv[0]); exit(1); } fchmod(tty, 0600); fchown(tty, getuid(), getgid()); open(argv[optind], O_RDWR); open(argv[optind], O_RDWR); } /*}}} */ } /*}}} */ /*{{{ get into grafics mode*/ signal(SIGTERM, quit); signal(SIGHUP, quit); set_tty(0); if ((screen = bit_open(SCREEN_DEV)) == NULL) { reset_tty(0); exit(EX_NOPERM); } bit_grafscreen(); /*}}} */ /*{{{ load font*/ if (fontname) { char fontpath[_POSIX_PATH_MAX]; if (*fontname == '/' || *fontname == '.') strcpy(fontpath, fontname); else { strcpy(fontpath, ICONDIR); strcat(fontpath, "/"); strcat(fontpath, fontname); } if ((font = open_font(fontname)) == NULL) font = open_font(NULL); } else font = open_font(NULL); /*}}} */ /*{{{ draw background*/ bit_blit(screen, 0, 0, screen->wide, screen->high, BIT_CLR, NULL, 0, 0); if (background) { BITMAP *bp; FILE *fp; char backgroundpath[_POSIX_PATH_MAX]; if (*background == '/' || *background == '.') strcpy(backgroundpath, background); else { strcpy(backgroundpath, ICONDIR); strcat(backgroundpath, "/"); strcat(backgroundpath, background); } if ((fp = fopen(backgroundpath, "r")) != NULL && (bp = bitmapread(fp)) != NULL) { int x, y; for (x = 0; x < screen->wide; x += bp->wide) bit_blit( screen, x, 0, screen->wide - x < bp->wide ? screen->wide - x : bp->wide, bp->high, BIT_SRC, bp, 0, 0); for (y = 0; y < screen->high; y += bp->high) bit_blit( screen, 0, y, screen->wide, screen->high - y < bp->high ? screen->high - y : bp->high, BIT_SRC, screen, 0, 0); } } /*}}} */ /*{{{ draw hostname*/ { int bx, bw, by, bh; char hostname[_POSIX_PATH_MAX]; struct hostent *h; gethostname(hostname, sizeof(hostname)); if ((h = gethostbyname(hostname)) != NULL) strcpy(hostname, h->h_name); bw = font->head.wide * (strlen(hostname) + 2); bh = 2 * font->head.high; bx = (screen->wide - bw) / 2; by = screen->high / 6 - bh / 2; cutebox(bx, by, bw, bh); printstr(bx + font->head.wide, by + bh - font->head.high / 2, hostname); } /*}}} */ /*{{{ draw login box*/ { int bx, bw, by, bh; bx = (screen->wide - font->head.wide * 40) / 2; by = (screen->high - font->head.high * 8) / 2; bw = font->head.wide * 40; bh = font->head.high * 8; cutebox(bx, by, bw, bh); } /*}}} */ /*{{{ draw login box contents*/ x = (screen->wide - font->head.wide * 18) / 2; login_y = screen->high / 2 - font->head.wide / 6; password_y = screen->high / 2 + font->head.high / 6 + font->head.high; printstr(x, password_y, "Password: "******"Press ESC for terminal login"); /*}}} */ while (1) { /*{{{ get login and password or escape*/ printstr(x, login_y, "Login: "******"mgr", NULL }; int i; sprintf(env_user, "USER=%s", pw->pw_name); sprintf(env_logname, "LOGNAME=%s", pw->pw_name); sprintf(env_home, "HOME=%s", pw->pw_dir); sprintf(env_shell, "SHELL=%s", pw->pw_shell == NULL || pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell); sprintf(env_path, "PATH=%s", PATH); sprintf(env_mail, "MAIL=%s/%s", MAILDIR, pw->pw_name); if (chdir(pw->pw_dir) != 0) chdir("/"); if (ttyname(0)) { chown(ttyname(0), pw->pw_uid, pw->pw_gid); chmod(ttyname(0), 0600); } for (i = 1; i <= _NSIG; i++) signal(i, SIG_DFL); bit_destroy(screen); reset_tty(0); initgroups(pw->pw_name, pw->pw_gid); setgid(pw->pw_gid); setuid(pw->pw_uid); sprintf(mgrlogin, "%s/.mgrlogin", pw->pw_dir); execve(mgrlogin, login_argv, login_env); execve(MGR_BINARY, login_argv, login_env); exit(EX_OSFILE); } /*}}} */ else /*{{{ incorrect login*/ { printstr((screen->wide - font->head.wide * 16) / 2, login_y + 3 * font->head.high, "Login incorrect"); } /*}}} */ } /*}}} */ } }
int main(int argc, char **argv) { int i; int rval,ll; struct text *kk; /* If the user hits start, bail */ cont_btn_callback(0, CONT_START, (cont_btn_callback_t)arch_exit); pvr_init_defaults(); conio_init(CONIO_TTY_PVR, CONIO_INPUT_LINE); #if 0 /* revoke */ setgid(getgid()); #endif init(); /* Initialize everything */ /* signal(SIGINT,trapdel); */ #if 0 if (argc > 1) /* Restore file specified */ { /* Restart is label 8305 (Fortran) */ i = restore(argv[1]); /* See what we've got */ switch(i) { case 0: /* The restore worked fine */ yea=Start(); k=null; unlink(argv[1]);/* Don't re-use the save */ goto l8; /* Get where we're going */ case 1: /* Couldn't open it */ exit(1); /* So give up */ case 2: /* Oops -- file was altered */ rspeak(202); /* You dissolve */ exit(1); /* File could be non-adventure */ } /* So don't unlink it. */ } #endif startup(); /* prepare for a user */ for (;;) /* main command loop (label 2) */ { if (newloc<9 && newloc!=0 && closng) { rspeak(130); /* if closing leave only by */ newloc=loc; /* main office */ if (!apanic) clock2=15; apanic=TRUE; } rval=fdwarf(); /* dwarf stuff */ if (rval==99) die(99); l2000: if (loc==0) die(99); /* label 2000 */ kk = &stext[loc]; if ((abb[loc]%abbnum)==0 || kk->seekadr==0) kk = <ext[loc]; if (!forced(loc) && dark()) { if (wzdark && pct(35)) { die(90); goto l2000; } kk = &rtext[16]; } if (toting(bear)) rspeak(141); /* 2001 */ speak(kk); k=1; if (forced(loc)) goto l8; if (loc==33 && pct(25)&&!closng) rspeak(8); if (!dark()) { abb[loc]++; for (i=atloc[loc]; i!=0; i=linkx[i]) /*2004 */ { obj=i; if (obj>100) obj -= 100; if (obj==steps && toting(nugget)) continue; if (prop[obj]<0) { if (closed) continue; prop[obj]=0; if (obj==rug||obj==chain) prop[obj]=1; tally--; if (tally==tally2 && tally != 0) if (limit>35) limit=35; } ll = prop[obj]; /* 2006 */ if (obj==steps && loc==fixed[steps]) ll = 1; pspeak(obj, ll); } /* 2008 */ goto l2012; l2009: k=54; /* 2009 */ l2010: spk=k; l2011: rspeak(spk); } l2012: verb=0; /* 2012 */ obj=0; l2600: checkhints(); /* to 2600-2602 */ if (closed) { if (prop[oyster]<0 && toting(oyster)) pspeak(oyster,1); for (i=1; i<100; i++) if (toting(i)&&prop[i]<0) /*2604 */ prop[i] = -1-prop[i]; } wzdark=dark(); /* 2605 */ if (knfloc>0 && knfloc!=loc) knfloc=1; getin(&wd1,&wd2); #if 0 if (delhit) /* user typed a DEL */ { delhit=0; /* reset counter */ strcpy(wd1,"quit"); /* pretend he's quitting*/ *wd2=0; } #endif l2608: if ((foobar = -foobar)>0) foobar=0; /* 2608 */ /* should check here for "magic mode" */ turns++; if (demo && turns>=SHORT) done(1); /* to 13000 */ if (verb==say && *wd2!=0) verb=0; if (verb==say) goto l4090; if (tally==0 && loc>=15 && loc!=33) clock1--; if (clock1==0) { closing(); /* to 10000 */ goto l19999; } if (clock1<0) clock2--; if (clock2==0) { caveclose(); /* to 11000 */ continue; /* back to 2 */ } if (prop[lamp]==1) limit--; if (limit<=30 && here(batter) && prop[batter]==0 && here(lamp)) { rspeak(188); /* 12000 */ prop[batter]=1; if (toting(batter)) drop(batter,loc); limit=limit+2500; lmwarn=FALSE; goto l19999; } if (limit==0) { limit = -1; /* 12400 */ prop[lamp]=0; rspeak(184); goto l19999; } if (limit<0&&loc<=8) { rspeak(185); /* 12600 */ gaveup=TRUE; done(2); /* to 20000 */ } if (limit<=30) { if (lmwarn|| !here(lamp)) goto l19999; /*12200*/ lmwarn=TRUE; spk=187; if (place[batter]==0) spk=183; if (prop[batter]==1) spk=189; rspeak(spk); } l19999: k=43; if (liqloc(loc)==water) k=70; if (!strncmp(wd1,"enter",5) && (!strncmp(wd2,"strea",5)||!strncmp(wd2,"water",5))) goto l2010; if (!strncmp(wd1,"enter",5) && *wd2!=0) goto l2800; if ((strncmp(wd1,"water",5)&&strncmp(wd1,"oil",3)) || (strncmp(wd2,"plant",5)&&strncmp(wd2,"door",4))) goto l2610; if (at(vocab(wd2,1,0))) strcpy(wd2,"pour"); l2610: if (!strncmp(wd1,"west",4)) if (++iwest==10) rspeak(17); l2630: i=vocab(wd1,-1,0); if (i== -1) { spk=60; /* 3000 */ if (pct(20)) spk=61; if (pct(20)) spk=13; rspeak(spk); goto l2600; } k=i%1000; kq=i/1000+1; switch(kq) { case 1: goto l8; case 2: goto l5000; case 3: goto l4000; case 4: goto l2010; default: bug(22); } l8: switch(march()) { case 2: continue; /* i.e. goto l2 */ case 99: die(99); goto l2000; default: bug(110); } l2800: strcpy(wd1,wd2); *wd2=0; goto l2610; l4000: verb=k; spk=actspk[verb]; if (*wd2!=0 && verb!=say) goto l2800; if (verb==say) obj= *wd2; if (obj!=0) goto l4090; switch(verb) { case 1: /* take = 8010 */ if (atloc[loc]==0||linkx[atloc[loc]]!=0) goto l8000; for (i=1; i<=5; i++) if (dloc[i]==loc&&dflag>=2) goto l8000; obj=atloc[loc]; goto l9010; case 2: case 3: case 9: /* 8000 : drop,say,wave */ case 10: case 16: case 17: /* calm,rub,toss */ case 19: case 21: case 28: /* find,feed,break */ case 29: /* wake */ l8000: printf("%s what?\n",wd1); obj=0; goto l2600; case 4: case 6: /* 8040 open,lock */ spk=28; if (here(clam)) obj=clam; if (here(oyster)) obj=oyster; if (at(door)) obj=door; if (at(grate)) obj=grate; if (obj!=0 && here(chain)) goto l8000; if (here(chain)) obj=chain; if (obj==0) goto l2011; goto l9040; case 5: goto l2009; /* nothing */ case 7: goto l9070; /* on */ case 8: goto l9080; /* off */ case 11: goto l8000; /* walk */ case 12: goto l9120; /* kill */ case 13: goto l9130; /* pour */ case 14: /* eat: 8140 */ if (!here(food)) goto l8000; l8142: dstroy(food); spk=72; goto l2011; case 15: goto l9150; /* drink */ case 18: /* quit: 8180 */ gaveup=yes(22,54,54); if (gaveup) done(2); /* 8185 */ goto l2012; case 20: /* invent=8200 */ spk=98; for (i=1; i<=100; i++) { if (i!=bear && toting(i)) { if (spk==98) rspeak(99); blklin=FALSE; pspeak(i,-1); blklin=TRUE; spk=0; } } if (toting(bear)) spk=141; goto l2011; case 22: goto l9220; /* fill */ case 23: goto l9230; /* blast */ case 24: /* score: 8240 */ scorng=TRUE; printf("If you were to quit now, you would score"); printf(" %d out of a possible ",score()); printf("%d.",mxscor); scorng=FALSE; gaveup=yes(143,54,54); if (gaveup) done(2); goto l2012; case 25: /* foo: 8250 */ k=vocab(wd1,3,0); spk=42; if (foobar==1-k) goto l8252; if (foobar!=0) spk=151; goto l2011; l8252: foobar=k; if (k!=4) goto l2009; foobar=0; if (place[eggs]==plac[eggs] ||(toting(eggs)&&loc==plac[eggs])) goto l2011; if (place[eggs]==0&&place[troll]==0&&prop[troll]==0) prop[troll]=1; k=2; if (here(eggs)) k=1; if (loc==plac[eggs]) k=0; move(eggs,plac[eggs]); pspeak(eggs,k); goto l2012; case 26: /* brief=8260 */ spk=156; abbnum=10000; detail=3; goto l2011; case 27: /* read=8270 */ if (here(magzin)) obj=magzin; if (here(tablet)) obj=obj*100+tablet; if (here(messag)) obj=obj*100+messag; if (closed&&toting(oyster)) obj=oyster; if (obj>100||obj==0||dark()) goto l8000; goto l9270; case 30: /* suspend=8300 */ spk=201; if (demo) goto l2011; printf("I can suspend your adventure for you so"); printf(" you can resume later, but\n"); printf("you will have to wait at least"); printf(" %d minutes before continuing.",latncy); if (!yes(200,54,54)) goto l2012; datime(&saved,&savet); ciao(); /* Do we quit? */ continue; /* Maybe not */ case 31: /* hours=8310 */ printf("Colossal cave is closed 9am-5pm Mon "); printf("through Fri except holidays.\n"); goto l2012; default: bug(23); } l4090: switch(verb) { case 1: /* take = 9010 */ l9010: switch(trtake()) { case 2011: goto l2011; case 9220: goto l9220; case 2009: goto l2009; case 2012: goto l2012; default: bug(102); } l9020: case 2: /* drop = 9020 */ switch(trdrop()) { case 2011: goto l2011; case 19000: done(3); case 2012: goto l2012; default: bug(105); } case 3: switch(trsay()) { case 2012: goto l2012; case 2630: goto l2630; default: bug(107); } l9040: case 4: case 6: /* open, close */ switch(tropen()) { case 2011: goto l2011; case 2010: goto l2010; default: bug(106); } case 5: goto l2009; /* nothing */ case 7: /* on 9070 */ l9070: if (!here(lamp)) goto l2011; spk=184; if (limit<0) goto l2011; prop[lamp]=1; rspeak(39); if (wzdark) goto l2000; goto l2012; case 8: /* off */ l9080: if (!here(lamp)) goto l2011; prop[lamp]=0; rspeak(40); if (dark()) rspeak(16); goto l2012; case 9: /* wave */ if ((!toting(obj))&&(obj!=rod||!toting(rod2))) spk=29; if (obj!=rod||!at(fissur)||!toting(obj)||closng) goto l2011; prop[fissur]=1-prop[fissur]; pspeak(fissur,2-prop[fissur]); goto l2012; case 10: case 11: case 18: /* calm, walk, quit */ case 24: case 25: case 26: /* score, foo, brief */ case 30: case 31: /* suspend, hours */ goto l2011; l9120: case 12: /* kill */ switch(trkill()) { case 8000: goto l8000; case 8: goto l8; case 2011: goto l2011; case 2608: goto l2608; case 19000: done(3); default: bug(112); } l9130: case 13: /* pour */ if (obj==bottle||obj==0) obj=liq(); if (obj==0) goto l8000; if (!toting(obj)) goto l2011; spk=78; if (obj!=oil&&obj!=water) goto l2011; prop[bottle]=1; place[obj]=0; spk=77; if (!(at(plant)||at(door))) goto l2011; if (at(door)) { prop[door]=0; /* 9132 */ if (obj==oil) prop[door]=1; spk=113+prop[door]; goto l2011; } spk=112; if (obj!=water) goto l2011; pspeak(plant,prop[plant]+1); prop[plant]=(prop[plant]+2)% 6; prop[plant2]=prop[plant]/2; k=null; goto l8; case 14: /* 9140 - eat */ if (obj==food) goto l8142; if (obj==bird||obj==snake||obj==clam||obj==oyster ||obj==dwarf||obj==dragon||obj==troll ||obj==bear) spk=71; goto l2011; l9150: case 15: /* 9150 - drink */ if (obj==0&&liqloc(loc)!=water&&(liq()!=water ||!here(bottle))) goto l8000; if (obj!=0&&obj!=water) spk=110; if (spk==110||liq()!=water||!here(bottle)) goto l2011; prop[bottle]=1; place[water]=0; spk=74; goto l2011; case 16: /* 9160: rub */ if (obj!=lamp) spk=76; goto l2011; case 17: /* 9170: throw */ switch(trtoss()) { case 2011: goto l2011; case 9020: goto l9020; case 9120: goto l9120; case 8: goto l8; case 9210: goto l9210; default: bug(113); } case 19: case 20: /* 9190: find, invent */ if (at(obj)||(liq()==obj&&at(bottle)) ||k==liqloc(loc)) spk=94; for (i=1; i<=5; i++) if (dloc[i]==loc&&dflag>=2&&obj==dwarf) spk=94; if (closed) spk=138; if (toting(obj)) spk=24; goto l2011; l9210: case 21: /* feed */ switch(trfeed()) { case 2011: goto l2011; default: bug(114); } l9220: case 22: /* fill */ switch(trfill()) { case 2011: goto l2011; case 8000: goto l8000; case 9020: goto l9020; default: bug(115); } l9230: case 23: /* blast */ if (prop[rod2]<0||!closed) goto l2011; bonus=133; if (loc==115) bonus=134; if (here(rod2)) bonus=135; rspeak(bonus); done(2); l9270: case 27: /* read */ if (dark()) goto l5190; if (obj==magzin) spk=190; if (obj==tablet) spk=196; if (obj==messag) spk=191; if (obj==oyster&&hinted[2]&&toting(oyster)) spk=194; if (obj!=oyster||hinted[2]||!toting(oyster) ||!closed) goto l2011; hinted[2]=yes(192,193,54); goto l2012; case 28: /* break */ if (obj==mirror) spk=148; if (obj==vase&&prop[vase]==0) { spk=198; if (toting(vase)) drop(vase,loc); prop[vase]=2; fixed[vase]= -1; goto l2011; } if (obj!=mirror||!closed) goto l2011; rspeak(197); done(3); case 29: /* wake */ if (obj!=dwarf||!closed) goto l2011; rspeak(199); done(3); default: bug(24); } l5000: obj=k; if (fixed[k]!=loc && !here(k)) goto l5100; l5010: if (*wd2!=0) goto l2800; if (verb!=0) goto l4090; printf("What do you want to do with the %s?\n",wd1); goto l2600; l5100: if (k!=grate) goto l5110; if (loc==1||loc==4||loc==7) k=dprssn; if (loc>9&&loc<15) k=entrnc; if (k!=grate) goto l8; l5110: if (k!=dwarf) goto l5120; for (i=1; i<=5; i++) if (dloc[i]==loc&&dflag>=2) goto l5010; l5120: if ((liq()==k&&here(bottle))||k==liqloc(loc)) goto l5010; if (obj!=plant||!at(plant2)||prop[plant2]==0) goto l5130; obj=plant2; goto l5010; l5130: if (obj!=knife||knfloc!=loc) goto l5140; knfloc = -1; spk=116; goto l2011; l5140: if (obj!=rod||!here(rod2)) goto l5190; obj=rod2; goto l5010; l5190: if ((verb==find||verb==invent)&&*wd2==0) goto l5010; printf("I see no %s here\n",wd1); goto l2012; } }
/****************************************************************************** * * * Function: daemon_start * * * * Purpose: init process as daemon * * * * Parameters: allow_root - allow root permission for application * * * * Author: Alexei Vladishev * * * * Comments: it doesn't allow running under 'root' if allow_root is zero * * * ******************************************************************************/ int daemon_start(int allow_root) { pid_t pid; struct passwd *pwd; struct sigaction phan; char user[7] = "zabbix"; /* running as root ? */ if (0 == allow_root && (0 == getuid() || 0 == getgid())) { pwd = getpwnam(user); if (NULL == pwd) { zbx_error("user %s does not exist", user); zbx_error("Cannot run as root!"); exit(FAIL); } if (-1 == setgid(pwd->pw_gid)) { zbx_error("cannot setgid to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #ifdef HAVE_FUNCTION_INITGROUPS if (-1 == initgroups(user, pwd->pw_gid)) { zbx_error("cannot initgroups to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #endif if (-1 == setuid(pwd->pw_uid)) { zbx_error("cannot setuid to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #ifdef HAVE_FUNCTION_SETEUID if (-1 == setegid(pwd->pw_gid) || -1 == seteuid(pwd->pw_uid)) { zbx_error("cannot setegid or seteuid to %s: %s", user, zbx_strerror(errno)); exit(FAIL); } #endif } if (0 != (pid = zbx_fork())) exit(0); setsid(); signal(SIGHUP, SIG_IGN); if (0 != (pid = zbx_fork())) exit(0); /* this is to eliminate warning: ignoring return value of chdir */ if (-1 == chdir("/")) assert(0); umask(0002); redirect_std(CONFIG_LOG_FILE); #ifdef HAVE_SYS_RESOURCE_SETPRIORITY if (0 != setpriority(PRIO_PROCESS, 0, 5)) zbx_error("Unable to set process priority to 5. Leaving default."); #endif /*------------------------------------------------*/ if (FAIL == create_pid_file(CONFIG_PID_FILE)) exit(FAIL); parent_pid = (int)getpid(); phan.sa_sigaction = child_signal_handler; sigemptyset(&phan.sa_mask); phan.sa_flags = SA_SIGINFO; sigaction(SIGINT, &phan, NULL); sigaction(SIGQUIT, &phan, NULL); sigaction(SIGTERM, &phan, NULL); sigaction(SIGPIPE, &phan, NULL); sigaction(SIGILL, &phan, NULL); sigaction(SIGFPE, &phan, NULL); sigaction(SIGSEGV, &phan, NULL); sigaction(SIGBUS, &phan, NULL); sigaction(SIGALRM, &phan, NULL); sigaction(SIGUSR1, &phan, NULL); /* Set SIGCHLD now to avoid race conditions when a child process is created before */ /* sigaction() is called. To avoid problems when scripts exit in zbx_execute() and */ /* other cases, SIGCHLD is set to SIG_IGN in zbx_child_fork(). */ phan.sa_sigaction = parent_signal_handler; sigaction(SIGCHLD, &phan, NULL); zbx_setproctitle("main process"); return MAIN_ZABBIX_ENTRY(); }
/* Run an external command returning exit status, and optionally filling * provided buffer with STDOUT output up to the size provided. * * Note: XXX: We are not using the timeout parameter at present. We still need * to implement a reliable timeout mechanism. */ static int _run_extcmd(uid_t uid, gid_t gid, const char *cmd, char *so_buf, const size_t so_buf_sz, const int cflag, const int timeout, const char *substr_search, int *pid_status, const fko_srv_options_t * const opts) { char so_read_buf[IO_READ_BUF_LEN] = {0}; pid_t pid=0; FILE *output; int retval = EXTCMD_SUCCESS_ALL_OUTPUT; int line_ctr = 0, found_str = 0, do_break = 0; char *argv_new[MAX_CMDLINE_ARGS]; /* for validation and/or execvpe() */ int argc_new=0; #if HAVE_EXECVPE int pipe_fd[2]; #endif #if AFL_FUZZING /* Don't allow command execution in AFL fuzzing mode */ return 0; #endif *pid_status = 0; /* Even without execvpe() we examine the command for basic validity * in term of number of args */ memset(argv_new, 0x0, sizeof(argv_new)); if(strtoargv(cmd, argv_new, &argc_new) != 1) { log_msg(LOG_ERR, "run_extcmd(): Error converting cmd str to argv via strtoargv()"); return EXTCMD_ARGV_ERROR; } #if !HAVE_EXECVPE /* if we are not using execvpe() then free up argv_new unconditionally * since was used only for validation */ free_argv(argv_new, &argc_new); #endif #if HAVE_EXECVPE if(opts->verbose > 1) log_msg(LOG_INFO, "run_extcmd() (with execvpe()): running CMD: %s", cmd); if(so_buf != NULL || substr_search != NULL) { if(pipe(pipe_fd) < 0) { log_msg(LOG_ERR, "run_extcmd(): pipe() failed: %s", strerror(errno)); free_argv(argv_new, &argc_new); return EXTCMD_PIPE_ERROR; } } //在子进程中创建CMD。 pid = fork(); if (pid == 0) { if(chdir("/") != 0) exit(EXTCMD_CHDIR_ERROR); if(so_buf != NULL || substr_search != NULL) { close(pipe_fd[0]); dup2(pipe_fd[1], STDOUT_FILENO); if(cflag & WANT_STDERR) dup2(pipe_fd[1], STDERR_FILENO); else close(STDERR_FILENO); } /* Take care of gid/uid settings before running the command. */ if(gid > 0) if(setgid(gid) < 0) exit(EXTCMD_SETGID_ERROR); if(uid > 0) if(setuid(uid) < 0) exit(EXTCMD_SETUID_ERROR); /* don't use env */ execvpe(argv_new[0], argv_new, (char * const *)NULL); } else if(pid == -1) { log_msg(LOG_ERR, "run_extcmd(): fork() failed: %s", strerror(errno)); free_argv(argv_new, &argc_new); return EXTCMD_FORK_ERROR; } /* Only the parent process makes it here */ if(so_buf != NULL || substr_search != NULL) { close(pipe_fd[1]); if ((output = fdopen(pipe_fd[0], "r")) != NULL) { if(so_buf != NULL) memset(so_buf, 0x0, so_buf_sz); while((fgets(so_read_buf, IO_READ_BUF_LEN, output)) != NULL) { line_ctr++; copy_or_search(so_read_buf, so_buf, so_buf_sz, substr_search, cflag, &found_str, &do_break); if(do_break) break; } fclose(output); /* Make sure we only have complete lines */ if(!(cflag & ALLOW_PARTIAL_LINES)) truncate_partial_line(so_buf); } else { log_msg(LOG_ERR, "run_extcmd(): could not fdopen() pipe output file descriptor."); free_argv(argv_new, &argc_new); return EXTCMD_OPEN_ERROR; } } free_argv(argv_new, &argc_new); waitpid(pid, pid_status, 0); #else if(opts->verbose > 1) log_msg(LOG_INFO, "run_extcmd() (without execvpe()): running CMD: %s", cmd); if(so_buf == NULL && substr_search == NULL) { /* Since we do not have to capture output, we will fork here (which we * * would have to do anyway if we are running as another user as well). * */ pid = fork(); if(pid == -1) { log_msg(LOG_ERR, "run_extcmd: fork failed: %s", strerror(errno)); return(EXTCMD_FORK_ERROR); } else if (pid == 0) { /* We are the child */ if(chdir("/") != 0) exit(EXTCMD_CHDIR_ERROR); /* Take care of gid/uid settings before running the command. */ if(gid > 0) if(setgid(gid) < 0) exit(EXTCMD_SETGID_ERROR); if(uid > 0) if(setuid(uid) < 0) exit(EXTCMD_SETUID_ERROR); *pid_status = system(cmd); exit(*pid_status); } /* Retval is forced to 0 as we don't care about the exit status of * the child (for now) */ retval = EXTCMD_SUCCESS_ALL_OUTPUT; } else { /* Looking for output use popen and fill the buffer to its limit. */ output = popen(cmd, "r"); if(output == NULL) { log_msg(LOG_ERR, "Got popen error %i: %s", errno, strerror(errno)); retval = EXTCMD_OPEN_ERROR; } else { if(so_buf != NULL) memset(so_buf, 0x0, so_buf_sz); while((fgets(so_read_buf, IO_READ_BUF_LEN, output)) != NULL) { line_ctr++; copy_or_search(so_read_buf, so_buf, so_buf_sz, substr_search, cflag, &found_str, &do_break); if(do_break) break; } pclose(output); /* Make sure we only have complete lines */ if(!(cflag & ALLOW_PARTIAL_LINES)) truncate_partial_line(so_buf); } } #endif if(substr_search != NULL) { /* The semantics of the return value changes in search mode to the line * number where the substring match was found, or zero if it wasn't found */ if(found_str) retval = line_ctr; else retval = 0; } else { if(WIFEXITED(*pid_status)) { /* Even if the child exited with an error condition, if we make it here * then the child exited normally as far as the OS is concerned (i.e. didn't * crash or get hit with a signal) */ retval = EXTCMD_SUCCESS_ALL_OUTPUT; } else retval = EXTCMD_EXECUTION_ERROR; } if(opts->verbose > 1) log_msg(LOG_INFO, "run_extcmd(): returning %d, pid_status: %d", retval, WIFEXITED(*pid_status) ? WEXITSTATUS(*pid_status) : *pid_status); return(retval); }
int main(int argc, char **argv) { const struct optstruct *opt; #ifndef C_WINDOWS struct passwd *user = NULL; #endif time_t currtime; const char *dbdir, *cfgfile; char *pua_cats = NULL, *pt; int ret, tcpsock = 0, localsock = 0, i, min_port, max_port; unsigned int sigs = 0; int lsockets[2], nlsockets = 0; unsigned int dboptions = 0; #ifdef C_LINUX struct stat sb; #endif #ifdef C_WINDOWS if(!pthread_win32_process_attach_np()) { mprintf("!Can't start the win32 pthreads layer\n"); return 1; } #endif if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) { mprintf("!Can't parse command line options\n"); return 1; } if(optget(opts, "help")->enabled) { help(); optfree(opts); return 0; } if(optget(opts, "debug")->enabled) { #if defined(C_LINUX) /* [email protected]: create a dump if needed */ struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; if(setrlimit(RLIMIT_CORE, &rlim) < 0) perror("setrlimit"); #endif debug_mode = 1; } /* parse the config file */ cfgfile = optget(opts, "config-file")->strarg; pt = strdup(cfgfile); if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) { fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt); free(pt); return 1; } free(pt); if(optget(opts, "version")->enabled) { print_version(optget(opts, "DatabaseDirectory")->strarg); optfree(opts); return 0; } umask(0); /* drop privileges */ #if (!defined(C_OS2)) && (!defined(C_WINDOWS)) if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { if((user = getpwnam(opt->strarg)) == NULL) { fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg); optfree(opts); return 1; } if(optget(opts, "AllowSupplementaryGroups")->enabled) { #ifdef HAVE_INITGROUPS if(initgroups(opt->strarg, user->pw_gid)) { fprintf(stderr, "ERROR: initgroups() failed.\n"); optfree(opts); return 1; } #else mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups in %s\n", cfgfile); optfree(opts); return 1; #endif } else { #ifdef HAVE_SETGROUPS if(setgroups(1, &user->pw_gid)) { fprintf(stderr, "ERROR: setgroups() failed.\n"); optfree(opts); return 1; } #endif } if(setgid(user->pw_gid)) { fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid); optfree(opts); return 1; } if(setuid(user->pw_uid)) { fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid); optfree(opts); return 1; } } #endif /* initialize logger */ logg_lock = !optget(opts, "LogFileUnlock")->enabled; logg_time = optget(opts, "LogTime")->enabled; logok = optget(opts, "LogClean")->enabled; logg_size = optget(opts, "LogFileMaxSize")->numarg; logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled; mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg; do { /* logger initialized */ if((opt = optget(opts, "LogFile"))->enabled) { char timestr[32]; logg_file = opt->strarg; if(strlen(logg_file) < 2 || (logg_file[0] != '/' && logg_file[0] != '\\' && logg_file[1] != ':')) { fprintf(stderr, "ERROR: LogFile requires full path.\n"); ret = 1; break; } time(&currtime); if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) { fprintf(stderr, "ERROR: Can't initialize the internal logger\n"); ret = 1; break; } } else logg_file = NULL; if((ret = cl_init(CL_INIT_DEFAULT))) { logg("!Can't initialize libclamav: %s\n", cl_strerror(ret)); ret = 1; break; } if(optget(opts, "Debug")->enabled) /* enable debug messages in libclamav */ { cl_debug(); logg_verbose = 2; } #if defined(USE_SYSLOG) && !defined(C_AIX) if(optget(opts, "LogSyslog")->enabled) { int fac = LOG_LOCAL6; opt = optget(opts, "LogFacility"); if((fac = logg_facility(opt->strarg)) == -1) { logg("!LogFacility: %s: No such facility.\n", opt->strarg); ret = 1; break; } openlog("clamd", LOG_PID, fac); logg_syslog = 1; } #endif #ifdef C_LINUX procdev = 0; if(stat("/proc", &sb) != -1 && !sb.st_size) procdev = sb.st_dev; #endif /* check socket type */ if(optget(opts, "TCPSocket")->enabled) tcpsock = 1; if(optget(opts, "LocalSocket")->enabled) localsock = 1; if(!tcpsock && !localsock) { logg("!Please define server type (local and/or TCP).\n"); ret = 1; break; } logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version()); #ifndef C_WINDOWS if(user) logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid); #endif if(logg_size) logg("#Log file size limited to %d bytes.\n", logg_size); else logg("#Log file size limit disabled.\n"); min_port = optget(opts, "StreamMinPort")->numarg; max_port = optget(opts, "StreamMaxPort")->numarg; if (min_port < 1024 || min_port > max_port || max_port > 65535) { logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port); ret = 1; break; } if(!(engine = cl_engine_new())) { logg("!Can't initialize antivirus engine\n"); ret = 1; break; } /* load the database(s) */ dbdir = optget(opts, "DatabaseDirectory")->strarg; logg("#Reading databases from %s\n", dbdir); if(optget(opts, "DetectPUA")->enabled) { dboptions |= CL_DB_PUA; if((opt = optget(opts, "ExcludePUA"))->enabled) { dboptions |= CL_DB_PUA_EXCLUDE; i = 0; logg("#Excluded PUA categories:"); while(opt) { if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { logg("!Can't allocate memory for pua_cats\n"); cl_engine_free(engine); ret = 1; break; } logg("# %s", opt->strarg); sprintf(pua_cats + i, ".%s", opt->strarg); i += strlen(opt->strarg) + 1; pua_cats[i] = 0; opt = opt->nextarg; } if (ret) break; logg("#\n"); pua_cats[i] = '.'; pua_cats[i + 1] = 0; } if((opt = optget(opts, "IncludePUA"))->enabled) { if(pua_cats) { logg("!ExcludePUA and IncludePUA cannot be used at the same time\n"); free(pua_cats); ret = 1; break; } dboptions |= CL_DB_PUA_INCLUDE; i = 0; logg("#Included PUA categories:"); while(opt) { if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { logg("!Can't allocate memory for pua_cats\n"); ret = 1; break; } logg("# %s", opt->strarg); sprintf(pua_cats + i, ".%s", opt->strarg); i += strlen(opt->strarg) + 1; pua_cats[i] = 0; opt = opt->nextarg; } if (ret) break; logg("#\n"); pua_cats[i] = '.'; pua_cats[i + 1] = 0; } if(pua_cats) { if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) { logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret)); free(pua_cats); ret = 1; break; } free(pua_cats); } } else { logg("#Not loading PUA signatures.\n"); } /* set the temporary dir */ if((opt = optget(opts, "TemporaryDirectory"))->enabled) { if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) { logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret)); ret = 1; break; } } if(optget(opts, "LeaveTemporaryFiles")->enabled) cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1); if(optget(opts, "PhishingSignatures")->enabled) dboptions |= CL_DB_PHISHING; else logg("#Not loading phishing signatures.\n"); if(optget(opts,"PhishingScanURLs")->enabled) dboptions |= CL_DB_PHISHING_URLS; else logg("#Disabling URL based phishing detection.\n"); if(optget(opts,"DevACOnly")->enabled) { logg("#Only using the A-C matcher.\n"); cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1); } if((opt = optget(opts, "DevACDepth"))->enabled) { cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg); logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg); } if((ret = cl_load(dbdir, engine, &sigs, dboptions))) { logg("!%s\n", cl_strerror(ret)); ret = 1; break; } logg("#Loaded %u signatures.\n", sigs); if((ret = cl_engine_compile(engine)) != 0) { logg("!Database initialization error: %s\n", cl_strerror(ret)); ret = 1; break; } if(tcpsock) { #ifdef C_WINDOWS WSADATA wsaData; if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { logg("!Error at WSAStartup(): %d\n", WSAGetLastError()); ret = 1; break; } #endif if ((lsockets[nlsockets] = tcpserver(opts)) == -1) { ret = 1; break; } nlsockets++; } if(localsock) { if ((lsockets[nlsockets] = localserver(opts)) == -1) { ret = 1; break; } nlsockets++; } /* fork into background */ if(!optget(opts, "Foreground")->enabled) { #ifdef C_BSD /* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */ for(ret=0;ret<nlsockets;ret++) { fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK); } #endif if(daemonize() == -1) { logg("!daemonize() failed\n"); ret = 1; break; } #ifdef C_BSD for(ret=0;ret<nlsockets;ret++) { fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK); } #endif if(!debug_mode) if(chdir("/") == -1) logg("^Can't change current working directory to root\n"); } else foreground = 1; ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts); } while (0); logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : ""); for (i = 0; i < nlsockets; i++) { closesocket(lsockets[i]); } #ifndef C_OS2 if(nlsockets && localsock) { opt = optget(opts, "LocalSocket"); if(unlink(opt->strarg) == -1) logg("!Can't unlink the socket file %s\n", opt->strarg); else logg("Socket file removed.\n"); } #endif #ifdef C_WINDOWS if(tcpsock) WSACleanup(); if(!pthread_win32_process_detach_np()) { logg("!Can't stop the win32 pthreads layer\n"); logg_close(); optfree(opts); return 1; } #endif logg_close(); optfree(opts); return ret; }
static gboolean start_child(pcmk_child_t * child) { int lpc = 0; uid_t uid = 0; gid_t gid = 0; struct rlimit oflimits; gboolean use_valgrind = FALSE; gboolean use_callgrind = FALSE; const char *devnull = "/dev/null"; const char *env_valgrind = getenv("PCMK_valgrind_enabled"); const char *env_callgrind = getenv("PCMK_callgrind_enabled"); enum cluster_type_e stack = get_cluster_type(); child->active_before_startup = FALSE; if (child->command == NULL) { crm_info("Nothing to do for child \"%s\"", child->name); return TRUE; } if (env_callgrind != NULL && crm_is_true(env_callgrind)) { use_callgrind = TRUE; use_valgrind = TRUE; } else if (env_callgrind != NULL && strstr(env_callgrind, child->name)) { use_callgrind = TRUE; use_valgrind = TRUE; } else if (env_valgrind != NULL && crm_is_true(env_valgrind)) { use_valgrind = TRUE; } else if (env_valgrind != NULL && strstr(env_valgrind, child->name)) { use_valgrind = TRUE; } if (use_valgrind && strlen(VALGRIND_BIN) == 0) { crm_warn("Cannot enable valgrind for %s:" " The location of the valgrind binary is unknown", child->name); use_valgrind = FALSE; } if (child->uid) { if (crm_user_lookup(child->uid, &uid, &gid) < 0) { crm_err("Invalid user (%s) for %s: not found", child->uid, child->name); return FALSE; } crm_info("Using uid=%u and group=%u for process %s", uid, gid, child->name); } child->pid = fork(); CRM_ASSERT(child->pid != -1); if (child->pid > 0) { /* parent */ mainloop_child_add(child->pid, 0, child->name, child, pcmk_child_exit); crm_info("Forked child %d for process %s%s", child->pid, child->name, use_valgrind ? " (valgrind enabled: " VALGRIND_BIN ")" : ""); update_node_processes(local_nodeid, NULL, get_process_list()); return TRUE; } else { /* Start a new session */ (void)setsid(); /* Setup the two alternate arg arrarys */ opts_vgrind[0] = strdup(VALGRIND_BIN); if (use_callgrind) { opts_vgrind[1] = strdup("--tool=callgrind"); opts_vgrind[2] = strdup("--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p"); opts_vgrind[3] = strdup(child->command); opts_vgrind[4] = NULL; } else { opts_vgrind[1] = strdup(child->command); opts_vgrind[2] = NULL; opts_vgrind[3] = NULL; opts_vgrind[4] = NULL; } opts_default[0] = strdup(child->command);; if(gid) { if(stack == pcmk_cluster_corosync) { /* Drop root privileges completely * * We can do this because we set uidgid.gid.${gid}=1 * via CMAP which allows these processes to connect to * corosync */ if (setgid(gid) < 0) { crm_perror(LOG_ERR, "Could not set group to %d", gid); } /* Keep the root group (so we can access corosync), but add the haclient group (so we can access ipc) */ } else if (initgroups(child->uid, gid) < 0) { crm_err("Cannot initalize groups for %s: %s (%d)", child->uid, pcmk_strerror(errno), errno); } } if (uid && setuid(uid) < 0) { crm_perror(LOG_ERR, "Could not set user to %d (%s)", uid, child->uid); } /* Close all open file descriptors */ getrlimit(RLIMIT_NOFILE, &oflimits); for (lpc = 0; lpc < oflimits.rlim_cur; lpc++) { close(lpc); } (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */ (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */ (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */ if (use_valgrind) { (void)execvp(VALGRIND_BIN, opts_vgrind); } else { (void)execvp(child->command, opts_default); } crm_perror(LOG_ERR, "FATAL: Cannot exec %s", child->command); crm_exit(DAEMON_RESPAWN_STOP); } return TRUE; /* never reached */ }
int dexopt(const char *apk_path, uid_t uid, int is_public) { struct utimbuf ut; struct stat apk_stat, dex_stat; char dex_path[PKG_PATH_MAX]; char dexopt_flags[PROPERTY_VALUE_MAX]; char *end; int res, zip_fd=-1, odex_fd=-1; /* Before anything else: is there a .odex file? If so, we have * pre-optimized the apk and there is nothing to do here. */ if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) { return -1; } /* platform-specific flags affecting optimization and verification */ property_get("dalvik.vm.dexopt-flags", dexopt_flags, ""); strcpy(dex_path, apk_path); end = strrchr(dex_path, '.'); if (end != NULL) { strcpy(end, ".odex"); if (stat(dex_path, &dex_stat) == 0) { return 0; } } if (create_cache_path(dex_path, apk_path)) { return -1; } memset(&apk_stat, 0, sizeof(apk_stat)); stat(apk_path, &apk_stat); zip_fd = open(apk_path, O_RDONLY, 0); if (zip_fd < 0) { LOGE("dexopt cannot open '%s' for input\n", apk_path); return -1; } unlink(dex_path); odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644); if (odex_fd < 0) { LOGE("dexopt cannot open '%s' for output\n", dex_path); goto fail; } if (fchown(odex_fd, AID_SYSTEM, uid) < 0) { LOGE("dexopt cannot chown '%s'\n", dex_path); goto fail; } if (fchmod(odex_fd, S_IRUSR|S_IWUSR|S_IRGRP | (is_public ? S_IROTH : 0)) < 0) { LOGE("dexopt cannot chmod '%s'\n", dex_path); goto fail; } LOGD("DexInv: --- BEGIN '%s' ---\n", apk_path); pid_t pid; pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ if (setgid(uid) != 0) { LOGE("setgid(%d) failed during dexopt\n", uid); exit(64); } if (setuid(uid) != 0) { LOGE("setuid(%d) during dexopt\n", uid); exit(65); } if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) { LOGE("flock(%s) failed: %s\n", dex_path, strerror(errno)); exit(66); } run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags); exit(67); /* only get here on exec failure */ } else { res = wait_dexopt(pid, apk_path); if (res != 0) { LOGE("dexopt failed on '%s' res = %d\n", dex_path, res); goto fail; } } ut.actime = apk_stat.st_atime; ut.modtime = apk_stat.st_mtime; utime(dex_path, &ut); close(odex_fd); close(zip_fd); return 0; fail: if (odex_fd >= 0) { close(odex_fd); unlink(dex_path); } if (zip_fd >= 0) { close(zip_fd); } return -1; }
static void run_file(const char *filename, uid_t uid, gid_t gid) { /* Run a file by spawning off a process which redirects I/O, * spawns a subshell, then waits for it to complete and sends * mail to the user. */ pid_t pid; int fd_out, fd_in; int queue; char mailbuf[MAXLOGNAME], fmt[64]; char *mailname = NULL; FILE *stream; int send_mail = 0; struct stat buf, lbuf; off_t size; struct passwd *pentry; int fflags; long nuid; long ngid; #ifdef PAM pam_handle_t *pamh = NULL; int pam_err; struct pam_conv pamc = { .conv = openpam_nullconv, .appdata_ptr = NULL }; #endif PRIV_START if (chmod(filename, S_IRUSR) != 0) { perr("cannot change file permissions"); } PRIV_END pid = fork(); if (pid == -1) perr("cannot fork"); else if (pid != 0) return; /* Let's see who we mail to. Hopefully, we can read it from * the command file; if not, send it to the owner, or, failing that, * to root. */ pentry = getpwuid(uid); if (pentry == NULL) perrx("Userid %lu not found - aborting job %s", (unsigned long) uid, filename); #ifdef PAM PRIV_START pam_err = pam_start(atrun, pentry->pw_name, &pamc, &pamh); if (pam_err != PAM_SUCCESS) perrx("cannot start PAM: %s", pam_strerror(pamh, pam_err)); pam_err = pam_acct_mgmt(pamh, PAM_SILENT); /* Expired password shouldn't prevent the job from running. */ if (pam_err != PAM_SUCCESS && pam_err != PAM_NEW_AUTHTOK_REQD) perrx("Account %s (userid %lu) unavailable for job %s: %s", pentry->pw_name, (unsigned long)uid, filename, pam_strerror(pamh, pam_err)); pam_end(pamh, pam_err); PRIV_END #endif /* PAM */ PRIV_START stream=fopen(filename, "r"); PRIV_END if (stream == NULL) perr("cannot open input file"); if ((fd_in = dup(fileno(stream))) <0) perr("error duplicating input file descriptor"); if (fstat(fd_in, &buf) == -1) perr("error in fstat of input file descriptor"); if (lstat(filename, &lbuf) == -1) perr("error in fstat of input file"); if (S_ISLNK(lbuf.st_mode)) perrx("Symbolic link encountered in job %s - aborting", filename); if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || (lbuf.st_size!=buf.st_size)) perrx("Somebody changed files from under us for job %s - aborting", filename); if (buf.st_nlink > 1) perrx("Somebody is trying to run a linked script for job %s", filename); if ((fflags = fcntl(fd_in, F_GETFD)) <0) perr("error in fcntl"); fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); snprintf(fmt, sizeof(fmt), "#!/bin/sh\n# atrun uid=%%ld gid=%%ld\n# mail %%%ds %%d", MAXLOGNAME - 1); if (fscanf(stream, fmt, &nuid, &ngid, mailbuf, &send_mail) != 4) perrx("File %s is in wrong format - aborting", filename); if (mailbuf[0] == '-') perrx("Illegal mail name %s in %s", mailbuf, filename); mailname = mailbuf; if (nuid != uid) perrx("Job %s - userid %ld does not match file uid %lu", filename, nuid, (unsigned long)uid); if (ngid != gid) perrx("Job %s - groupid %ld does not match file gid %lu", filename, ngid, (unsigned long)gid); fclose(stream); if (chdir(ATSPOOL_DIR) < 0) perr("cannot chdir to %s", ATSPOOL_DIR); /* Create a file to hold the output of the job we are about to run. * Write the mail header. */ if((fd_out=open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) perr("cannot create output file"); write_string(fd_out, "Subject: Output from your job "); write_string(fd_out, filename); write_string(fd_out, "\n\n"); fstat(fd_out, &buf); size = buf.st_size; close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); pid = fork(); if (pid < 0) perr("error in fork"); else if (pid == 0) { char *nul = NULL; char **nenvp = &nul; /* Set up things for the child; we want standard input from the input file, * and standard output and error sent to our output file. */ if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) perr("error in lseek"); if (dup(fd_in) != STDIN_FILENO) perr("error in I/O redirection"); if (dup(fd_out) != STDOUT_FILENO) perr("error in I/O redirection"); if (dup(fd_out) != STDERR_FILENO) perr("error in I/O redirection"); close(fd_in); close(fd_out); if (chdir(ATJOB_DIR) < 0) perr("cannot chdir to %s", ATJOB_DIR); queue = *filename; PRIV_START nice(tolower(queue) - 'a'); #ifdef LOGIN_CAP /* * For simplicity and safety, set all aspects of the user context * except for a selected subset: Don't set priority, which was * set based on the queue file name according to the tradition. * Don't bother to set environment, including path vars, either * because it will be discarded anyway. Although the job file * should set umask, preset it here just in case. */ if (setusercontext(NULL, pentry, uid, LOGIN_SETALL & ~(LOGIN_SETPRIORITY | LOGIN_SETPATH | LOGIN_SETENV)) != 0) exit(EXIT_FAILURE); /* setusercontext() logged the error */ #else /* LOGIN_CAP */ if (initgroups(pentry->pw_name,pentry->pw_gid)) perr("cannot init group access list"); if (setgid(gid) < 0 || setegid(pentry->pw_gid) < 0) perr("cannot change group"); if (setlogin(pentry->pw_name)) perr("cannot set login name"); if (setuid(uid) < 0 || seteuid(uid) < 0) perr("cannot set user id"); #endif /* LOGIN_CAP */ if (chdir(pentry->pw_dir)) chdir("/"); if(execle("/bin/sh","sh",(char *) NULL, nenvp) != 0) perr("exec failed for /bin/sh"); PRIV_END }
static ngx_int_t ngx_open_pipe(ngx_cycle_t *cycle, ngx_open_pipe_t *op) { int fd; u_char **argv; ngx_pid_t pid; sigset_t set; ngx_core_conf_t *ccf; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (pipe(op->pfd) < 0) { return NGX_ERROR; } argv = op->argv->elts; if ((pid = fork()) < 0) { goto err; } else if (pid > 0) { op->pid = pid; if (op->open_fd->fd != NGX_INVALID_FILE) { if (close(op->open_fd->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "close \"%s\" failed", op->open_fd->name.data); } } if (op->type == NGX_PIPE_WRITE) { op->open_fd->fd = op->pfd[1]; close(op->pfd[0]); } else { op->open_fd->fd = op->pfd[0]; close(op->pfd[1]); } } else { if (op->type == 1) { close(op->pfd[1]); if (op->pfd[0] != STDIN_FILENO) { dup2(op->pfd[0], STDIN_FILENO); close(op->pfd[0]); } } else { close(op->pfd[0]); if (op->pfd[1] != STDOUT_FILENO) { dup2(op->pfd[1], STDOUT_FILENO); close(op->pfd[1]); } } if (geteuid() == 0) { if (setgid(ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setgid(%d) failed", ccf->group); exit(2); } if (initgroups(ccf->username, ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "initgroups(%s, %d) failed", ccf->username, ccf->group); } if (setuid(ccf->user) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setuid(%d) failed", ccf->user); exit(2); } } /* * redirect stderr to /dev/null, because stderr will be connected with * fd used by the last pipe when error log is configured using pipe, * that will cause it no close */ fd = open("/dev/null", O_WRONLY); if (fd == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "open(\"/dev/null\") failed"); exit(2); } if (dup2(fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "dup2(STDERR) failed"); exit(2); } if (fd > STDERR_FILENO && close(fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "close() failed"); exit(2); } sigemptyset(&set); if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "sigprocmask() failed"); exit(2); } execv((const char *) argv[0], (char *const *) op->argv->elts); exit(0); } return NGX_OK; err: close(op->pfd[0]); close(op->pfd[1]); return NGX_ERROR; }
void swWorker_onStart(swServer *serv) { /** * Release other worker process */ swWorker *worker; if (SwooleWG.id >= serv->worker_num) { SwooleG.process_type = SW_PROCESS_TASKWORKER; } else { SwooleG.process_type = SW_PROCESS_WORKER; } int is_root = !geteuid(); struct passwd *passwd = NULL; struct group *group = NULL; if (is_root) { //get group info if (SwooleG.group) { group = getgrnam(SwooleG.group); if (!group) { swSysError("get group [%s] info failed.", SwooleG.group); } } //get user info if (SwooleG.user) { passwd = getpwnam(SwooleG.user); if (!passwd) { swSysError("get user [%s] info failed.", SwooleG.user); } } //chroot if (SwooleG.chroot) { if (0 > chroot(SwooleG.chroot)) { swSysError("chroot to [%s] failed.", SwooleG.chroot); } } //set process group if (SwooleG.group && group) { if (setgid(group->gr_gid) < 0) { swSysError("setgid to [%s] failed.", SwooleG.group); } } //set process user if (SwooleG.user && passwd) { if (setuid(passwd->pw_uid) < 0) { swSysError("setuid to [%s] failed.", SwooleG.user); } } } SwooleWG.worker = swServer_get_worker(serv, SwooleWG.id); int i; for (i = 0; i < serv->worker_num + SwooleG.task_worker_num; i++) { worker = swServer_get_worker(serv, i); if (SwooleWG.id == i) { continue; } else { swWorker_free(worker); } if (swIsWorker()) { swSetNonBlock(worker->pipe_master); } } if (serv->onWorkerStart) { serv->onWorkerStart(serv, SwooleWG.id); } }
bool f_posix_setgid(int gid) { return setgid(gid); }
static void drop_privileges(struct credentials *cred) { if (cred && (initgroups(cred->pass->pw_name, cred->gid) || setgid (cred->gid) || setuid(cred->pass->pw_uid))) die("cannot drop privileges"); }
/* * Do chroot, if requested. * * Switch UID and GID to what is specified in the config file */ static int switch_users(CONF_SECTION *cs) { /* * Get the current maximum for core files. Do this * before anything else so as to ensure it's properly * initialized. */ if (fr_set_dumpable_init() < 0) { fr_perror("radiusd"); return 0; } /* * Don't do chroot/setuid/setgid if we're in debugging * as non-root. */ if (debug_flag && (getuid() != 0)) return 1; if (cf_section_parse(cs, NULL, bootstrap_config) < 0) { fprintf(stderr, "radiusd: Error: Failed to parse user/group information.\n"); return 0; } #ifdef HAVE_GRP_H /* Set GID. */ if (gid_name) { struct group *gr; gr = getgrnam(gid_name); if (gr == NULL) { fprintf(stderr, "%s: Cannot get ID for group %s: %s\n", progname, gid_name, fr_syserror(errno)); return 0; } server_gid = gr->gr_gid; } else { server_gid = getgid(); } #endif #ifdef HAVE_PWD_H /* Set UID. */ if (uid_name) { struct passwd *pw; pw = getpwnam(uid_name); if (pw == NULL) { fprintf(stderr, "%s: Cannot get passwd entry for user %s: %s\n", progname, uid_name, fr_syserror(errno)); return 0; } if (getuid() == pw->pw_uid) { uid_name = NULL; } else { server_uid = pw->pw_uid; #ifdef HAVE_INITGROUPS if (initgroups(uid_name, server_gid) < 0) { fprintf(stderr, "%s: Cannot initialize supplementary group list for user %s: %s\n", progname, uid_name, fr_syserror(errno)); return 0; } #endif } } else { server_uid = getuid(); } #endif if (chroot_dir) { if (chroot(chroot_dir) < 0) { fprintf(stderr, "%s: Failed to perform chroot %s: %s", progname, chroot_dir, fr_syserror(errno)); return 0; } /* * Note that we leave chdir alone. It may be * OUTSIDE of the root. This allows us to read * the configuration from "-d ./etc/raddb", with * the chroot as "./chroot/" for example. After * the server has been loaded, it does a "cd * ${logdir}" below, so that core files (if any) * go to a logging directory. * * This also allows the configuration of the * server to be outside of the chroot. If the * server is statically linked, then the only * things needed inside of the chroot are the * logging directories. */ } #ifdef HAVE_GRP_H /* Set GID. */ if (gid_name && (setgid(server_gid) < 0)) { fprintf(stderr, "%s: Failed setting group to %s: %s", progname, gid_name, fr_syserror(errno)); return 0; } #endif #ifdef HAVE_SETUID /* * Just before losing root permissions, ensure that the * log files have the correct owner && group. * * We have to do this because the log file MAY have been * specified on the command-line. */ if (uid_name || gid_name) { if ((default_log.dst == L_DST_FILES) && (default_log.fd < 0)) { default_log.fd = open(main_config.log_file, O_WRONLY | O_APPEND | O_CREAT, 0640); if (default_log.fd < 0) { fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno)); return 0; } if (chown(main_config.log_file, server_uid, server_gid) < 0) { fprintf(stderr, "%s: Cannot change ownership of log file %s: %s\n", progname, main_config.log_file, fr_syserror(errno)); return 0; } } } if (uid_name) { doing_setuid = true; fr_suid_down(); } #endif /* * This also clears the dumpable flag if core dumps * aren't allowed. */ if (fr_set_dumpable(allow_core_dumps) < 0) { ERROR("%s", fr_strerror()); } if (allow_core_dumps) { INFO("Core dumps are enabled"); } return 1; }
int main(int argc, char **argv) { static int verbose = 0, debug = 0, validate = 0; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"config", required_argument, NULL, 'c'}, {"validate", no_argument, NULL, 'C'}, {"debug", no_argument, NULL, 'd'}, {"version", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'V'}, {"get-socketpath", no_argument, NULL, 'p'}, {0, 0, 0, 0} }; char *config_path = NULL; const char* usage = "Usage: sway [options] [command]\n" "\n" " -h, --help Show help message and quit.\n" " -c, --config <config> Specify a config file.\n" " -C, --validate Check the validity of the config file, then exit.\n" " -d, --debug Enables full logging, including debug information.\n" " -v, --version Show the version number and quit.\n" " -V, --verbose Enables more verbose logging.\n" " --get-socketpath Gets the IPC socket path and prints it, then exits.\n" "\n"; int c; while (1) { int option_index = 0; c = getopt_long(argc, argv, "hCdvVpc:", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'h': // help fprintf(stdout, "%s", usage); exit(EXIT_SUCCESS); break; case 'c': // config config_path = strdup(optarg); break; case 'C': // validate validate = 1; break; case 'd': // debug debug = 1; break; case 'v': // version #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE fprintf(stdout, "sway version %s (%s, branch \"%s\")\n", SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); #else fprintf(stdout, "version not detected\n"); #endif exit(EXIT_SUCCESS); break; case 'V': // verbose verbose = 1; break; case 'p': ; // --get-socketpath if (getenv("SWAYSOCK")) { fprintf(stdout, "%s\n", getenv("SWAYSOCK")); exit(EXIT_SUCCESS); } else { fprintf(stderr, "sway socket not detected.\n"); exit(EXIT_FAILURE); } break; default: fprintf(stderr, "%s", usage); exit(EXIT_FAILURE); } } if (optind < argc) { // Behave as IPC client if (getuid() != geteuid() || getgid() != getegid()) { if (setgid(getgid()) != 0 || setuid(getuid()) != 0) { sway_abort("Unable to drop root"); } } char *socket_path = getenv("SWAYSOCK"); if (!socket_path) { sway_abort("Unable to retrieve socket path"); } char *command = join_args(argv + optind, argc - optind); run_as_ipc_client(command, socket_path); return 0; } // we need to setup logging before wlc_init in case it fails. if (debug) { init_log(L_DEBUG); } else if (verbose || validate) { init_log(L_INFO); } else { init_log(L_ERROR); } setenv("WLC_DIM", "0", 0); wlc_log_set_handler(wlc_log_handler); detect_proprietary(); /* Changing code earlier than this point requires detailed review */ /* (That code runs as root on systems without logind, and wlc_init drops to * another user.) */ if (!wlc_init(&interface, argc, argv)) { return 1; } register_extensions(); // handle SIGTERM signals signal(SIGTERM, sig_handler); #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE sway_log(L_INFO, "Starting sway version %s (%s, branch \"%s\")\n", SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); #endif init_layout(); if (validate) { bool valid = load_config(config_path); return valid ? 0 : 1; } if (!load_config(config_path)) { sway_log(L_ERROR, "Error(s) loading config!"); } if (config_path) { free(config_path); } ipc_init(); if (!terminate_request) { wlc_run(); } ipc_terminate(); return 0; }
static int __sandbox_task_execute(task_t * ptask) { FUNC_BEGIN("sandbox_task_execute(%p)", ptask); assert(ptask); /* Run the prisoner program in a separate process group */ if (setsid() < 0) { WARNING("failed setting session id"); return EXIT_FAILURE; } /* Close fd's not used by the prisoner program */ int fd; for (fd = 0; fd < FILENO_MAX; fd++) { if ((fd == ptask->ifd) || (fd == ptask->ofd) || (fd == ptask->efd)) { continue; } close(fd); } /* Redirect I/O channel */ if (dup2(ptask->efd, STDERR_FILENO) < 0) { WARNING("failed redirecting error channel"); return EXIT_FAILURE; } DBG("dup2: %d->%d", ptask->efd, STDERR_FILENO); if (dup2(ptask->ofd, STDOUT_FILENO) < 0) { WARNING("failed redirecting output channel(s)"); return EXIT_FAILURE; } DBG("dup2: %d->%d", ptask->ofd, STDOUT_FILENO); if (dup2(ptask->ifd, STDIN_FILENO) < 0) { WARNING("failed redirecting input channel(s)"); return EXIT_FAILURE; } DBG("dup2: %d->%d", ptask->ifd, STDIN_FILENO); /* Apply security restrictions */ if (strcmp(ptask->jail, "/") != 0) { if (chdir(ptask->jail) < 0) { WARNING("failed switching to jail directory"); return EXIT_FAILURE; } if (chroot(ptask->jail) < 0) { WARNING("failed chroot to jail directory"); return EXIT_FAILURE; } DBG("jail: \"%s\"", ptask->jail); } /* Change identity before executing the targeted program */ if (setgid(ptask->gid) < 0) { WARNING("changing group identity"); return EXIT_FAILURE; } DBG("setgid: %lu", (unsigned long)ptask->gid); if (setuid(ptask->uid) < 0) { WARNING("changing owner identity"); return EXIT_FAILURE; } DBG("setuid: %lu", (unsigned long)ptask->uid); /* Prepare argument arrray to be passed to execve() */ char * argv [ARG_MAX] = {NULL}; int argc = 0; while ((argc + 1 < ARG_MAX) && (ptask->comm.args[argc] >= 0)) { argv[argc] = ptask->comm.buff + ptask->comm.args[argc]; argc++; } if (strcmp(ptask->jail, "/") != 0) { argv[0] += strlen(ptask->jail); } argv[argc] = NULL; #ifndef NDEBUG argc = 0; while (argv[argc] != NULL) { DBG("argv[%d]: \"%s\"", argc, argv[argc]); argc++; } #endif /* !defined NDEBUG */ /* Most kinds of resource restrictions are applied through the *setrlimit* * system call, with the exceptions of virtual memory limit and the cpu * usage limit. * Because we might have already changed identity by this time, the hard * limits should remain as they were. Thus we must invoke a *getrlimit* * ahead of time to load original hard limit value. * Also note that, cpu usage limit should be set LAST to reduce overhead. */ struct rlimit rlimval; /* Do NOT produce core dump files at all. */ if (getrlimit(RLIMIT_CORE, &rlimval) < 0) { return EXIT_FAILURE; } rlimval.rlim_cur = 0; if (setrlimit(RLIMIT_CORE, &rlimval) < 0) { return EXIT_FAILURE; } DBG("RLIMIT_CORE: %ld", rlimval.rlim_cur); /* Disk quota */ if (getrlimit(RLIMIT_FSIZE, &rlimval) < 0) { return EXIT_FAILURE; } rlimval.rlim_cur = ptask->quota[S_QUOTA_DISK]; if (setrlimit(RLIMIT_FSIZE, &rlimval) < 0) { return EXIT_FAILURE; } DBG("RLIMIT_FSIZE: %ld", rlimval.rlim_cur); #ifdef DELETED /* Memory quota */ if (getrlimit(RLIMIT_AS, &rlimval) < 0) { return EXIT_FAILURE; } rlimval.rlim_cur = ptask->quota[S_QUOTA_MEMORY]; if (setrlimit(RLIMIT_AS, &rlimval) < 0) { return EXIT_FAILURE; } DBG("RLIMIT_AS: %ld", rlimval.rlim_cur); #endif /* DELETED */ /* Time resource limits, these should be set last to reduce overhead. Thus, * no debug information is produced on success. */ struct itimerval timerval; /* Wallclock quota */ timerval.it_interval.tv_sec = 0; timerval.it_interval.tv_usec = 0; timerval.it_value.tv_sec = ptask->quota[S_QUOTA_WALLCLOCK] / 1000; timerval.it_value.tv_usec = (ptask->quota[S_QUOTA_WALLCLOCK] % 1000) * 1000; if (setitimer(ITIMER_REAL, &timerval, NULL) < 0) { WARNING("setting ITIMER_REAL"); return EXIT_FAILURE; } /* CPU quota */ timerval.it_interval.tv_sec = 0; timerval.it_interval.tv_usec = 0; timerval.it_value.tv_sec = ptask->quota[S_QUOTA_CPU] / 1000; timerval.it_value.tv_usec = (ptask->quota[S_QUOTA_CPU] % 1000) * 1000; if (setitimer(ITIMER_PROF, &timerval, NULL) < 0) { WARNING("setting ITIMER_PROF"); return EXIT_FAILURE; } /* Enter tracing mode */ if (!trace_self()) { WARNING("trace_self"); return EXIT_FAILURE; } /* Execute the targeted program */ if (execve(argv[0], argv, NULL) < 0) { WARNING("execve failed unexpectedly"); return EXIT_FAILURE; } /* According to Linux manual, the execve() function will NEVER return on * success, thus we should not be able to reach to this line of code! */ return EXIT_FAILURE; }
/* * setup() - performs all ONE TIME setup for this test. */ void setup() { char *cwdname = NULL; int fd; umask(0); /* capture signals */ tst_sig(NOFORK, DEF_HANDLER, cleanup); /* Pause if that option was specified */ TEST_PAUSE; ltpuser = getpwnam(nobody_uid); if (setgid(ltpuser->pw_uid) == -1) { tst_resm(TINFO, "setgid failed to " "to set the gid to %d", ltpuser->pw_uid); perror("setgid"); } if (setuid(ltpuser->pw_uid) == -1) { tst_resm(TINFO, "setuid failed to " "to set the uid to %d", ltpuser->pw_uid); perror("setuid"); } /* make a temporary directory and cd to it */ tst_tmpdir(); /* * set up a name that should generate an ENOTDIR error */ if ((cwdname = getcwd(cwdname, 0)) == NULL) { tst_brkm(TBROK, cleanup, "could not get currect directory"); } sprintf(test_name5, "%s/fake.%d", cwdname, getpid()); if ((fileHandle = creat(test_name5, 0444)) == -1) { tst_brkm(TBROK, cleanup, "creat(2) FAILED to create temp file"); } sprintf(test_name3, "%s/fake.%d", test_name5, getpid()); /* creat() and close a zero length file with executeable permission */ sprintf(test_name6, "%s/execve03.%d", cwdname, getpid()); if ((fd = creat(test_name6, 0755)) == -1) { tst_brkm(TBROK, cleanup, "creat() failed"); } if (close(fd) == -1) { tst_brkm(TBROK, cleanup, "close() failed"); } bad_addr = mmap(0, 1, PROT_NONE, MAP_PRIVATE_EXCEPT_UCLINUX|MAP_ANONYMOUS, 0, 0); if (bad_addr == MAP_FAILED) { tst_brkm(TBROK, cleanup, "mmap failed"); } TC[3].tname = bad_addr; }
BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { pid_t pid; int flags; int numArgs; LPSTR* pArgs = NULL; char** envp = NULL; char* filename = NULL; HANDLE thread; HANDLE process; WINPR_ACCESS_TOKEN* token; LPTCH lpszEnvironmentBlock; BOOL ret = FALSE; sigset_t oldSigMask; sigset_t newSigMask; BOOL restoreSigMask = FALSE; pid = 0; numArgs = 0; lpszEnvironmentBlock = NULL; pArgs = CommandLineToArgvA(lpCommandLine, &numArgs); if (!pArgs) return FALSE; flags = 0; token = (WINPR_ACCESS_TOKEN*) hToken; if (lpEnvironment) { envp = EnvironmentBlockToEnvpA(lpEnvironment); } else { lpszEnvironmentBlock = GetEnvironmentStrings(); if (!lpszEnvironmentBlock) goto finish; envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock); } if (!envp) goto finish; filename = FindApplicationPath(pArgs[0]); if (NULL == filename) goto finish; /* block all signals so that the child can safely reset the caller's handlers */ sigfillset(&newSigMask); restoreSigMask = !pthread_sigmask(SIG_SETMASK, &newSigMask, &oldSigMask); /* fork and exec */ pid = fork(); if (pid < 0) { /* fork failure */ goto finish; } if (pid == 0) { /* child process */ #ifndef __sun int maxfd; #endif int fd; int sig; sigset_t set; struct sigaction act; /* set default signal handlers */ memset(&act, 0, sizeof(act)); act.sa_handler = SIG_DFL; act.sa_flags = 0; sigemptyset(&act.sa_mask); for (sig = 1; sig < NSIG; sig++) sigaction(sig, &act, NULL); /* unblock all signals */ sigfillset(&set); pthread_sigmask(SIG_UNBLOCK, &set, NULL); if (lpStartupInfo) { int handle_fd; handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdOutput); if (handle_fd != -1) dup2(handle_fd, STDOUT_FILENO); handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdError); if (handle_fd != -1) dup2(handle_fd, STDERR_FILENO); handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdInput); if (handle_fd != -1) dup2(handle_fd, STDIN_FILENO); } #ifdef __sun closefrom(3); #else #ifdef F_MAXFD // on some BSD derivates maxfd = fcntl(0, F_MAXFD); #else maxfd = sysconf(_SC_OPEN_MAX); #endif for(fd=3; fd<maxfd; fd++) close(fd); #endif // __sun if (token) { if (token->GroupId) { int rc = setgid((gid_t) token->GroupId); if (rc < 0) { } else { initgroups(token->Username, (gid_t) token->GroupId); } } if (token->UserId) setuid((uid_t) token->UserId); } /* TODO: add better cwd handling and error checking */ if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0) chdir(lpCurrentDirectory); if (execve(filename, pArgs, envp) < 0) { /* execve failed - end the process */ _exit(1); } } else { /* parent process */ } process = CreateProcessHandle(pid); if (!process) { goto finish; } thread = CreateNoneHandle(); if (!thread) { ProcessHandleCloseHandle(process); goto finish; } lpProcessInformation->hProcess = process; lpProcessInformation->hThread = thread; lpProcessInformation->dwProcessId = (DWORD) pid; lpProcessInformation->dwThreadId = (DWORD) pid; ret = TRUE; finish: /* restore caller's original signal mask */ if (restoreSigMask) pthread_sigmask(SIG_SETMASK, &oldSigMask, NULL); free(filename); if (pArgs) { HeapFree(GetProcessHeap(), 0, pArgs); } if (lpszEnvironmentBlock) FreeEnvironmentStrings(lpszEnvironmentBlock); if (envp) { int i = 0; while (envp[i]) { free(envp[i]); i++; } free(envp); } return ret; }
int main(int argc, char **argv) { struct protox *tp = NULL; /* for printing cblocks & stats */ int ch; int n; af = AF_UNSPEC; while ((ch = getopt(argc, argv, "Aabc:df:gI:iLlM:mN:nPp:rSsBtuWw:z")) != -1) switch(ch) { case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'b': bflag = 1; break; case 'c': kread(0, 0, 0); kread(nl[N_NCPUS].n_value, (char *)&n, sizeof(n)); cpuflag = strtol(optarg, NULL, 0); if (cpuflag < 0 || cpuflag >= n) errx(1, "cpu %d does not exist", cpuflag); break; case 'd': dflag = 1; break; case 'f': if (strcmp(optarg, "ipx") == 0) af = AF_IPX; else if (strcmp(optarg, "inet") == 0) af = AF_INET; #ifdef INET6 else if (strcmp(optarg, "inet6") == 0) af = AF_INET6; #endif /*INET6*/ #ifdef INET6 else if (strcmp(optarg, "pfkey") == 0) af = PF_KEY; #endif /*INET6*/ else if (strcmp(optarg, "unix") == 0) af = AF_UNIX; else if (strcmp(optarg, "ng") == 0 || strcmp(optarg, "netgraph") == 0) af = AF_NETGRAPH; #ifdef ISO else if (strcmp(optarg, "iso") == 0) af = AF_ISO; #endif else if (strcmp(optarg, "link") == 0) af = AF_LINK; else if (strcmp(optarg, "mpls") == 0) af = AF_MPLS; else { errx(1, "%s: unknown address family", optarg); } break; case 'g': gflag = 1; break; case 'I': { char *cp; iflag = 1; for (cp = interface = optarg; isalpha(*cp); cp++) continue; unit = atoi(cp); break; } case 'i': iflag = 1; break; case 'L': Lflag = 1; break; case 'M': memf = optarg; break; case 'm': mflag = 1; break; case 'N': nlistf = optarg; break; case 'n': numeric_addr = numeric_port = 1; break; case 'P': Pflag = 1; break; case 'p': if ((tp = name2protox(optarg)) == NULL) { errx(1, "%s: unknown or uninstrumented protocol", optarg); } pflag = 1; break; case 'r': rflag = 1; break; case 's': ++sflag; break; case 'S': numeric_addr = 1; break; case 'B': Bflag = 1; break; case 't': tflag = 1; break; case 'u': af = AF_UNIX; break; case 'W': case 'l': Wflag = 1; break; case 'w': interval = atoi(optarg); iflag = 1; break; case 'z': zflag = 1; break; case '?': default: usage(); } argv += optind; argc -= optind; #define BACKWARD_COMPATIBILITY #ifdef BACKWARD_COMPATIBILITY if (*argv) { if (isdigit(**argv)) { interval = atoi(*argv); if (interval <= 0) usage(); ++argv; iflag = 1; } if (*argv) { nlistf = *argv; if (*++argv) memf = *argv; } } #endif /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ if (nlistf != NULL || memf != NULL) setgid(getgid()); if (mflag) { if (memf != NULL) { if (kread(0, 0, 0) == 0) mbpr(nl[N_MBSTAT].n_value, nl[N_MBTYPES].n_value, nl[N_NMBCLUSTERS].n_value, nl[N_NMBUFS].n_value, nl[N_NCPUS].n_value); } else { mbpr(0, 0, 0, 0, 0); } exit(0); } #if 0 /* * Keep file descriptors open to avoid overhead * of open/close on each call to get* routines. */ sethostent(1); setnetent(1); #else /* * This does not make sense any more with DNS being default over * the files. Doing a setXXXXent(1) causes a tcp connection to be * used for the queries, which is slower. */ #endif if (iflag && !sflag) { kread(0, 0, 0); intpr(interval, nl[N_IFNET].n_value, NULL); exit(0); } if (rflag) { kread(0, 0, 0); if (sflag) rt_stats(); else routepr(nl[N_RTREE].n_value); exit(0); } if (gflag) { kread(0, 0, 0); if (sflag) { if (af == AF_INET || af == AF_UNSPEC) mrt_stats(nl[N_MRTSTAT].n_value); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mrt6_stats(nl[N_MRT6STAT].n_value); #endif } else { if (af == AF_INET || af == AF_UNSPEC) mroutepr(nl[N_MFCTABLE].n_value, nl[N_VIFTABLE].n_value); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mroute6pr(nl[N_MF6CTABLE].n_value, nl[N_MIF6TABLE].n_value); #endif } exit(0); } kread(0, 0, 0); if (tp) { printproto(tp, tp->pr_name); exit(0); } if (af == AF_INET || af == AF_UNSPEC) for (tp = protox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) for (tp = ip6protox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /*INET6*/ #ifdef IPSEC if (af == PF_KEY || af == AF_UNSPEC) for (tp = pfkeyprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /*IPSEC*/ if (af == AF_IPX || af == AF_UNSPEC) { kread(0, 0, 0); for (tp = ipxprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); } if (af == AF_NETGRAPH || af == AF_UNSPEC) for (tp = netgraphprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #ifdef ISO if (af == AF_ISO || af == AF_UNSPEC) for (tp = isoprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) unixpr(); exit(0); }
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) { int i; char *colon = NULL; int counter; char **uenvs; char *uef; char **vassal_argv; pid_t pid; if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) { uwsgi_error("socketpair()"); return -1; } event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]); if (n_ui->use_config) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) { uwsgi_error("socketpair()"); return -1; } } if (n_ui->zerg) { uwsgi.emperor_broodlord_num++; } // TODO pre-start hook // a new uWSGI instance will start pid = fork(); if (pid < 0) { uwsgi_error("fork()") } else if (pid > 0) { n_ui->pid = pid; // close the right side of the pipe close(n_ui->pipe[1]); // close the "on demand" socket if (n_ui->on_demand_fd > -1) { close(n_ui->on_demand_fd); n_ui->on_demand_fd = -1; } if (n_ui->use_config) { close(n_ui->pipe_config[1]); } if (n_ui->use_config) { struct uwsgi_header uh; uh.modifier1 = 115; uh.pktsize = n_ui->config_len; uh.modifier2 = 0; if (write(n_ui->pipe_config[0], &uh, 4) != 4) { uwsgi_error("[uwsgi-emperor] write() header config"); } else { if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) != (long) n_ui->config_len) { uwsgi_error("[uwsgi-emperor] write() config"); } } } return 0; } else { if (uwsgi.emperor_tyrant) { uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name); if (setgid(n_ui->gid)) { uwsgi_error("setgid()"); exit(1); } if (setgroups(0, NULL)) { uwsgi_error("setgroups()"); exit(1); } if (setuid(n_ui->uid)) { uwsgi_error("setuid()"); exit(1); } } unsetenv("UWSGI_RELOADS"); unsetenv("NOTIFY_SOCKET"); uef = uwsgi_num2str(n_ui->pipe[1]); if (setenv("UWSGI_EMPEROR_FD", uef, 1)) { uwsgi_error("setenv()"); exit(1); } free(uef); // add UWSGI_BROODLORD_NUM if (n_ui->zerg) { uef = uwsgi_num2str(uwsgi.emperor_broodlord_num); if (setenv("UWSGI_BROODLORD_NUM", uef, 1)) { uwsgi_error("setenv()"); exit(1); } free(uef); } if (n_ui->use_config) { uef = uwsgi_num2str(n_ui->pipe_config[1]); if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) { uwsgi_error("setenv()"); exit(1); } free(uef); } uenvs = environ; while (*uenvs) { if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) { char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13); char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0); if (unsetenv(oe)) { uwsgi_error("unsetenv()"); free(oe); break; } free(oe); #ifdef UWSGI_DEBUG uwsgi_log("putenv %s\n", ne); #endif if (putenv(ne)) { uwsgi_error("putenv()"); } // do not free ne as putenv will add it to the environ uenvs = environ; continue; } uenvs++; } // close the left side of the pipe close(n_ui->pipe[0]); if (n_ui->use_config) { close(n_ui->pipe_config[0]); } counter = 4; struct uwsgi_string_list *uct = uwsgi.vassals_templates; while (uct) { counter += 2; uct = uct->next; } vassal_argv = uwsgi_malloc(sizeof(char *) * counter); // set args vassal_argv[0] = uwsgi.binary_path; if (uwsgi.emperor_broodlord) { colon = strchr(n_ui->name, ':'); if (colon) { colon[0] = 0; } } // initialize to a default value vassal_argv[1] = "--inherit"; if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml")) vassal_argv[1] = "--xml"; if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini")) vassal_argv[1] = "--ini"; if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml")) vassal_argv[1] = "--yaml"; if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml")) vassal_argv[1] = "--yaml"; if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js")) vassal_argv[1] = "--json"; if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json")) vassal_argv[1] = "--json"; if (colon) { colon[0] = ':'; } vassal_argv[2] = n_ui->name; if (uwsgi.emperor_magic_exec) { if (!access(n_ui->name, R_OK | X_OK)) { vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name); } } if (n_ui->use_config) { vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name); } counter = 3; uct = uwsgi.vassals_templates; while (uct) { vassal_argv[counter] = "--inherit"; vassal_argv[counter + 1] = uct->value; counter += 2; uct = uct->next; } vassal_argv[counter] = NULL; // disable stdin OR map it to the "on demand" socket if (n_ui->on_demand_fd > -1) { if (n_ui->on_demand_fd != 0) { if (dup2(n_ui->on_demand_fd, 0) < 0) { uwsgi_error("dup2()"); exit(1); } close(n_ui->on_demand_fd); } } else { int stdin_fd = open("/dev/null", O_RDONLY); if (stdin_fd < 0) { uwsgi_error_open("/dev/null"); exit(1); } if (stdin_fd != 0) { if (dup2(stdin_fd, 0) < 0) { uwsgi_error("dup2()"); exit(1); } close(stdin_fd); } } // close all of the unneded fd for (i = 3; i < (int) uwsgi.max_fd; i++) { if (n_ui->use_config) { if (i == n_ui->pipe_config[1]) continue; } if (i != n_ui->pipe[1]) { close(i); } } if (uwsgi.vassals_start_hook) { uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name); if (uwsgi.emperor_absolute_dir) { if (setenv("UWSGI_VASSALS_DIR", uwsgi.emperor_absolute_dir, 1)) { uwsgi_error("setenv()"); } } int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name); uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret); } // start !!! if (execvp(vassal_argv[0], vassal_argv)) { uwsgi_error("execvp()"); } uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n"); // never here exit(UWSGI_EXILE_CODE); } return -1; }
/* * mail [ -ehpPqrtw ] [-x debuglevel] [ -f file ] [ -F user(s) ] * mail -T file persons * mail [ -tw ] [ -m messagetype ] persons * rmail [ -tw ] persons */ int main(int argc, char **argv) { register int i; char *cptr, *p; static char pn[] = "main"; extern char **environ; int env_var_idx, next_slot_idx; int tmpfd = -1; (void)&argc; (void)&argv; setlocale(LC_CTYPE, ""); mb_cur_max = MB_CUR_MAX; /* fix here for bug #1086130 - security hole */ /* skip over the LD_* env variable */ env_var_idx = 0; next_slot_idx = 0; while (environ[env_var_idx] != NULL) { environ[next_slot_idx] = environ[env_var_idx]; if (strncmp(environ[env_var_idx], "LD_", 3)) { next_slot_idx++; } env_var_idx++; } environ[next_slot_idx] = NULL; line = smalloc(linesize = LSIZE); *line = '\0'; #ifdef SIGCONT { struct sigaction nsig; nsig.sa_handler = SIG_DFL; sigemptyset(&nsig.sa_mask); nsig.sa_flags = SA_RESTART; sigaction(SIGCONT, &nsig, (struct sigaction *)0); } #endif /* * Strip off path name of this command for use in messages */ if ((program = strrchr(argv[0], '/')) != NULL) { program++; } else { program = argv[0]; } /* Close all file descriptors except stdin, stdout & stderr */ for (i = 3; close(i) == 0; i++); /* * Get group id for mail, exit if none exists */ if ((grpptr = getgrnam("mail")) == NULL) { errmsg(E_GROUP, ""); exit(1); } else { mailgrp = grpptr->gr_gid; } /* * Save the *id for later use. */ my_uid = getuid(); my_gid = getgid(); my_euid = geteuid(); my_egid = getegid(); /* * What command (rmail or mail)? */ if (strcmp(program, "rmail") == SAME) { ismail = FALSE; } /* * Parse the command line and adjust argc and argv * to compensate for any options */ i = parse(argc, argv); argv += (i - 1); argc -= (i - 1); /* block a potential security hole */ if (flgT && (my_euid != 0)) { setgid(my_gid); Tout(pn, "Setgid unset\n"); } if (debug == 0) { /* If not set as an invocation option, check for system-wide */ /* global flag */ char *xp = xgetenv("DEBUG"); if (xp != (char *)NULL) { debug = atoi(xp); if (debug < 0) { /* Keep trace file even if successful */ keepdbgfile = -1; debug = -debug; } } } if (debug > 0) { strcpy(dbgfname, "/tmp/MLDBGXXXXXX"); if ((tmpfd = mkstemp(dbgfname)) == -1) { fprintf(stderr, "%s: can't open debugging file '%s'\n", program, dbgfname); exit(13); } if ((dbgfp = fdopen(tmpfd, "w")) == (FILE *)NULL) { fprintf(stderr, "%s: can't open debugging file '%s'\n", program, dbgfname); close(tmpfd); exit(13); } setbuf(dbgfp, NULL); fprintf(dbgfp, "main(): debugging level == %d\n", debug); fprintf(dbgfp, "main(): trace file ='%s': kept %s\n", dbgfname, ((keepdbgfile < 0) ? "on success or failure." : "only on failure.")); } if (!ismail && (goerr > 0 || !i)) { Dout(pn, 11, "!ismail, goerr=%d, i=%d\n", goerr, i); if (goerr > 0) { errmsg(E_SYNTAX, "Usage: rmail [-wt] person(s)"); } if (!i) { errmsg(E_SYNTAX, "At least one user must be specified"); } Dout(pn, 11, "exiting!\n"); done(0); } umsave = umask(7); uname(&utsn); if ((p = xgetenv("CLUSTER")) != (char *)NULL) { /* * We are not who we appear... */ thissys = p; } else { thissys = utsn.nodename; } Dout(pn, 11, "thissys = '%s', uname = '%s'\n", thissys, utsn.nodename); failsafe = xgetenv("FAILSAFE"); if (failsafe) Dout(pn, 11, "failsafe processing enabled to %s\n", failsafe); /* * Use environment variables */ home = getenv("HOME"); if (!home || !*home) { home = "."; } pwd = getpwuid(my_uid); if (pwd) cpy(&my_name, &my_namesize, pwd->pw_name); else cpy(&my_name, &my_namesize, ""); /* If root, use LOGNAME if set */ if (my_uid == 0) { /* If root, use LOGNAME if set */ if (((cptr = getenv("LOGNAME")) != NULL) && (strlen(cptr) != 0)) { cpy(&my_name, &my_namesize, cptr); } } Dout(pn, 11, "my_name = '%s'\n", my_name); /* * Catch signals for cleanup */ if (setjmp(sjbuf)) { done(0); } setsig(SIGINT, delete); setsig(SIGQUIT, delete); setsig(SIGTRAP, delete); #ifdef SIGIOT setsig(SIGIOT, delete); #endif #ifdef SIGEMT setsig(SIGEMT, delete); #endif setsig(SIGBUS, delete); setsig(SIGSEGV, delete); setsig(SIGPIPE, delete); setsig(SIGALRM, delete); setsig(SIGHUP, sig_done); setsig(SIGTERM, sig_done); cksaved(my_name); /* * Rmail is always invoked to send mail */ Dout(pn, 11, "ismail=%d, argc=%d\n", ismail, argc); if (ismail && (argc == 1)) { sending = FALSE; printmail(); } else { sending = TRUE; sendmail(argc, argv); } done(0); /*NOTREACHED*/ return 0; }
void closecal(FILE *fp) { uid_t uid; struct stat sbuf; int nread, pdes[2], status; char buf[1024]; if (!doall) return; rewind(fp); if (fstat(fileno(fp), &sbuf) || !sbuf.st_size) goto done; if (pipe(pdes) < 0) goto done; switch (fork()) { case -1: /* error */ (void)close(pdes[0]); (void)close(pdes[1]); goto done; case 0: /* child -- set stdin to pipe output */ if (pdes[0] != STDIN_FILENO) { (void)dup2(pdes[0], STDIN_FILENO); (void)close(pdes[0]); } (void)close(pdes[1]); uid = geteuid(); if (setuid(getuid()) < 0) { warnx("setuid failed"); _exit(1); } if (setgid(getegid()) < 0) { warnx("setgid failed"); _exit(1); } if (setuid(uid) < 0) { warnx("setuid failed"); _exit(1); } execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", "\"Reminder Service\"", (char *)NULL); warn(_PATH_SENDMAIL); _exit(1); } /* parent -- write to pipe input */ (void)close(pdes[0]); write(pdes[1], "From: \"Reminder Service\" <", 26); write(pdes[1], pw->pw_name, strlen(pw->pw_name)); write(pdes[1], ">\nTo: <", 7); write(pdes[1], pw->pw_name, strlen(pw->pw_name)); write(pdes[1], ">\nSubject: ", 11); write(pdes[1], dayname, strlen(dayname)); write(pdes[1], "'s Calendar\nPrecedence: bulk\n\n", 30); while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) (void)write(pdes[1], buf, nread); (void)close(pdes[1]); done: (void)fclose(fp); (void)unlink(path); while (wait(&status) >= 0); }