summaryrefslogtreecommitdiffstats
path: root/sbin/casperd
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/casperd')
-rw-r--r--sbin/casperd/Makefile17
-rw-r--r--sbin/casperd/casperd.8132
-rw-r--r--sbin/casperd/casperd.c721
-rw-r--r--sbin/casperd/zygote.c227
-rw-r--r--sbin/casperd/zygote.h40
5 files changed, 0 insertions, 1137 deletions
diff --git a/sbin/casperd/Makefile b/sbin/casperd/Makefile
deleted file mode 100644
index 93f145c..0000000
--- a/sbin/casperd/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-
-PROG= casperd
-
-SRCS= casperd.c zygote.c
-
-LIBADD= casper nv pjdlog util
-
-MAN= casperd.8
-
-CFLAGS+=-I${.CURDIR}
-CFLAGS+=-I${.CURDIR}/../../lib/libcapsicum
-CFLAGS+=-I${.CURDIR}/../../lib/libcasper
-CFLAGS+=-I${.CURDIR}/../../lib/libnv
-CFLAGS+=-I${.CURDIR}/../../lib/libpjdlog
-
-.include <bsd.prog.mk>
diff --git a/sbin/casperd/casperd.8 b/sbin/casperd/casperd.8
deleted file mode 100644
index 945b517..0000000
--- a/sbin/casperd/casperd.8
+++ /dev/null
@@ -1,132 +0,0 @@
-.\" Copyright (c) 2013 The FreeBSD Foundation
-.\" All rights reserved.
-.\"
-.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
-.\" from the FreeBSD Foundation.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd October 26, 2013
-.Dt CASPERD 8
-.Os
-.Sh NAME
-.Nm casperd
-.Nd "Capability Services friendly daemon"
-.Sh SYNOPSIS
-.Nm
-.Op Fl Fhv
-.Op Fl l Ar listenqueue
-.Op Fl D Ar servconfdir
-.Op Fl P Ar pidfile
-.Op Fl S Ar sockpath
-.Sh DESCRIPTION
-The
-.Nm
-daemon hosts various services that can be accessed through
-libcapsicum's capabilities by programs running in sandboxes.
-For example it is prohibited to send UDP packets to arbitrary destinations
-when operating in capability mode, which makes DNS resolution impossible.
-To make it possible the
-.Nm
-daemon provides the
-.Nm system.dns
-service that proxies DNS resolution requests through a dedicated,
-non-sandboxed process provided by
-.Nm .
-.Pp
-The
-.Nm
-daemon can be started with the following command line arguments:
-.Bl -tag -width ".Fl D Ar servconfdir"
-.It Fl D Ar servconfdir
-Specify alternative location of the service configuration directory.
-The default location is
-.Pa /etc/casper/ .
-.It Fl F
-Start the
-.Nm
-daemon in the foreground.
-By default
-.Nm
-starts in the background.
-.It Fl h
-Print the
-.Nm
-usage message.
-.It Fl l Ar listenqueue
-Specify depth of socket listen queue for the
-.Nm
-daemon.
-The default queue length is
-.Pa SOMAXCONN .
-.It Fl P Ar pidfile
-Specify alternative location of a file where main process PID will be
-stored.
-The default location is
-.Pa /var/run/casperd.pid .
-.It Fl S Ar sockpath
-Specify alternative location of the
-.Xr unix 4
-domain socket used to connect to the
-.Nm
-daemon.
-The default location is
-.Pa /var/run/casper .
-.It Fl v
-Print or log verbose/debugging information.
-This option can be specified multiple times to raise the verbosity
-level.
-.El
-.Sh FILES
-.Bl -tag -width ".Pa /var/run/casperd.pid" -compact
-.It Pa /etc/casper/
-The configuration directory for
-.Nm
-services.
-.It Pa /var/run/casper
-.Xr unix 4
-domain socket used to connect to the
-.Nm
-daemon.
-.It Pa /var/run/casperd.pid
-The default location of the
-.Nm
-PID file.
-.El
-.Sh EXIT STATUS
-The
-.Nm
-daemon exits 0 on success, and >0 if an error occurs.
-.Sh SEE ALSO
-.Xr cap_enter 2 ,
-.Xr libcapsicum 3 ,
-.Xr pidfile 3 ,
-.Xr capsicum 4 ,
-.Xr unix 4
-.Sh AUTHORS
-The
-.Nm
-was implemented by
-.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
-under sponsorship from the FreeBSD Foundation.
diff --git a/sbin/casperd/casperd.c b/sbin/casperd/casperd.c
deleted file mode 100644
index 65da58a..0000000
--- a/sbin/casperd/casperd.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*-
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Pawel Jakub Dawidek under sponsorship from
- * the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/capsicum.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <sys/nv.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libutil.h>
-#include <paths.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include <libcapsicum.h>
-#include <libcapsicum_impl.h>
-#include <libcasper.h>
-#include <libcasper_impl.h>
-#include <msgio.h>
-#include <pjdlog.h>
-
-#include "msgio.h"
-
-#include "zygote.h"
-
-#define CASPERD_PIDFILE "/var/run/casperd.pid"
-#define CASPERD_SERVCONFDIR "/etc/casper"
-#define CASPERD_SOCKPATH "/var/run/casper"
-
-typedef void service_function_t(struct service_connection *, const nvlist_t *,
- nvlist_t *);
-
-struct casper_service {
- const char *cs_name;
- const char *cs_execpath;
- struct service *cs_service;
- nvlist_t *cs_attrs;
- TAILQ_ENTRY(casper_service) cs_next;
-};
-
-static TAILQ_HEAD(, casper_service) casper_services =
- TAILQ_HEAD_INITIALIZER(casper_services);
-
-#define SERVICE_IS_CORE(service) ((service)->cs_execpath == NULL)
-
-static void service_external_execute(int chanfd);
-
-#define KEEP_ERRNO(work) do { \
- int _serrno; \
- \
- _serrno = errno; \
- work; \
- errno = _serrno; \
-} while (0)
-
-static struct casper_service *
-service_find(const char *name)
-{
- struct casper_service *casserv;
-
- TAILQ_FOREACH(casserv, &casper_services, cs_next) {
- if (strcmp(casserv->cs_name, name) == 0)
- break;
- }
- return (casserv);
-}
-
-/*
- * Function always consumes the given attrs.
- */
-static void
-service_register(nvlist_t *attrs)
-{
- struct casper_service *casserv;
- const char *name;
-
- PJDLOG_ASSERT(nvlist_exists_string(attrs, "name"));
- PJDLOG_ASSERT(nvlist_exists_string(attrs, "execpath") ||
- (nvlist_exists_number(attrs, "commandfunc") &&
- nvlist_exists_number(attrs, "limitfunc")));
-
- name = nvlist_get_string(attrs, "name");
- PJDLOG_ASSERT(name != NULL);
- if (name[0] == '\0') {
- pjdlog_error("Unable to register service with an empty name.");
- nvlist_destroy(attrs);
- return;
- }
- if (service_find(name) != NULL) {
- pjdlog_error("Service \"%s\" is already registered.", name);
- nvlist_destroy(attrs);
- return;
- }
-
- casserv = malloc(sizeof(*casserv));
- if (casserv == NULL) {
- pjdlog_errno(LOG_ERR, "Unable to register service \"%s\"",
- name);
- nvlist_destroy(attrs);
- return;
- }
- casserv->cs_name = name;
- if (nvlist_exists_string(attrs, "execpath")) {
- struct stat sb;
-
- PJDLOG_ASSERT(!nvlist_exists_number(attrs, "commandfunc"));
- PJDLOG_ASSERT(!nvlist_exists_number(attrs, "limitfunc"));
-
- casserv->cs_service = NULL;
-
- casserv->cs_execpath = nvlist_get_string(attrs, "execpath");
- if (casserv->cs_execpath == NULL ||
- casserv->cs_execpath[0] == '\0') {
- pjdlog_error("Unable to register service with an empty execpath.");
- free(casserv);
- nvlist_destroy(attrs);
- return;
- }
- if (stat(casserv->cs_execpath, &sb) == -1) {
- pjdlog_errno(LOG_ERR,
- "Unable to register service \"%s\", problem with executable \"%s\"",
- name, casserv->cs_execpath);
- free(casserv);
- nvlist_destroy(attrs);
- return;
- }
- } else /* if (nvlist_exists_number(attrs, "commandfunc")) */ {
- PJDLOG_ASSERT(!nvlist_exists_string(attrs, "execpath"));
-
- casserv->cs_execpath = NULL;
-
- casserv->cs_service = service_alloc(name,
- (void *)(uintptr_t)nvlist_get_number(attrs, "limitfunc"),
- (void *)(uintptr_t)nvlist_get_number(attrs, "commandfunc"));
- if (casserv->cs_service == NULL) {
- pjdlog_errno(LOG_ERR,
- "Unable to register service \"%s\"", name);
- free(casserv);
- nvlist_destroy(attrs);
- return;
- }
- }
- casserv->cs_attrs = attrs;
- TAILQ_INSERT_TAIL(&casper_services, casserv, cs_next);
- pjdlog_debug(1, "Service %s successfully registered.",
- casserv->cs_name);
-}
-
-static bool
-casper_allowed_service(const nvlist_t *limits, const char *service)
-{
-
- if (limits == NULL)
- return (true);
-
- if (nvlist_exists_null(limits, service))
- return (true);
-
- return (false);
-}
-
-static int
-casper_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
-{
- const char *name;
- int type;
- void *cookie;
-
- cookie = NULL;
- while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) {
- if (type != NV_TYPE_NULL)
- return (EINVAL);
- if (!casper_allowed_service(oldlimits, name))
- return (ENOTCAPABLE);
- }
-
- return (0);
-}
-
-static int
-casper_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
- nvlist_t *nvlout)
-{
- struct casper_service *casserv;
- const char *servname;
- nvlist_t *nvl;
- int chanfd, execfd, procfd, error;
-
- if (strcmp(cmd, "open") != 0)
- return (EINVAL);
- if (!nvlist_exists_string(nvlin, "service"))
- return (EINVAL);
-
- servname = nvlist_get_string(nvlin, "service");
-
- casserv = service_find(servname);
- if (casserv == NULL)
- return (ENOENT);
-
- if (!casper_allowed_service(limits, servname))
- return (ENOTCAPABLE);
-
-#ifdef O_EXEC_WORKING
- execfd = open(casserv->cs_execpath, O_EXEC);
-#else
- execfd = open(casserv->cs_execpath, O_RDONLY);
-#endif
- if (execfd < -1) {
- error = errno;
- pjdlog_errno(LOG_ERR,
- "Unable to open executable '%s' of service '%s'",
- casserv->cs_execpath, casserv->cs_name);
- return (error);
- }
-
- if (zygote_clone(service_external_execute, &chanfd, &procfd) == -1) {
- error = errno;
- close(execfd);
- return (error);
- }
-
- nvl = nvlist_create(0);
- nvlist_add_string(nvl, "service", casserv->cs_name);
- if (nvlist_exists_descriptor(nvlin, "stderrfd")) {
- nvlist_move_descriptor(nvl, "stderrfd",
- nvlist_take_descriptor(nvlin, "stderrfd"));
- }
- nvlist_move_descriptor(nvl, "execfd", execfd);
- nvlist_move_descriptor(nvl, "procfd", procfd);
- if (nvlist_send(chanfd, nvl) == -1) {
- error = errno;
- pjdlog_errno(LOG_ERR, "Unable to send nvlist");
- nvlist_destroy(nvl);
- close(chanfd);
- return (error);
- }
- nvlist_destroy(nvl);
-
- nvlist_move_descriptor(nvlout, "chanfd", chanfd);
-
- return (0);
-}
-
-static void
-fdswap(int *fd0, int *fd1)
-{
- int tmpfd;
-
- PJDLOG_VERIFY((tmpfd = dup(*fd0)) != -1);
- PJDLOG_VERIFY(dup2(*fd1, *fd0) != -1);
- PJDLOG_VERIFY(dup2(tmpfd, *fd1) != -1);
- close(tmpfd);
- tmpfd = *fd0;
- *fd0 = *fd1;
- *fd1 = tmpfd;
-}
-
-static void
-fdmove(int *oldfdp, int newfd)
-{
-
- if (*oldfdp != newfd) {
- PJDLOG_VERIFY(dup2(*oldfdp, newfd) != -1);
- close(*oldfdp);
- *oldfdp = newfd;
- }
-}
-
-static void
-fdcloexec(int fd)
-{
- int flags;
-
- flags = fcntl(fd, F_GETFD);
- PJDLOG_ASSERT(flags != -1);
- if ((flags & FD_CLOEXEC) != 0)
- PJDLOG_VERIFY(fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) != -1);
-}
-
-static void
-service_register_core(void)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- nvlist_add_string(nvl, "name", "core.casper");
- nvlist_add_number(nvl, "limitfunc", (uint64_t)(uintptr_t)casper_limit);
- nvlist_add_number(nvl, "commandfunc",
- (uint64_t)(uintptr_t)casper_command);
- service_register(nvl);
-}
-
-static int
-setup_creds(int sock)
-{
- struct cmsgcred cred;
-
- if (cred_recv(sock, &cred) == -1)
- return (-1);
-
- if (setgroups((int)cred.cmcred_ngroups, cred.cmcred_groups) == -1)
- return (-1);
-
- if (setgid(cred.cmcred_groups[0]) == -1)
- return (-1);
-
- if (setuid(cred.cmcred_euid) == -1)
- return (-1);
-
- return (0);
-}
-
-static void
-service_external_execute(int chanfd)
-{
- char *service, *argv[3];
- int stderrfd, execfd, procfd;
- nvlist_t *nvl;
-
- nvl = nvlist_recv(chanfd, 0);
- if (nvl == NULL)
- pjdlog_exit(1, "Unable to receive nvlist");
- service = nvlist_take_string(nvl, "service");
- PJDLOG_ASSERT(service != NULL);
- if (nvlist_exists_descriptor(nvl, "stderrfd")) {
- stderrfd = nvlist_take_descriptor(nvl, "stderrfd");
- } else {
- stderrfd = open(_PATH_DEVNULL, O_RDWR);
- if (stderrfd < 0)
- pjdlog_exit(1, "Unable to open %s", _PATH_DEVNULL);
- }
- execfd = nvlist_take_descriptor(nvl, "execfd");
- procfd = nvlist_take_descriptor(nvl, "procfd");
- nvlist_destroy(nvl);
-
- /*
- * Move all descriptors into right slots.
- */
-
- if (stderrfd != STDERR_FILENO) {
- if (chanfd == STDERR_FILENO)
- fdswap(&stderrfd, &chanfd);
- else if (execfd == STDERR_FILENO)
- fdswap(&stderrfd, &execfd);
- else if (procfd == STDERR_FILENO)
- fdswap(&stderrfd, &procfd);
- fdmove(&stderrfd, STDERR_FILENO);
- }
- fdcloexec(stderrfd);
-
- if (chanfd != PARENT_FILENO) {
- if (execfd == PARENT_FILENO)
- fdswap(&chanfd, &execfd);
- else if (procfd == PARENT_FILENO)
- fdswap(&chanfd, &procfd);
- fdmove(&chanfd, PARENT_FILENO);
- }
- fdcloexec(chanfd);
-
- if (execfd != EXECUTABLE_FILENO) {
- if (procfd == EXECUTABLE_FILENO)
- fdswap(&execfd, &procfd);
- fdmove(&execfd, EXECUTABLE_FILENO);
- }
- fdcloexec(execfd);
-
- if (procfd != PROC_FILENO)
- fdmove(&procfd, PROC_FILENO);
- fdcloexec(procfd);
-
- /*
- * Use credentials of the caller process.
- */
- setup_creds(chanfd);
-
- argv[0] = service;
- asprintf(&argv[1], "%d", pjdlog_debug_get());
- argv[2] = NULL;
-
- fexecve(execfd, argv, NULL);
- pjdlog_exit(1, "Unable to execute service %s", service);
-}
-
-static void
-service_register_external_one(const char *dirpath, int dfd,
- const char *filename)
-{
- char execpath[FILENAME_MAX];
- nvlist_t *nvl;
- ssize_t done;
- int fd;
-
- fd = openat(dfd, filename, O_RDONLY);
- if (fd == -1) {
- pjdlog_errno(LOG_ERR, "Unable to open \"%s/%s\"", dirpath,
- filename);
- return;
- }
-
- done = read(fd, execpath, sizeof(execpath));
- if (done == -1) {
- pjdlog_errno(LOG_ERR, "Unable to read content of \"%s/%s\"",
- dirpath, filename);
- close(fd);
- return;
- }
- close(fd);
- if (done == sizeof(execpath)) {
- pjdlog_error("Executable path too long in \"%s/%s\".", dirpath,
- filename);
- return;
- }
- execpath[done] = '\0';
- while (done > 0) {
- if (execpath[--done] == '\n')
- execpath[done] = '\0';
- }
-
- nvl = nvlist_create(0);
- nvlist_add_string(nvl, "name", filename);
- nvlist_add_string(nvl, "execpath", execpath);
- if (nvlist_error(nvl) != 0) {
- pjdlog_common(LOG_ERR, 0, nvlist_error(nvl),
- "Unable to allocate attributes for service \"%s/%s\"",
- dirpath, filename);
- nvlist_destroy(nvl);
- return;
- }
-
- service_register(nvl);
- /* service_register() consumed nvl. */
-}
-
-static uint8_t
-file_type(int dfd, const char *filename)
-{
- struct stat sb;
-
- if (fstatat(dfd, filename, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
- pjdlog_errno(LOG_ERR, "Unable to stat \"%s\"", filename);
- return (DT_UNKNOWN);
- }
- return (IFTODT(sb.st_mode));
-}
-
-static void
-service_register_external(const char *dirpath)
-{
- DIR *dirp;
- struct dirent *dp;
- int dfd;
-
- dirp = opendir(dirpath);
- if (dirp == NULL) {
- pjdlog_errno(LOG_WARNING, "Unable to open \"%s\"", dirpath);
- return;
- }
- dfd = dirfd(dirp);
- PJDLOG_ASSERT(dfd >= 0);
- while ((dp = readdir(dirp)) != NULL) {
- dp->d_type = file_type(dfd, dp->d_name);
- /* We are only interested in regular files, skip the rest. */
- if (dp->d_type != DT_REG) {
- pjdlog_debug(1,
- "File \"%s/%s\" is not a regular file, skipping.",
- dirpath, dp->d_name);
- continue;
- }
- service_register_external_one(dirpath, dfd, dp->d_name);
- }
- closedir(dirp);
-}
-
-static void
-casper_accept(int lsock)
-{
- struct casper_service *casserv;
- struct service_connection *sconn;
- int sock;
-
- sock = accept(lsock, NULL, NULL);
- if (sock == -1) {
- pjdlog_errno(LOG_ERR, "Unable to accept casper connection");
- return;
- }
- casserv = service_find("core.casper");
- PJDLOG_ASSERT(casserv != NULL);
-
- sconn = service_connection_add(casserv->cs_service, sock, NULL);
- if (sconn == NULL) {
- close(sock);
- return;
- }
-}
-
-static void
-main_loop(int lqlen, const char *sockpath, struct pidfh *pfh)
-{
- fd_set fds;
- struct sockaddr_un sun;
- struct casper_service *casserv;
- struct service_connection *sconn, *sconntmp;
- int lsock, sock, maxfd, ret;
- mode_t oldumask;
-
- lsock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (lsock == -1)
- pjdlog_exit(1, "Unable to create socket");
-
- (void)unlink(sockpath);
-
- bzero(&sun, sizeof(sun));
- sun.sun_family = AF_UNIX;
- PJDLOG_VERIFY(strlcpy(sun.sun_path, sockpath, sizeof(sun.sun_path)) <
- sizeof(sun.sun_path));
- sun.sun_len = SUN_LEN(&sun);
-
- oldumask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
- if (bind(lsock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
- pjdlog_exit(1, "Unable to bind to %s", sockpath);
- (void)umask(oldumask);
- if (listen(lsock, lqlen) == -1)
- pjdlog_exit(1, "Unable to listen on %s", sockpath);
-
- for (;;) {
- FD_ZERO(&fds);
- FD_SET(lsock, &fds);
- maxfd = lsock;
- TAILQ_FOREACH(casserv, &casper_services, cs_next) {
- /* We handle only core services. */
- if (!SERVICE_IS_CORE(casserv))
- continue;
- for (sconn = service_connection_first(casserv->cs_service);
- sconn != NULL;
- sconn = service_connection_next(sconn)) {
- sock = service_connection_get_sock(sconn);
- FD_SET(sock, &fds);
- maxfd = sock > maxfd ? sock : maxfd;
- }
- }
- maxfd++;
-
- PJDLOG_ASSERT(maxfd <= (int)FD_SETSIZE);
- ret = select(maxfd, &fds, NULL, NULL, NULL);
- PJDLOG_ASSERT(ret == -1 || ret > 0); /* select() cannot timeout */
- if (ret == -1) {
- if (errno == EINTR)
- continue;
- KEEP_ERRNO((void)pidfile_remove(pfh));
- pjdlog_exit(1, "select() failed");
- }
-
- if (FD_ISSET(lsock, &fds))
- casper_accept(lsock);
- TAILQ_FOREACH(casserv, &casper_services, cs_next) {
- /* We handle only core services. */
- if (!SERVICE_IS_CORE(casserv))
- continue;
- for (sconn = service_connection_first(casserv->cs_service);
- sconn != NULL; sconn = sconntmp) {
- /*
- * Prepare for connection to be removed from
- * the list on failure.
- */
- sconntmp = service_connection_next(sconn);
- sock = service_connection_get_sock(sconn);
- if (FD_ISSET(sock, &fds)) {
- service_message(casserv->cs_service,
- sconn);
- }
- }
- }
- }
-}
-
-static void
-usage(void)
-{
-
- pjdlog_exitx(1,
- "usage: casperd [-Fhv] [-D servconfdir] [-P pidfile] [-S sockpath]");
-}
-
-int
-main(int argc, char *argv[])
-{
- struct pidfh *pfh;
- const char *pidfile, *servconfdir, *sockpath;
- pid_t otherpid;
- int ch, debug, lqlen;
- bool foreground;
-
- pjdlog_init(PJDLOG_MODE_STD);
-
- debug = 0;
- foreground = false;
- lqlen = SOMAXCONN;
- pidfile = CASPERD_PIDFILE;
- servconfdir = CASPERD_SERVCONFDIR;
- sockpath = CASPERD_SOCKPATH;
-
- while ((ch = getopt(argc, argv, "D:Fhl:P:S:v")) != -1) {
- switch (ch) {
- case 'D':
- servconfdir = optarg;
- break;
- case 'F':
- foreground = true;
- break;
- case 'l':
- lqlen = strtol(optarg, NULL, 0);
- if (lqlen < 1)
- lqlen = SOMAXCONN;
- break;
- case 'P':
- pidfile = optarg;
- break;
- case 'S':
- sockpath = optarg;
- break;
- case 'v':
- debug++;
- break;
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 0)
- usage();
-
- if (!foreground)
- pjdlog_mode_set(PJDLOG_MODE_SYSLOG);
- pjdlog_prefix_set("(casperd) ");
- pjdlog_debug_set(debug);
-
- if (zygote_init() < 0)
- pjdlog_exit(1, "Unable to create zygote process");
-
- pfh = pidfile_open(pidfile, 0600, &otherpid);
- if (pfh == NULL) {
- if (errno == EEXIST) {
- pjdlog_exitx(1, "casperd already running, pid: %jd.",
- (intmax_t)otherpid);
- }
- pjdlog_errno(LOG_WARNING, "Cannot open or create pidfile %s",
- pidfile);
- }
-
- if (!foreground) {
- if (daemon(0, 0) == -1) {
- KEEP_ERRNO((void)pidfile_remove(pfh));
- pjdlog_exit(1, "Unable to go into background");
- }
- }
-
- /* Write PID to a file. */
- if (pidfile_write(pfh) == -1) {
- pjdlog_errno(LOG_WARNING, "Unable to write to pidfile %s",
- pidfile);
- } else {
- pjdlog_debug(1, "PID stored in %s.", pidfile);
- }
-
- /*
- * Register core services.
- */
- service_register_core();
- /*
- * Register external services.
- */
- service_register_external(servconfdir);
-
- /*
- * Wait for connections.
- */
- main_loop(lqlen, sockpath, pfh);
-}
diff --git a/sbin/casperd/zygote.c b/sbin/casperd/zygote.c
deleted file mode 100644
index 5bc9396..0000000
--- a/sbin/casperd/zygote.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*-
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Pawel Jakub Dawidek under sponsorship from
- * the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/capsicum.h>
-#include <sys/procdesc.h>
-#include <sys/socket.h>
-#include <sys/nv.h>
-
-#include <assert.h>
-#include <err.h>
-#include <errno.h>
-#include <paths.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include <libcapsicum.h>
-#include <libcapsicum_impl.h>
-#include <pjdlog.h>
-
-#include "zygote.h"
-
-/* Zygote info. */
-static int zygote_sock = -1;
-
-static void
-stdnull(void)
-{
- int fd;
-
- fd = open(_PATH_DEVNULL, O_RDWR);
- if (fd == -1)
- errx(1, "Unable to open %s", _PATH_DEVNULL);
-
- if (setsid() == -1)
- errx(1, "Unable to detach from session");
-
- if (dup2(fd, STDIN_FILENO) == -1)
- errx(1, "Unable to cover stdin");
- if (dup2(fd, STDOUT_FILENO) == -1)
- errx(1, "Unable to cover stdout");
- if (dup2(fd, STDERR_FILENO) == -1)
- errx(1, "Unable to cover stderr");
-
- close(fd);
-}
-
-int
-zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp)
-{
- nvlist_t *nvl;
- int error;
-
- if (zygote_sock == -1) {
- /* Zygote didn't start. */
- errno = ENXIO;
- return (-1);
- }
-
- nvl = nvlist_create(0);
- nvlist_add_number(nvl, "func", (uint64_t)(uintptr_t)func);
- nvl = nvlist_xfer(zygote_sock, nvl, 0);
- if (nvl == NULL)
- return (-1);
- if (nvlist_exists_number(nvl, "error")) {
- error = (int)nvlist_get_number(nvl, "error");
- nvlist_destroy(nvl);
- errno = error;
- return (-1);
- }
-
- *chanfdp = nvlist_take_descriptor(nvl, "chanfd");
- *procfdp = nvlist_take_descriptor(nvl, "procfd");
-
- nvlist_destroy(nvl);
- return (0);
-}
-
-/*
- * This function creates sandboxes on-demand whoever has access to it via
- * 'sock' socket. Function sends two descriptors to the caller: process
- * descriptor of the sandbox and socket pair descriptor for communication
- * between sandbox and its owner.
- */
-static void
-zygote_main(int sock)
-{
- int error, fd, procfd;
- int chanfd[2];
- nvlist_t *nvlin, *nvlout;
- zygote_func_t *func;
- pid_t pid;
-
- assert(sock > STDERR_FILENO);
-
- setproctitle("zygote");
-
- if (pjdlog_mode_get() != PJDLOG_MODE_STD)
- stdnull();
- for (fd = STDERR_FILENO + 1; fd < sock; fd++)
- close(fd);
- closefrom(sock + 1);
-
- for (;;) {
- nvlin = nvlist_recv(sock, 0);
- if (nvlin == NULL) {
- if (errno == ENOTCONN) {
- /* Casperd exited. */
- exit(0);
- }
- continue;
- }
- func = (zygote_func_t *)(uintptr_t)nvlist_get_number(nvlin,
- "func");
- nvlist_destroy(nvlin);
-
- /*
- * Someone is requesting a new process, create one.
- */
- procfd = -1;
- chanfd[0] = -1;
- chanfd[1] = -1;
- error = 0;
- if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0,
- chanfd) == -1) {
- error = errno;
- goto send;
- }
- pid = pdfork(&procfd, 0);
- switch (pid) {
- case -1:
- /* Failure. */
- error = errno;
- break;
- case 0:
- /* Child. */
- close(sock);
- close(chanfd[0]);
- func(chanfd[1]);
- /* NOTREACHED */
- exit(1);
- default:
- /* Parent. */
- close(chanfd[1]);
- break;
- }
-send:
- nvlout = nvlist_create(0);
- if (error != 0) {
- nvlist_add_number(nvlout, "error", (uint64_t)error);
- if (chanfd[0] >= 0)
- close(chanfd[0]);
- if (procfd >= 0)
- close(procfd);
- } else {
- nvlist_move_descriptor(nvlout, "chanfd", chanfd[0]);
- nvlist_move_descriptor(nvlout, "procfd", procfd);
- }
- (void)nvlist_send(sock, nvlout);
- nvlist_destroy(nvlout);
- }
- /* NOTREACHED */
-}
-
-int
-zygote_init(void)
-{
- int serrno, sp[2];
- pid_t pid;
-
- if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, sp) == -1)
- return (-1);
-
- pid = fork();
- switch (pid) {
- case -1:
- /* Failure. */
- serrno = errno;
- close(sp[0]);
- close(sp[1]);
- errno = serrno;
- return (-1);
- case 0:
- /* Child. */
- close(sp[0]);
- zygote_main(sp[1]);
- /* NOTREACHED */
- abort();
- default:
- /* Parent. */
- zygote_sock = sp[0];
- close(sp[1]);
- return (0);
- }
- /* NOTREACHED */
-}
diff --git a/sbin/casperd/zygote.h b/sbin/casperd/zygote.h
deleted file mode 100644
index 4c9c771..0000000
--- a/sbin/casperd/zygote.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Pawel Jakub Dawidek under sponsorship from
- * the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _ZYGOTE_H_
-#define _ZYGOTE_H_
-
-typedef void zygote_func_t(int);
-
-int zygote_init(void);
-int zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp);
-
-#endif /* !_ZYGOTE_H_ */
OpenPOWER on IntegriCloud