Ejemplo n.º 1
0
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);
    }
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
    }
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
/*
 * 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);
}