Пример #1
0
static void
ioctl_tests_send_0(int sock)
{
	unsigned long cmds[2];
	int fd;

	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
	CHECK(descriptor_send(sock, fd) == 0);
	CHECK(close(fd) == 0);

	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
	cmds[0] = FIOCLEX;
	cmds[1] = FIONCLEX;
	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
	CHECK(descriptor_send(sock, fd) == 0);
	CHECK(close(fd) == 0);

	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
	cmds[0] = FIOCLEX;
	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
	CHECK(descriptor_send(sock, fd) == 0);
	CHECK(close(fd) == 0);

	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
	CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
	CHECK(descriptor_send(sock, fd) == 0);
	CHECK(close(fd) == 0);
}
Пример #2
0
static void
ioctl_tests_2(int fd)
{
	unsigned long cmds[2];

	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);

	cmds[0] = FIOCLEX;
	cmds[1] = FIONCLEX;
	errno = 0;
	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
	cmds[0] = FIOCLEX;
	errno = 0;
	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);

	CHECK(fcntl(fd, F_GETFD) == 0);
	errno = 0;
	CHECK(ioctl(fd, FIOCLEX) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(fcntl(fd, F_GETFD) == 0);
	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	errno = 0;
	CHECK(ioctl(fd, FIONCLEX) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	CHECK(fcntl(fd, F_SETFD, 0) == 0);
	CHECK(fcntl(fd, F_GETFD) == 0);
}
Пример #3
0
/*
 * XXX: I CANT INTO LATIN
 */
static void
capsicate(struct connection *conn)
{
    int error;
    cap_rights_t rights;
#ifdef ICL_KERNEL_PROXY
    const unsigned long cmds[] = { ISCSIDCONNECT, ISCSIDSEND, ISCSIDRECEIVE,
                                   ISCSIDHANDOFF, ISCSIDFAIL, ISCSISADD, ISCSISREMOVE
                                 };
#else
    const unsigned long cmds[] = { ISCSIDHANDOFF, ISCSIDFAIL, ISCSISADD,
                                   ISCSISREMOVE
                                 };
#endif

    cap_rights_init(&rights, CAP_IOCTL);
    error = cap_rights_limit(conn->conn_iscsi_fd, &rights);
    if (error != 0 && errno != ENOSYS)
        log_err(1, "cap_rights_limit");

    error = cap_ioctls_limit(conn->conn_iscsi_fd, cmds,
                             sizeof(cmds) / sizeof(cmds[0]));
    if (error != 0 && errno != ENOSYS)
        log_err(1, "cap_ioctls_limit");

    error = cap_enter();
    if (error != 0 && errno != ENOSYS)
        log_err(1, "cap_enter");

    if (cap_sandboxed())
        log_debugx("Capsicum capability mode enabled");
    else
        log_warnx("Capsicum capability mode not supported");
}
Пример #4
0
int
uart_set_backend(struct uart_softc *sc, const char *opts)
{
	int retval;
#ifndef WITHOUT_CAPSICUM
	cap_rights_t rights;
	cap_ioctl_t cmds[] = { TIOCGETA, TIOCSETA, TIOCGWINSZ };
#endif

	retval = -1;

	if (opts == NULL)
		return (0);

	if (strcmp("stdio", opts) == 0) {
		if (!uart_stdio) {
			sc->tty.fd = STDIN_FILENO;
			sc->tty.opened = true;
			uart_stdio = true;
			retval = 0;
		}
	} else if (uart_tty_backend(sc, opts) == 0) {
		retval = 0;
	}

	/* Make the backend file descriptor non-blocking */
	if (retval == 0)
		retval = fcntl(sc->tty.fd, F_SETFL, O_NONBLOCK);

#ifndef WITHOUT_CAPSICUM
	cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ, CAP_WRITE);
	if (cap_rights_limit(sc->tty.fd, &rights) == -1 && errno != ENOSYS)
		errx(EX_OSERR, "Unable to apply rights for sandbox");
	if (cap_ioctls_limit(sc->tty.fd, cmds, nitems(cmds)) == -1 && errno != ENOSYS)
		errx(EX_OSERR, "Unable to apply rights for sandbox");
	if (!uart_stdio) {
		if (caph_limit_stdin() == -1 && errno != ENOSYS)
			errx(EX_OSERR, "Unable to apply rights for sandbox");
	}
#endif

	if (retval == 0)
		uart_opentty(sc);

	return (retval);
}
Пример #5
0
static void
ioctl_tests_0(int fd)
{
	unsigned long cmds[2];

	CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);

	CHECK(fcntl(fd, F_GETFD) == 0);
	CHECK(ioctl(fd, FIOCLEX) == 0);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	CHECK(ioctl(fd, FIONCLEX) == 0);
	CHECK(fcntl(fd, F_GETFD) == 0);

	cmds[0] = FIOCLEX;
	cmds[1] = FIONCLEX;
	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
	cmds[0] = cmds[1] = 0;
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
	CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
	    (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
	cmds[0] = FIOCLEX;
	cmds[1] = FIONCLEX;
	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
	cmds[0] = cmds[1] = 0;
	CHECK(cap_ioctls_get(fd, cmds, 1) == nitems(cmds));
	CHECK(cmds[0] == FIOCLEX || cmds[0] == FIONCLEX);
	CHECK(cmds[1] == 0);

	CHECK(fcntl(fd, F_GETFD) == 0);
	CHECK(ioctl(fd, FIOCLEX) == 0);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	CHECK(ioctl(fd, FIONCLEX) == 0);
	CHECK(fcntl(fd, F_GETFD) == 0);

	cmds[0] = FIOCLEX;
	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
	cmds[0] = cmds[1] = 0;
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
	CHECK(cmds[0] == FIOCLEX);
	cmds[0] = FIOCLEX;
	cmds[1] = FIONCLEX;
	errno = 0;
	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
	CHECK(errno == ENOTCAPABLE);
	cmds[0] = cmds[1] = 0;
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
	CHECK(cmds[0] == FIOCLEX);

	CHECK(fcntl(fd, F_GETFD) == 0);
	CHECK(ioctl(fd, FIOCLEX) == 0);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	errno = 0;
	CHECK(ioctl(fd, FIONCLEX) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	CHECK(fcntl(fd, F_SETFD, 0) == 0);
	CHECK(fcntl(fd, F_GETFD) == 0);

	CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
	cmds[0] = FIOCLEX;
	errno = 0;
	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);

	CHECK(fcntl(fd, F_GETFD) == 0);
	errno = 0;
	CHECK(ioctl(fd, FIOCLEX) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(fcntl(fd, F_GETFD) == 0);
	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	errno = 0;
	CHECK(ioctl(fd, FIONCLEX) == -1);
	CHECK(errno == ENOTCAPABLE);
	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
	CHECK(fcntl(fd, F_SETFD, 0) == 0);
	CHECK(fcntl(fd, F_GETFD) == 0);
}
Пример #6
0
int
main (int argc, char *argv[])
{
	wchar_t *tprev, *tthis;
	FILE *ifp, *ofp;
	int ch, comp;
	size_t prevbuflen, thisbuflen, b1;
	char *prevline, *thisline, *p;
	const char *ifn;
	cap_rights_t rights;

	(void) setlocale(LC_ALL, "");

	obsolete(argv);
	while ((ch = getopt(argc, argv, "cdif:s:u")) != -1)
		switch (ch) {
		case 'c':
			cflag = 1;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'i':
			iflag = 1;
			break;
		case 'f':
			numfields = strtol(optarg, &p, 10);
			if (numfields < 0 || *p)
				errx(1, "illegal field skip value: %s", optarg);
			break;
		case 's':
			numchars = strtol(optarg, &p, 10);
			if (numchars < 0 || *p)
				errx(1, "illegal character skip value: %s", optarg);
			break;
		case 'u':
			uflag = 1;
			break;
		case '?':
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	/* If no flags are set, default is -d -u. */
	if (cflag) {
		if (dflag || uflag)
			usage();
	} else if (!dflag && !uflag)
		dflag = uflag = 1;

	if (argc > 2)
		usage();

	ifp = stdin;
	ifn = "stdin";
	ofp = stdout;
	if (argc > 0 && strcmp(argv[0], "-") != 0)
		ifp = file(ifn = argv[0], "r");
	cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
	if (cap_rights_limit(fileno(ifp), &rights) < 0 && errno != ENOSYS)
		err(1, "unable to limit rights for %s", ifn);
	cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
	if (argc > 1)
		ofp = file(argv[1], "w");
	else
		cap_rights_set(&rights, CAP_IOCTL);
	if (cap_rights_limit(fileno(ofp), &rights) < 0 && errno != ENOSYS) {
		err(1, "unable to limit rights for %s",
		    argc > 1 ? argv[1] : "stdout");
	}
	if (cap_rights_is_set(&rights, CAP_IOCTL)) {
		unsigned long cmd;

		cmd = TIOCGETA; /* required by isatty(3) in printf(3) */

		if (cap_ioctls_limit(fileno(ofp), &cmd, 1) < 0 &&
		    errno != ENOSYS) {
			err(1, "unable to limit ioctls for %s",
			    argc > 1 ? argv[1] : "stdout");
		}
	}

	strerror_init();
	if (cap_enter() < 0 && errno != ENOSYS)
		err(1, "unable to enter capability mode");

	prevbuflen = thisbuflen = 0;
	prevline = thisline = NULL;

	if (getline(&prevline, &prevbuflen, ifp) < 0) {
		if (ferror(ifp))
			err(1, "%s", ifn);
		exit(0);
	}
	tprev = convert(prevline);

	if (!cflag && uflag && dflag)
		show(ofp, prevline);

	tthis = NULL;
	while (getline(&thisline, &thisbuflen, ifp) >= 0) {
		if (tthis != NULL)
			free(tthis);
		tthis = convert(thisline);

		if (tthis == NULL && tprev == NULL)
			comp = inlcmp(thisline, prevline);
		else if (tthis == NULL || tprev == NULL)
			comp = 1;
		else
			comp = wcscoll(tthis, tprev);

		if (comp) {
			/* If different, print; set previous to new value. */
			if (cflag || !dflag || !uflag)
				show(ofp, prevline);
			p = prevline;
			b1 = prevbuflen;
			prevline = thisline;
			prevbuflen = thisbuflen;
			if (tprev != NULL)
				free(tprev);
			tprev = tthis;
			if (!cflag && uflag && dflag)
				show(ofp, prevline);
			thisline = p;
			thisbuflen = b1;
			tthis = NULL;
			repeats = 0;
		} else
			++repeats;
	}
	if (ferror(ifp))
		err(1, "%s", ifn);
	if (cflag || !dflag || !uflag)
		show(ofp, prevline);
	exit(0);
}
Пример #7
0
int
drop_privs(const struct hast_resource *res)
{
    char jailhost[sizeof(res->hr_name) * 2];
    struct jail jailst;
    struct passwd *pw;
    uid_t ruid, euid, suid;
    gid_t rgid, egid, sgid;
    gid_t gidset[1];
    bool capsicum, jailed;

    /*
     * According to getpwnam(3) we have to clear errno before calling the
     * function to be able to distinguish between an error and missing
     * entry (with is not treated as error by getpwnam(3)).
     */
    errno = 0;
    pw = getpwnam(HAST_USER);
    if (pw == NULL) {
        if (errno != 0) {
            pjdlog_errno(LOG_ERR,
                         "Unable to find info about '%s' user", HAST_USER);
            return (-1);
        } else {
            pjdlog_error("'%s' user doesn't exist.", HAST_USER);
            errno = ENOENT;
            return (-1);
        }
    }

    bzero(&jailst, sizeof(jailst));
    jailst.version = JAIL_API_VERSION;
    jailst.path = pw->pw_dir;
    if (res == NULL) {
        (void)snprintf(jailhost, sizeof(jailhost), "hastctl");
    } else {
        (void)snprintf(jailhost, sizeof(jailhost), "hastd: %s (%s)",
                       res->hr_name, role2str(res->hr_role));
    }
    jailst.hostname = jailhost;
    jailst.jailname = NULL;
    jailst.ip4s = 0;
    jailst.ip4 = NULL;
    jailst.ip6s = 0;
    jailst.ip6 = NULL;
    if (jail(&jailst) >= 0) {
        jailed = true;
    } else {
        jailed = false;
        pjdlog_errno(LOG_WARNING,
                     "Unable to jail to directory to %s", pw->pw_dir);
        if (chroot(pw->pw_dir) == -1) {
            pjdlog_errno(LOG_ERR,
                         "Unable to change root directory to %s",
                         pw->pw_dir);
            return (-1);
        }
    }
    PJDLOG_VERIFY(chdir("/") == 0);
    gidset[0] = pw->pw_gid;
    if (setgroups(1, gidset) == -1) {
        pjdlog_errno(LOG_ERR, "Unable to set groups to gid %u",
                     (unsigned int)pw->pw_gid);
        return (-1);
    }
    if (setgid(pw->pw_gid) == -1) {
        pjdlog_errno(LOG_ERR, "Unable to set gid to %u",
                     (unsigned int)pw->pw_gid);
        return (-1);
    }
    if (setuid(pw->pw_uid) == -1) {
        pjdlog_errno(LOG_ERR, "Unable to set uid to %u",
                     (unsigned int)pw->pw_uid);
        return (-1);
    }

#ifdef HAVE_CAPSICUM
    capsicum = (cap_enter() == 0);
    if (!capsicum) {
        pjdlog_common(LOG_DEBUG, 1, errno,
                      "Unable to sandbox using capsicum");
    } else if (res != NULL) {
        cap_rights_t rights;
        static const unsigned long geomcmds[] = {
            DIOCGDELETE,
            DIOCGFLUSH
        };

        PJDLOG_ASSERT(res->hr_role == HAST_ROLE_PRIMARY ||
                      res->hr_role == HAST_ROLE_SECONDARY);

        cap_rights_init(&rights, CAP_FLOCK, CAP_IOCTL, CAP_PREAD,
                        CAP_PWRITE);
        if (cap_rights_limit(res->hr_localfd, &rights) == -1) {
            pjdlog_errno(LOG_ERR,
                         "Unable to limit capability rights on local descriptor");
        }
        if (cap_ioctls_limit(res->hr_localfd, geomcmds,
                             sizeof(geomcmds) / sizeof(geomcmds[0])) == -1) {
            pjdlog_errno(LOG_ERR,
                         "Unable to limit allowed GEOM ioctls");
        }

        if (res->hr_role == HAST_ROLE_PRIMARY) {
            static const unsigned long ggatecmds[] = {
                G_GATE_CMD_MODIFY,
                G_GATE_CMD_START,
                G_GATE_CMD_DONE,
                G_GATE_CMD_DESTROY
            };

            cap_rights_init(&rights, CAP_IOCTL);
            if (cap_rights_limit(res->hr_ggatefd, &rights) == -1) {
                pjdlog_errno(LOG_ERR,
                             "Unable to limit capability rights to CAP_IOCTL on ggate descriptor");
            }
            if (cap_ioctls_limit(res->hr_ggatefd, ggatecmds,
                                 sizeof(ggatecmds) / sizeof(ggatecmds[0])) == -1) {
                pjdlog_errno(LOG_ERR,
                             "Unable to limit allowed ggate ioctls");
            }
        }
    }
#else
    capsicum = false;
#endif

    /*
     * Better be sure that everything succeeded.
     */
    PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0);
    PJDLOG_VERIFY(ruid == pw->pw_uid);
    PJDLOG_VERIFY(euid == pw->pw_uid);
    PJDLOG_VERIFY(suid == pw->pw_uid);
    PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0);
    PJDLOG_VERIFY(rgid == pw->pw_gid);
    PJDLOG_VERIFY(egid == pw->pw_gid);
    PJDLOG_VERIFY(sgid == pw->pw_gid);
    PJDLOG_VERIFY(getgroups(0, NULL) == 1);
    PJDLOG_VERIFY(getgroups(1, gidset) == 1);
    PJDLOG_VERIFY(gidset[0] == pw->pw_gid);

    pjdlog_debug(1,
                 "Privileges successfully dropped using %s%s+setgid+setuid.",
                 capsicum ? "capsicum+" : "", jailed ? "jail" : "chroot");

    return (0);
}
Пример #8
0
static struct vmctx *
do_open(const char *vmname)
{
	struct vmctx *ctx;
	int error;
	bool reinit, romboot;
#ifndef WITHOUT_CAPSICUM
	cap_rights_t rights;
	const cap_ioctl_t *cmds;	
	size_t ncmds;
#endif

	reinit = romboot = false;

	if (lpc_bootrom())
		romboot = true;

	error = vm_create(vmname);
	if (error) {
		if (errno == EEXIST) {
			if (romboot) {
				reinit = true;
			} else {
				/*
				 * The virtual machine has been setup by the
				 * userspace bootloader.
				 */
			}
		} else {
			perror("vm_create");
			exit(1);
		}
	} else {
		if (!romboot) {
			/*
			 * If the virtual machine was just created then a
			 * bootrom must be configured to boot it.
			 */
			fprintf(stderr, "virtual machine cannot be booted\n");
			exit(1);
		}
	}

	ctx = vm_open(vmname);
	if (ctx == NULL) {
		perror("vm_open");
		exit(1);
	}

#ifndef WITHOUT_CAPSICUM
	cap_rights_init(&rights, CAP_IOCTL, CAP_MMAP_RW);
	if (cap_rights_limit(vm_get_device_fd(ctx), &rights) == -1 &&
	    errno != ENOSYS)
		errx(EX_OSERR, "Unable to apply rights for sandbox");
	vm_get_ioctls(&ncmds);
	cmds = vm_get_ioctls(NULL);
	if (cmds == NULL)
		errx(EX_OSERR, "out of memory");
	if (cap_ioctls_limit(vm_get_device_fd(ctx), cmds, ncmds) == -1 &&
	    errno != ENOSYS)
		errx(EX_OSERR, "Unable to apply rights for sandbox");
	free((cap_ioctl_t *)cmds);
#endif
 
	if (reinit) {
		error = vm_reinit(ctx);
		if (error) {
			perror("vm_reinit");
			exit(1);
		}
	}
	error = vm_set_topology(ctx, sockets, cores, threads, maxcpus);
	if (error)
		errx(EX_OSERR, "vm_set_topology");
	return (ctx);
}