Page MenuHomeFreeBSD

D15289.1791052111.diff
No OneTemporary

Size
26 KB
Referenced Files
None
Subscribers
None

D15289.1791052111.diff

Index: lib/libcasper/services/Makefile
===================================================================
--- lib/libcasper/services/Makefile
+++ lib/libcasper/services/Makefile
@@ -4,6 +4,7 @@
SUBDIR= cap_dns
SUBDIR+= cap_grp
+SUBDIR+= cap_jail
SUBDIR+= cap_pwd
SUBDIR+= cap_random
SUBDIR+= cap_sysctl
Index: lib/libcasper/services/cap_jail/Makefile
===================================================================
--- /dev/null
+++ lib/libcasper/services/cap_jail/Makefile
@@ -0,0 +1,28 @@
+# $FreeBSD$
+
+SHLIBDIR?= /lib/casper
+
+.include <src.opts.mk>
+
+PACKAGE=libcasper
+
+SHLIB_MAJOR= 1
+INCSDIR?= ${INCLUDEDIR}/casper
+
+.if ${MK_CASPER} != "no"
+SHLIB= cap_jail
+
+SRCS= cap_jail.c
+.endif
+
+INCS= cap_jail.h
+
+LIBADD= nv
+
+CFLAGS+=-I${.CURDIR}
+
+MAN+= cap_jail.3
+
+MLINKS+=cap_jail.3 cap_jail_get.3
+MLINKS+=cap_jail.3 libcap_jail.3
+.include <bsd.lib.mk>
Index: lib/libcasper/services/cap_jail/cap_jail.h
===================================================================
--- /dev/null
+++ lib/libcasper/services/cap_jail/cap_jail.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2018 Stefan Grundmann
+ * All rights reserved.
+ *
+ * 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 _CAP_JAIL_H_
+#define _CAP_JAIL_H_
+
+#ifdef HAVE_CASPER
+#define WITH_CASPER
+#endif
+
+#ifdef WITH_CASPER
+int cap_jail_get(cap_channel_t *chan, struct iovec *iov, u_int niov,
+ int flags);
+#else
+#define cap_jail_get(chan, iov, niov, flags) \
+ jail_get(iov, niov, flags);
+#endif
+
+#endif /* !_CAP_JAIL_H_ */
Index: lib/libcasper/services/cap_jail/cap_jail.3
===================================================================
--- /dev/null
+++ lib/libcasper/services/cap_jail/cap_jail.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2018 Stefan Grundmann
+.\" All rights reserved.
+.\"
+.\" 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 May 11, 2018
+.Dt CAP_JAIL 3
+.Os
+.Sh NAME
+.Nm cap_jail
+.Nd "library for getting jail information in capability mode"
+.Sh LIBRARY
+.Lb libcap_jail
+.Sh SYNOPSIS
+.In sys/uio.h
+.In libcasper.h
+.In casper/cap_jail.h
+.Ft int
+.Fn cap_jail_get "cap_channel_t *chan" " struct iovec *iov" " u_int niov" " int flags"
+.Sh DESCRIPTION
+The function
+.Fn cap_jail_get
+is equivalent to
+.Xr jail_get 2
+except that the connection to the
+.Nm system.jail
+service needs to be provided.
+.Sh EXAMPLES
+The following example first opens a capability to casper and then uses this
+capability to create the
+.Nm system.jail
+casper service and uses it to get the
+.Dv jid
+and
+.Dv name
+of the first jail
+.Bd -literal
+cap_channel_t *capcas, *capjail;
+struct iovec iov[4];
+char name[256];
+int jid;
+
+capcas = cap_init();
+if (capcas == NULL)
+ err(1, "Unable to contact Casper");
+
+/* Enter capability mode sandbox. */
+if (cap_enter() < 0 && errno != ENOSYS)
+ err(1, "Unable to enter capability mode");
+
+/* Use Casper capability to create capability to the system.jail service. */
+capjail = cap_service_open(capcas, "system.jail");
+if (capjail == NULL)
+ err(1, "Unable to open system.jail service");
+
+/* Close Casper capability, we don't need it anymore. */
+cap_close(capcas);
+
+/* prepare iovs */
+jid = 0;
+iov[0].iov_base = __DECONST(char *, "lastjid");
+iov[0].iov_len = strlen(iov[0].iov_base) + 1;
+iov[1].iov_base = &jid;
+iov[1].iov_len = sizeof(jid);
+iov[2].iov_base = __DECONST(char *, "name");
+iov[2].iov_len = strlen(iov[2].iov_base) + 1;
+iov[3].iov_base = name;
+iov[3].iov_len = sizeof(name);
+
+/* Fetch values */
+jid = cap_jail_get(capjail, iov, 4, 0);
+
+if (jid < 0 && errno != ENOENT)
+ err(1, "Unable to get jail information");
+if (jid > 0)
+ printf("jid = %d name = %s\\n", jid, name);
+else
+ printf("no jails\\n");
+
+cap_close(capjail);
+.Ed
+.Sh SEE ALSO
+.Xr cap_enter 2 ,
+.Xr jail_get 2 ,
+.Xr capsicum 4 ,
+.Sh AUTHORS
+The
+.Nm cap_jail
+service and this manual page were written by
+.An Stefan Grundmann
Index: lib/libcasper/services/cap_jail/cap_jail.c
===================================================================
--- /dev/null
+++ lib/libcasper/services/cap_jail/cap_jail.c
@@ -0,0 +1,227 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Stefan Grundmann
+ * All rights reserved.
+ *
+ * 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/uio.h>
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/cnv.h>
+#include <sys/dnv.h>
+#include <sys/nv.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libcasper.h>
+#include <libcasper_service.h>
+
+#include "cap_jail.h"
+
+static nvlist_t *iovs_to_nvl(struct iovec* iov, size_t niov, size_t *bs);
+static int nvl_to_iovs(struct iovec* iov, size_t niov, const nvlist_t* nvl);
+
+int
+cap_jail_get(cap_channel_t *chan, struct iovec *iov, u_int niov, int flags)
+{
+ nvlist_t *nvl;
+ size_t bs;
+ int ret;
+
+ nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
+ nvlist_add_string(nvl, "cmd", "jail_get");
+ nvlist_add_number(nvl, "flags", flags);
+ nvlist_add_number(nvl, "niov", niov);
+
+ nvlist_move_nvlist(nvl, "iovs", iovs_to_nvl(iov, niov, &bs));
+ nvlist_add_number(nvl, "bs", bs);
+
+ nvl = cap_xfer_nvlist(chan, nvl);
+ if (nvl == NULL)
+ return (-1);
+
+ if (nvlist_get_number(nvl, "error") != 0) {
+ errno = (int)nvlist_get_number(nvl, "error");
+ nvlist_destroy(nvl);
+ return (-1);
+ }
+
+ ret = (int)nvlist_get_number(nvl, "ret");
+
+ if (nvl_to_iovs(iov, niov, nvlist_get_nvlist(nvl, "iovs")) != 0) {
+ nvlist_destroy(nvl);
+ return (-1);
+ }
+
+ nvlist_destroy(nvl);
+ return (ret);
+}
+
+static int
+nvl_to_iovs(struct iovec* iov, size_t niov, const nvlist_t* nvl)
+{
+ const char *name;
+ const void *val;
+ void *cookie;
+ size_t i, len;
+ int type;
+
+ cookie = NULL;
+ for (i=0; i < niov; i++) {
+ if ((name = nvlist_next(nvl, &type, &cookie)) == NULL)
+ return (-1);
+
+ switch (type) {
+ case NV_TYPE_NUMBER:
+ iov[i].iov_len = 0;
+ break;
+ case NV_TYPE_BINARY:
+ val = cnvlist_get_binary(cookie, &len);
+ if (len > iov[i].iov_len)
+ return (-1);
+ if (memcmp(iov[i].iov_base, val, len) != 0)
+ memcpy(iov[i].iov_base, val, len);
+ break;
+ default:
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Service functions.
+ */
+
+static nvlist_t*
+iovs_to_nvl(struct iovec* iov, size_t niov, size_t *bs)
+{
+ nvlist_t *nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
+ size_t i, size;
+
+ size = 0;
+ for (i=0; i < niov; i++) {
+ if (iov[i].iov_len == 0)
+ nvlist_add_number(nvl, "NULL", 0);
+ else {
+ nvlist_add_binary(nvl, "iov",
+ iov[i].iov_base, iov[i].iov_len);
+ size += iov[i].iov_len;
+ }
+ }
+
+ if (bs != NULL)
+ *bs = size;
+
+ return (nvl);
+}
+
+static int
+nvl_to_iovs_s(struct iovec* iov, size_t niov, const nvlist_t* nvl,
+ uint8_t* buf, size_t bs)
+{
+ const char *name;
+ const void *val;
+ void *cookie;
+ size_t i, len, offset;
+ int type;
+
+ offset = 0;
+ cookie = NULL;
+ for (i=0; i < niov; i++) {
+ if ((name = nvlist_next(nvl, &type, &cookie)) == NULL)
+ return (-1);
+ switch (type) {
+ case NV_TYPE_NUMBER:
+ iov[i].iov_base = 0;
+ iov[i].iov_len = 0;
+ break;
+ case NV_TYPE_BINARY:
+ val = cnvlist_get_binary(cookie, &len);
+ if (offset + len > bs)
+ return (-1);
+ memcpy(buf + offset, val, len);
+ iov[i].iov_base = buf + offset;
+ iov[i].iov_len = len;
+ offset += len;
+ break;
+ default:
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+jail_command(const char *cmd, const nvlist_t *limits __unused,
+ nvlist_t *nvlin, nvlist_t *nvlout)
+{
+ const nvlist_t *nvliov;
+ struct iovec *iov;
+ uint8_t *buf;
+ size_t bs, niov;
+ int flags, r, ret;
+
+ if (strcmp(cmd, "jail_get") != 0)
+ return (EINVAL);
+
+ flags = (int)dnvlist_get_number(nvlin, "flags", 0);
+ niov = (size_t)dnvlist_get_number(nvlin, "niov", 0);
+ bs = (size_t)dnvlist_get_number(nvlin, "bs", 0);
+ nvliov = dnvlist_get_nvlist(nvlin, "iovs", NULL);
+
+ r = 0;
+ buf = NULL;
+ if ((iov = malloc(niov * sizeof(struct iovec))) == NULL ||
+ (buf = malloc(bs)) == NULL) {
+ r = errno;
+ goto error;
+ }
+ if (nvl_to_iovs_s(iov, niov, nvliov, buf, bs) < 0) {
+ r = EINVAL;
+ goto error;
+ }
+ if ((ret = jail_get(iov, niov, flags)) < 0) {
+ r = errno;
+ goto error;
+ }
+ nvlist_add_number(nvlout, "ret", ret);
+ nvlist_add_nvlist(nvlout, "iovs", iovs_to_nvl(iov, niov, NULL));
+ error:
+ free(buf);
+ free(iov);
+ return (r);
+}
+
+CREATE_SERVICE("system.jail", NULL, jail_command,
+ CASPER_SERVICE_NO_UNIQ_LIMITS);
Index: lib/libcasper/services/cap_sysctl/cap_sysctl.h
===================================================================
--- lib/libcasper/services/cap_sysctl/cap_sysctl.h
+++ lib/libcasper/services/cap_sysctl/cap_sysctl.h
@@ -44,9 +44,13 @@
#ifdef WITH_CASPER
int cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen);
+int cap_sysctl(cap_channel_t *chan, const int *name, u_int namelen,
+ void *oldp, size_t *oldlenp, const void *newp, size_t newlen);
#else
#define cap_sysctlbyname(chan, name, oldp, oldlenp, newp, newlen) \
sysctlbyname(name, oldp, oldlenp, newp, newlen)
+#define cap_sysctl(chan, name, namelen, oldp, oldlenp, newp, newlen) \
+ sysctl(name, namelen, oldp, oldlenp, newp, newlen)
#endif
#endif /* !_CAP_SYSCTL_H_ */
Index: lib/libcasper/services/cap_sysctl/cap_sysctl.3
===================================================================
--- lib/libcasper/services/cap_sysctl/cap_sysctl.3
+++ lib/libcasper/services/cap_sysctl/cap_sysctl.3
@@ -38,11 +38,17 @@
.In casper/cap_sysctl.h
.Ft int
.Fn cap_sysctlbyname "cap_channel_t *chan" " const char *name" " void *oldp" " size_t *oldlenp" " const void *newp" " size_t newlen"
+.Ft int
+.Fn cap_sysctl "cap_channel_t *chan" " int *name" " u_int namelen" " void *oldp" " size_t *oldlenp" " const void *newp" " size_t newlen"
.Sh DESCRIPTION
-The function
+The functions
.Fn cap_sysctlbyname
-is equivalent to
+and
+.Fn cap_sysctl
+are equivalent to
.Xr sysctlbyname 3
+and
+.Xr sysctl 3
except that the connection to the
.Nm system.sysctl
service needs to be provided.
@@ -129,6 +135,7 @@
.Sh SEE ALSO
.Xr cap_enter 2 ,
.Xr err 3 ,
+.Xr sysctl 3 ,
.Xr sysctlbyname 3 ,
.Xr capsicum 4 ,
.Xr nv 9
Index: lib/libcasper/services/cap_sysctl/cap_sysctl.c
===================================================================
--- lib/libcasper/services/cap_sysctl/cap_sysctl.c
+++ lib/libcasper/services/cap_sysctl/cap_sysctl.c
@@ -34,6 +34,7 @@
#include <sys/types.h>
#include <sys/sysctl.h>
+#include <sys/dnv.h>
#include <sys/nv.h>
#include <assert.h>
@@ -46,6 +47,8 @@
#include "cap_sysctl.h"
+static nvlist_t *sysctl_mibs = NULL;
+
int
cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen)
@@ -93,6 +96,53 @@
return (0);
}
+int
+cap_sysctl(cap_channel_t *chan, const int *name, u_int namelen,
+ void *oldp, size_t *oldlenp, const void *newp, size_t newlen)
+{
+ nvlist_t *nvl;
+ const uint8_t *retoldp;
+ size_t oldlen;
+ uint8_t operation;
+
+ operation = 0;
+ if (oldp != NULL)
+ operation |= CAP_SYSCTL_READ;
+ if (newp != NULL)
+ operation |= CAP_SYSCTL_WRITE;
+
+ nvl = nvlist_create(0);
+ nvlist_add_string(nvl, "cmd", "sysctl");
+ nvlist_add_binary(nvl, "name", (const void*)name, namelen * sizeof(int));
+ nvlist_add_number(nvl, "operation", (uint64_t)operation);
+ if (oldp == NULL && oldlenp != NULL)
+ nvlist_add_null(nvl, "justsize");
+ else if (oldlenp != NULL)
+ nvlist_add_number(nvl, "oldlen", (uint64_t)*oldlenp);
+ if (newp != NULL)
+ nvlist_add_binary(nvl, "newp", newp, newlen);
+ nvl = cap_xfer_nvlist(chan, nvl);
+ if (nvl == NULL)
+ return (-1);
+ if (nvlist_get_number(nvl, "error") != 0) {
+ errno = (int)nvlist_get_number(nvl, "error");
+ nvlist_destroy(nvl);
+ return (-1);
+ }
+
+ if (oldp == NULL && oldlenp != NULL) {
+ *oldlenp = (size_t)nvlist_get_number(nvl, "oldlen");
+ } else if (oldp != NULL) {
+ retoldp = nvlist_get_binary(nvl, "oldp", &oldlen);
+ memcpy(oldp, retoldp, oldlen);
+ if (oldlenp != NULL)
+ *oldlenp = oldlen;
+ }
+ nvlist_destroy(nvl);
+
+ return (0);
+}
+
/*
* Service functions.
*/
@@ -110,7 +160,7 @@
if (nvlist_error(nvl) != 0)
return (nvlist_error(nvl));
-#define HAS_NAME 0x01
+#define HAS_NAME_OR_MIB 0x01
#define HAS_OPERATION 0x02
fields = 0;
@@ -118,12 +168,12 @@
while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
/* We accept only one 'name' and one 'operation' in nvl. */
if (strcmp(name, "name") == 0) {
- if (type != NV_TYPE_STRING)
+ if (type != NV_TYPE_STRING && type != NV_TYPE_BINARY)
return (EINVAL);
/* Only one 'name' can be present. */
- if ((fields & HAS_NAME) != 0)
+ if ((fields & HAS_NAME_OR_MIB) != 0)
return (EINVAL);
- fields |= HAS_NAME;
+ fields |= HAS_NAME_OR_MIB;
} else if (strcmp(name, "operation") == 0) {
uint64_t operation;
@@ -150,15 +200,55 @@
}
/* Both fields has to be there. */
- if (fields != (HAS_NAME | HAS_OPERATION))
+ if (fields != (HAS_NAME_OR_MIB | HAS_OPERATION))
return (EINVAL);
#undef HAS_OPERATION
-#undef HAS_NAME
+#undef HAS_NAME_OR_MIB
return (0);
}
+static bool
+sysctl_allowed_mib(const nvlist_t *limits, const int *chmib, size_t chmiblen,
+ uint64_t choperation)
+{
+ uint64_t operation;
+ const char *name;
+ const int *mib;
+ size_t len;
+ size_t miblen;
+ void *cookie;
+ int type;
+
+ if (limits == NULL)
+ return (true);
+
+ cookie = NULL;
+ while ((name = nvlist_next(limits, &type, &cookie)) != NULL) {
+ assert(type == NV_TYPE_NUMBER);
+
+ operation = nvlist_get_number(limits, name);
+ if ((operation & choperation) != choperation)
+ continue;
+ mib = (const int*)dnvlist_get_binary(sysctl_mibs, name, &len,
+ NULL, 0);
+ miblen = len / sizeof(int);
+ if ((operation & CAP_SYSCTL_RECURSIVE) == 0) {
+ if (miblen != chmiblen ||
+ memcmp(mib, chmib, miblen) != 0)
+ continue;
+ } else
+ if (miblen > chmiblen ||
+ memcmp(mib, chmib, miblen) != 0)
+ continue;
+
+ return (true);
+ }
+
+ return (false);
+}
+
static bool
sysctl_allowed(const nvlist_t *limits, const char *chname, uint64_t choperation)
{
@@ -197,6 +287,26 @@
return (false);
}
+static void
+sysctl_lookup_mibs(const nvlist_t *limits)
+{
+ nvlist_t *mibs;
+ int mib[CTL_MAXNAME];
+ const char *name;
+ void *cookie;
+ size_t miblen;
+ int type;
+
+ mibs = nvlist_create(0);
+ cookie = NULL;
+ while ((name = nvlist_next(limits, &type, &cookie)) != NULL)
+ if (sysctlnametomib(name, mib, &miblen) == 0)
+ nvlist_add_binary(mibs, name, mib, miblen * sizeof(int));
+
+ nvlist_destroy(sysctl_mibs);
+ sysctl_mibs = mibs;
+}
+
static int
sysctl_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
{
@@ -218,6 +328,7 @@
return (ENOTCAPABLE);
}
+ sysctl_lookup_mibs(newlimits);
return (0);
}
@@ -227,8 +338,10 @@
{
const char *name;
const void *newp;
+ const int *mib;
void *oldp;
uint64_t operation;
+ size_t miblen;
size_t oldlen, newlen;
size_t *oldlenp;
int error;
@@ -239,11 +352,18 @@
if (error != 0)
return (error);
- name = nvlist_get_string(nvlin, "name");
+ mib = NULL;
operation = nvlist_get_number(nvlin, "operation");
- if (!sysctl_allowed(limits, name, operation))
- return (ENOTCAPABLE);
-
+ if (nvlist_exists_binary(nvlin, "name")) {
+ mib = (const int*)nvlist_get_binary(nvlin, "name", &miblen);
+ miblen = miblen / sizeof(int);
+ if (!sysctl_allowed_mib(limits, mib, miblen, operation))
+ return (ENOTCAPABLE);
+ } else {
+ name = nvlist_get_string(nvlin, "name");
+ if (!sysctl_allowed(limits, name, operation))
+ return (ENOTCAPABLE);
+ }
if ((operation & CAP_SYSCTL_WRITE) != 0) {
if (!nvlist_exists_binary(nvlin, "newp"))
return (EINVAL);
@@ -276,10 +396,18 @@
oldlenp = NULL;
}
- if (sysctlbyname(name, oldp, oldlenp, newp, newlen) == -1) {
- error = errno;
- free(oldp);
- return (error);
+ if (mib != NULL) {
+ if (sysctl(mib, miblen, oldp, oldlenp, newp, newlen) == -1) {
+ error = errno;
+ free(oldp);
+ return(error);
+ }
+ } else {
+ if (sysctlbyname(name, oldp, oldlenp, newp, newlen) == -1) {
+ error = errno;
+ free(oldp);
+ return (error);
+ }
}
if ((operation & CAP_SYSCTL_READ) != 0) {
Index: lib/libcasper/services/cap_sysctl/tests/sysctl_test.c
===================================================================
--- lib/libcasper/services/cap_sysctl/tests/sysctl_test.c
+++ lib/libcasper/services/cap_sysctl/tests/sysctl_test.c
@@ -97,9 +97,13 @@
unsigned int result;
int oldvalue, newvalue;
size_t oldsize;
-
+ int mib0[CTL_MAXNAME], mib1[CTL_MAXNAME];
+ size_t miblen0, miblen1;
result = 0;
+ sysctlnametomib(SYSCTL0_NAME, mib0, &miblen0);
+ sysctlnametomib(SYSCTL1_NAME, mib1, &miblen1);
+
oldsize = sizeof(oldvalue);
if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize,
NULL, 0) == 0) {
@@ -108,7 +112,7 @@
}
newvalue = 123;
- if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, NULL, NULL, &newvalue,
+ if (cap_sysctl(capsysctl, mib0, miblen0, NULL, NULL, &newvalue,
sizeof(newvalue)) == 0) {
result |= SYSCTL0_WRITE;
}
@@ -140,7 +144,7 @@
}
oldsize = sizeof(oldvalue);
- if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize,
+ if (cap_sysctl(capsysctl, mib1, miblen1, &oldvalue, &oldsize,
NULL, 0) == 0) {
if (oldsize == sizeof(oldvalue))
result |= SYSCTL1_READ0;
Index: lib/libjail/Makefile
===================================================================
--- lib/libjail/Makefile
+++ lib/libjail/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <src.opts.mk>
+
PACKAGE=lib${LIB}
LIB= jail
SHLIBDIR?= /lib
@@ -27,4 +29,9 @@
CFLAGS+=-I${.CURDIR}
+.if ${MK_CASPER} != "no" && !defined(RESCUE)
+LIBADD= casper cap_sysctl cap_jail
+CFLAGS+=-DWITH_CASPER
+.endif
+
.include <bsd.lib.mk>
Index: lib/libjail/jail.h
===================================================================
--- lib/libjail/jail.h
+++ lib/libjail/jail.h
@@ -64,6 +64,7 @@
extern int jailparam_get(struct jailparam *jp, unsigned njp, int flags);
extern char *jailparam_export(struct jailparam *jp);
extern void jailparam_free(struct jailparam *jp, unsigned njp);
+extern int jail_cap_init(void);
__END_DECLS
#endif /* _JAIL_H */
Index: lib/libjail/jail.c
===================================================================
--- lib/libjail/jail.c
+++ lib/libjail/jail.c
@@ -39,6 +39,13 @@
#include <arpa/inet.h>
#include <netinet/in.h>
+#ifdef WITH_CASPER
+# include <sys/capsicum.h>
+# include <libcasper.h>
+# include <casper/cap_sysctl.h>
+# include <casper/cap_jail.h>
+#endif
+
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
@@ -69,6 +76,90 @@
static const char *bool_values[] = { "false", "true" };
static const char *jailsys_values[] = { "disable", "new", "inherit" };
+#ifdef WITH_CASPER
+static cap_channel_t *cap_h_sysctl = NULL;
+static cap_channel_t *cap_h_jail_get = NULL;
+
+static int
+jail_cap_init_sysclt(const cap_channel_t *capcas)
+{
+ nvlist_t *limits;
+
+ cap_h_sysctl = cap_service_open(capcas, "system.sysctl");
+ if (cap_h_sysctl == NULL)
+ return (-1);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, __DECONST(char *, SJPARAM),
+ CAP_SYSCTL_READ|CAP_SYSCTL_RECURSIVE);
+
+ return (cap_limit_set(cap_h_sysctl, limits));
+}
+
+static int
+jail_cap_init_jail(const cap_channel_t *capcas)
+{
+
+ cap_h_jail_get = cap_service_open(capcas, "system.jail");
+ if (cap_h_jail_get == NULL)
+ return (-1);
+ return (0);
+}
+
+int
+jail_cap_init()
+{
+ cap_channel_t *capcas;
+ int r;
+
+ capcas = cap_init();
+ if (capcas == NULL)
+ return (-1);
+
+ r = jail_cap_init_sysclt(capcas);
+ if (r == 0)
+ r = jail_cap_init_jail(capcas);
+
+ cap_close(capcas);
+ return (r);
+}
+
+static int
+hot_sysctl(const int *name, u_int namelen, void *oldp, size_t *oldplenp,
+ const void *newp, size_t newlen)
+{
+ int r;
+
+ r = sysctl(name, namelen, oldp, oldplenp, newp, newlen);
+ if (r < 0 && errno == EPERM && cap_h_sysctl != NULL)
+ r = cap_sysctl(cap_h_sysctl, name, namelen, oldp, oldplenp,
+ newp, newlen);
+ return (r);
+}
+
+static int
+hot_jail_get(struct iovec *iov, u_int niov, int flags)
+{
+ int r;
+
+ r = jail_get(iov, niov, flags);
+ if (r < 0 && errno == ECAPMODE && cap_h_jail_get != NULL)
+ r = cap_jail_get(cap_h_jail_get, iov, niov, flags);
+
+ return (r);
+}
+
+#define sysctl(name, namelen, oldp, oldlenp, newp, newlen) \
+ hot_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
+#define jail_get(iovec, iov, niov) \
+ hot_jail_get(iovec, iov, niov)
+#else /* WITH_CASPER */
+int
+jail_cap_init() {
+ return (0);
+}
+#endif /* !WITH_CASPER */
+
/*
* Import a null-terminated parameter list and set a jail with the flags
Index: rescue/librescue/Makefile
===================================================================
--- rescue/librescue/Makefile
+++ rescue/librescue/Makefile
@@ -16,13 +16,20 @@
.PATH: ${SRCTOP}/lib/libc/gen \
${SRCTOP}/lib/libc/net \
${SRCTOP}/lib/libc/stdlib \
- ${SRCTOP}/lib/libutil
+ ${SRCTOP}/lib/libutil \
+ ${SRCTOP}/lib/libjail
LIB= rescue
INTERNALLIB= # Don't install this library
SRCS= exec.c getusershell.c login_class.c popen.c rcmdsh.c \
sysctl.c system.c
+# If libjail is configured to use libcasper, jail.c must be
+# recompiled.
+.if ${MK_CASPER} != "no"
+SRCS+= jail.c
+.endif
+
CFLAGS+= -DRESCUE
# Flags copied from src/lib/libc and src/lib/libutil
# libc/db/Makefile.inc
Index: share/mk/src.libnames.mk
===================================================================
--- share/mk/src.libnames.mk
+++ share/mk/src.libnames.mk
@@ -75,6 +75,7 @@
casper \
cap_dns \
cap_grp \
+ cap_jail \
cap_pwd \
cap_random \
cap_sysctl \
@@ -237,6 +238,7 @@
_DP_casper= nv
_DP_cap_dns= nv
_DP_cap_grp= nv
+_DP_cap_jail= nv
_DP_cap_pwd= nv
_DP_cap_random= nv
_DP_cap_sysctl= nv
@@ -269,6 +271,9 @@
_DP_magic= z
_DP_mt= sbuf bsdxml
_DP_ldns= crypto
+.if ${MK_CASPER} != "no"
+_DP_jail+= casper cap_sysctl cap_jail
+.endif
.if ${MK_OPENSSL} != "no"
_DP_fetch= ssl crypto
.else
@@ -535,6 +540,7 @@
LIBCASPERDIR= ${OBJTOP}/lib/libcasper/libcasper
LIBCAP_DNSDIR= ${OBJTOP}/lib/libcasper/services/cap_dns
LIBCAP_GRPDIR= ${OBJTOP}/lib/libcasper/services/cap_grp
+LIBCAP_JAILDIR= ${OBJTOP}/lib/libcasper/servicec/cap_jail
LIBCAP_PWDDIR= ${OBJTOP}/lib/libcasper/services/cap_pwd
LIBCAP_RANDOMDIR= ${OBJTOP}/lib/libcasper/services/cap_random
LIBCAP_SYSCTLDIR= ${OBJTOP}/lib/libcasper/services/cap_sysctl
Index: usr.sbin/jls/jls.c
===================================================================
--- usr.sbin/jls/jls.c
+++ usr.sbin/jls/jls.c
@@ -40,6 +40,7 @@
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <capsicum_helpers.h>
#include <err.h>
#include <errno.h>
#include <jail.h>
@@ -90,6 +91,11 @@
char *dot, *ep, *jname, *pname;
int c, i, jflags, jid, lastjid, pflags, spc;
+ caph_cache_catpages();
+ if (jail_cap_init() < 0 || caph_limit_stdio() < 0 ||
+ caph_enter_casper() < 0)
+ err(1, "capsicum");
+
argc = xo_parse_args(argc, argv);
if (argc < 0)
exit(1);

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 3, 6:28 PM (4 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30137133
Default Alt Text
D15289.1791052111.diff (26 KB)

Event Timeline