Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149858128
D15289.1791052111.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
D15289.1791052111.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D15289: sandbox jls(8)
Attached
Detach File
Event Timeline
Log In to Comment