void runIpmgmtd(void) { pid_t pid; int status; int tmplfd; tmplfd = init_template(0); if ((pid = fork()) == -1) { fatal(ERR_FORK_FAILED, "fork() failed: %s\n", strerror(errno)); } if (pid == 0) { /* child */ char cmd[MAXPATHLEN]; char *const argv[] = { "ipmgmtd", NULL }; char *const envp[] = { "SMF_FMRI=svc:/network/ip-interface-management:default", NULL }; (void) ct_tmpl_clear(tmplfd); (void) close(tmplfd); makePath(IPMGMTD, cmd, sizeof (cmd)); execve(cmd, argv, envp); fatal(ERR_EXEC_FAILED, "execve(%s) failed: %s\n", cmd, strerror(errno)); } /* parent */ (void) ct_tmpl_clear(tmplfd); (void) close(tmplfd); dlog("INFO started ipmgmtd[%d]\n", (int)pid); while (wait(&status) != pid) { /* EMPTY */; } if (WIFEXITED(status)) { dlog("INFO ipmgmtd[%d] exited: %d\n", (int)pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { fatal(ERR_IPMGMTD_DIED, "ipmgmtd[%d] died on signal: %d\n", (int)pid, WTERMSIG(status)); } else { fatal(ERR_IPMGMTD_CRASHED, "ipmgmtd[%d] failed in unknown way\n", (int)pid); } }
Export* erts_export_put(Eterm mod, Eterm func, unsigned int arity) { ErtsCodeIndex code_ix = erts_staging_code_ix(); struct export_templ templ; struct export_entry* ee; ASSERT(is_atom(mod)); ASSERT(is_atom(func)); export_staging_lock(); ee = (struct export_entry*) index_put_entry(&export_tables[code_ix], init_template(&templ, mod, func, arity)); export_staging_unlock(); return ee->ep; }
Export* erts_find_function(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex code_ix) { struct export_templ templ; struct export_entry* ee; ee = hash_get_ext(&export_tables[code_ix].htable, init_template(&templ, m, f, a), &fun); if (ee == NULL || (ee->ep->addressv[code_ix] == ee->ep->code+3 && ee->ep->code[3] != (BeamInstr) BeamOp(op_i_generic_breakpoint))) { return NULL; } return ee->ep; }
static void setupLogging(boolean_t ctty) { char *argv[] = { "logger", NULL, NULL }; char cmd[MAXPATHLEN]; char *data; char **envp; int i; char *log_driver = "json-file"; pid_t pid; pid_t init_pid; int _stdout; int _stderr; int tmpfd; int tmplfd; boolean_t use_flowcon = B_FALSE; if ((data = mdataGet("docker:logdriver")) != NULL) { if (strcmp("json-file", data) != 0) { log_driver = strdup(data); if (log_driver == NULL) { fatal(ERR_STRDUP, "unable to strdup() logdriver: %s\n", strerror(errno)); } } free(data); } dlog("INFO logdriver %s\n", log_driver); argv[1] = log_driver; /* * When we're not using json-file, we want to fork a logger child to handle * the logging driver. For json-file and none we don't need to do anything * in the zone. */ if (strcmp("json-file", log_driver) == 0 || strcmp("none", log_driver) == 0) { return; } // keep the pid of init/dockerinit so we can kill if the logger doesn't work init_pid = getpid(); dlog("INFO gathering logger environment\n"); envp = getLoggingEnv(); dlog("INFO creating logger child for %s\n", log_driver); if ((pid = fork()) == -1) { fatal(ERR_FORK_FAILED, "fork() failed: %s\n", strerror(errno)); } if (pid == 0) { /* child */ /* * The init process and the logger must be in the same contract so that * init will be killed if the logger exits. However, we neeed to ensure * that any children of the logger are in a separate contract. */ tmplfd = init_template(CT_PR_KEEP_EXEC); (void) close(tmplfd); // Keep descriptor 0 as a copy of the log descriptor so that errors // until exec() (or if it fails) will go to the dockerinit log. If exec // is successful, the descriptor should close since it's opened CLOEXEC. if (dup2(log_fd, 0) < 0) { fatal(ERR_DUP2, "failed to dup2(log_fd, 0): %s\n", strerror(errno)); } log_stream = fdopen(0, "w"); if (log_stream == NULL) { log_stream = stderr; fatal(ERR_FDOPEN_LOG, "failed to fdopen(2): %s\n", strerror(errno)); } // close everything except the log_stream descriptor (0) closefrom(1); // connect 1,2 to /dev/null _stdout = open("/dev/null", O_WRONLY); if (_stdout != 1) { fatal(ERR_OPEN_CONSOLE, "failed to open /dev/null as stdout: %s\n", strerror(errno)); } _stderr = open("/dev/null", O_WRONLY); if (_stderr != 2) { fatal(ERR_OPEN_CONSOLE, "failed to open /dev/null as stderr: %s\n", strerror(errno)); } // setup the zfd redirection if (ctty) { makeMux(0, 1, use_flowcon); tmpfd = zfd_open("/dev/zfd/1", O_RDONLY); if (tmpfd != 3) { fatal(ERR_OPEN_CONSOLE, "failed to open /dev/zfd/1: %s\n", strerror(errno)); } tmpfd = open("/dev/null", O_RDONLY); if (tmpfd != 4) { fatal(ERR_OPEN_CONSOLE, "failed to open /dev/null: %s\n", strerror(errno)); } } else { makeMux(1, 3, use_flowcon); makeMux(2, 4, use_flowcon); tmpfd = zfd_open("/dev/zfd/3", O_RDONLY); if (tmpfd != 3) { fatal(ERR_OPEN_CONSOLE, "failed to open /dev/zfd/3: %s\n", strerror(errno)); } tmpfd = zfd_open("/dev/zfd/4", O_RDONLY); if (tmpfd != 4) { fatal(ERR_OPEN_CONSOLE, "failed to open /dev/zfd/4: %s\n", strerror(errno)); } } // log ENV + args + cmd, then close log hole makePath(DOCKER_LOGGER, cmd, sizeof (cmd)); dlog("LOGGER CMD '%s'\n", cmd); i = 0; while (argv[i] != NULL) { dlog("LOGGER ARG[%d] %s\n", i, argv[i]); i++; } dlog("LOGGER ARG[%d] <NULL>\n", i); i = 0; while (envp[i] != NULL) { dlog("LOGGER ENV[%d] %s\n", i, envp[i]); i++; } dlog("LOGGER ENV[%d] <NULL>\n", i); execve(cmd, argv, envp); dlog("LOGGER ERROR execve(%s) failed: %s\n", cmd, strerror(errno)); dlog("LOGGER ERROR killing init[%d]\n", (int)init_pid); (void) kill(init_pid, SIGKILL); fatal(ERR_EXEC_FAILED, "execve(%s) failed and we killed init\n", cmd); } /* parent */ /* * The init process and the logger must be in the same contract so that * init will be killed if the logger exits. However, we neeed to ensure * that any children of the init process are in a separate contract. */ tmplfd = init_template(CT_PR_KEEP_EXEC); (void) close(tmplfd); dlog("INFO started logger[%d] (%s)\n", (int)pid, log_driver); free(log_driver); }
static void doNfsMount(const char *nfsvolume, const char *mountpoint, boolean_t readonly) { pid_t pid; int status; int ret; int tmplfd; dlog("INFO mounting %s on %s\n", nfsvolume, mountpoint); /* ensure the directory exists */ ret = mkdir(mountpoint, 0755); if (ret == -1 && errno != EEXIST) { fatal(ERR_MKDIR, "failed to mkdir(%s): (%d) %s\n", mountpoint, errno, strerror(errno)); } /* do the mount */ tmplfd = init_template(0); if ((pid = fork()) == -1) { fatal(ERR_FORK_FAILED, "fork() failed: %s\n", strerror(errno)); } if (pid == 0) { /* child */ char cmd[MAXPATHLEN]; char *const argv[] = { "mount", "-o", (readonly == B_TRUE) ? "vers=3,sec=sys,ro" : "vers=3,sec=sys", (char *)nfsvolume, (char *)mountpoint, NULL }; (void) ct_tmpl_clear(tmplfd); (void) close(tmplfd); makePath(NFS_MOUNT, cmd, sizeof (cmd)); execv(cmd, argv); fatal(ERR_EXEC_FAILED, "execv(%s) failed: %s\n", cmd, strerror(errno)); } /* parent */ (void) ct_tmpl_clear(tmplfd); (void) close(tmplfd); dlog("INFO started mount[%d]\n", (int)pid); while (wait(&status) != pid) { /* EMPTY */; } if (WIFEXITED(status)) { dlog("INFO mount[%d] exited: %d\n", (int)pid, WEXITSTATUS(status)); if (WEXITSTATUS(status) != 0) { fatal(ERR_MOUNT_NFS_VOLUME, "mount[%d] exited non-zero (%d)\n", (int)pid, WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { fatal(ERR_EXEC_FAILED, "mount[%d] died on signal: %d\n", (int)pid, WTERMSIG(status)); } else { fatal(ERR_EXEC_FAILED, "mount[%d] failed in unknown way\n", (int)pid); } }
static int zsocket(zoneid_t zoneid, const char *path) { char c = 0; ctid_t ct = -1; int _errno = 0; int pid = 0; int sock_fd = 0; int sockfd[2] = {0}; int stat = 0; int tmpl_fd = 0; int flags; struct sockaddr_un addr; size_t addr_len = 0; if (zoneid < 0) { return (-1); } if (path == NULL) { return (-1); } bzero(&addr, sizeof (addr)); pthread_mutex_lock(&lock); if ((tmpl_fd = init_template()) < 0) { pthread_mutex_unlock(&lock); return (-1); } if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) != 0) { (void) ct_tmpl_clear(tmpl_fd); pthread_mutex_unlock(&lock); return (-1); } pid = fork(); debug("fork returned: %d\n", pid); if (pid < 0) { _errno = errno; (void) ct_tmpl_clear(tmpl_fd); close(sockfd[0]); close(sockfd[1]); errno = _errno; pthread_mutex_unlock(&lock); return (-1); } if (pid == 0) { (void) ct_tmpl_clear(tmpl_fd); (void) close(tmpl_fd); (void) close(sockfd[0]); if (zone_enter(zoneid) != 0) { debug("CHILD: zone_enter(%d) => %s\n", zoneid, strerror(errno)); _exit(1); } debug("CHILD: zone_enter(%d) => %d\n", zoneid, 0); (void) unlink(path); sock_fd = socket(PF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { debug("CHILD: socket => %d\n", errno); _exit(2); } fcntl(sock_fd, F_SETFL, O_NONBLOCK); addr.sun_family = AF_UNIX; addr_len = sizeof (addr.sun_family) + snprintf(addr.sun_path, sizeof (addr.sun_path), path); if (bind(sock_fd, (struct sockaddr *) &addr, addr_len) != 0) { debug("CHILD: bind => %d\n", errno); _exit(3); } if (write_fd(sockfd[1], (void *)"", 1, sock_fd) < 0) { debug("CHILD: write_fd => %d\n", errno); _exit(4); } debug("CHILD: write_fd => %d\n", errno); _exit(0); } if (contract_latest(&ct) == -1) { ct = -1; } (void) ct_tmpl_clear(tmpl_fd); (void) close(tmpl_fd); (void) contract_abandon_id(ct); (void) close(sockfd[1]); debug("PARENT: waitforpid(%d)\n", pid); while ((waitpid(pid, &stat, 0) != pid) && errno != ECHILD) { /* DO NOTHING */; } if (WIFEXITED(stat) == 0) { debug("PARENT: Child didn't exit\n"); _errno = ECHILD; sock_fd = -1; } else { stat = WEXITSTATUS(stat); debug("PARENT: Child exit status %d\n", stat); if (stat == 0) { read_fd(sockfd[0], &c, 1, &sock_fd); } else { _errno = stat; sock_fd = -1; } } close(sockfd[0]); pthread_mutex_unlock(&lock); if (sock_fd < 0) { errno = _errno; } else { if ((flags = fcntl(sock_fd, F_GETFD)) != -1) { flags |= FD_CLOEXEC; (void) fcntl(sock_fd, F_SETFD, flags); } errno = 0; } debug("zsocket returning fd=%d, errno=%d\n", sock_fd, errno); return (sock_fd); }
/* * Note to future maintainers: with the change of wall to use the * getutxent() API, the forked children (created by this function) * must call _exit as opposed to exit. This is necessary to avoid * unwanted fflushing of getutxent's stdio stream (caused by atexit * processing). */ static void sendmes(struct utmpx *p, zoneid_t zid) { int i; char *s; static char device[LMAX + 6]; char *bp; int ibp; FILE *f; int fd, tmpl_fd; boolean_t zoneenter = B_FALSE; if (zid != getzoneid()) { zoneenter = B_TRUE; tmpl_fd = init_template(); if (tmpl_fd == -1) { (void) fprintf(stderr, "Could not initialize " "process contract"); return; } } while ((i = (int)fork()) == -1) { (void) alarm(60); (void) wait((int *)0); (void) alarm(0); } if (i) return; if (zoneenter && zone_enter(zid) == -1) { char zonename[ZONENAME_MAX]; (void) getzonenamebyid(zid, zonename, ZONENAME_MAX); (void) fprintf(stderr, "Could not enter zone " "%s\n", zonename); } if (zoneenter) (void) ct_tmpl_clear(tmpl_fd); if (gflag) if (!chkgrp(p->ut_user)) _exit(0); (void) signal(SIGHUP, SIG_IGN); (void) alarm(60); s = &device[0]; (void) snprintf(s, sizeof (device), "/dev/%.*s", LMAX, p->ut_line); /* check if the device is really a tty */ if ((fd = open(s, O_WRONLY|O_NOCTTY|O_NONBLOCK)) == -1) { (void) fprintf(stderr, "Cannot send to %.*s on %s\n", NMAX, p->ut_user, s); perror("open"); (void) fflush(stderr); _exit(1); } else { if (!isatty(fd)) { (void) fprintf(stderr, "Cannot send to device %.*s %s\n", LMAX, p->ut_line, "because it's not a tty"); openlog("wall", 0, LOG_AUTH); syslog(LOG_CRIT, "%.*s in utmpx is not a tty\n", LMAX, p->ut_line); closelog(); (void) fflush(stderr); _exit(1); } } #ifdef DEBUG (void) close(fd); f = fopen("wall.debug", "a"); #else f = fdopen(fd, "w"); #endif if (f == NULL) { (void) fprintf(stderr, "Cannot send to %-.*s on %s\n", NMAX, &p->ut_user[0], s); perror("open"); (void) fflush(stderr); _exit(1); } (void) fprintf(f, "\07\07\07Broadcast Message from %s (%s) on %s %19.19s", who, line, systm, time_buf); if (gflag) (void) fprintf(f, " to group %s", grpname); (void) fprintf(f, "...\n"); #ifdef DEBUG (void) fprintf(f, "DEBUG: To %.*s on %s\n", NMAX, p->ut_user, s); #endif i = strlen(mesg); for (bp = mesg; --i >= 0; bp++) { ibp = (unsigned int)((unsigned char) *bp); if (*bp == '\n') (void) putc('\r', f); if (isprint(ibp) || *bp == '\r' || *bp == '\013' || *bp == ' ' || *bp == '\t' || *bp == '\n' || *bp == '\007') { (void) putc(*bp, f); } else { if (!isascii(*bp)) { (void) fputs("M-", f); *bp = toascii(*bp); } if (iscntrl(*bp)) { (void) putc('^', f); (void) putc(*bp + 0100, f); } else (void) putc(*bp, f); } if (*bp == '\n') (void) fflush(f); if (ferror(f) || feof(f)) { (void) printf("\n\007Write failed\n"); (void) fflush(stdout); _exit(1); } } (void) fclose(f); (void) close(fd); _exit(0); }