summaryrefslogtreecommitdiff
path: root/tools/regression/capsicum/libcasper/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/regression/capsicum/libcasper/sysctl.c')
-rw-r--r--tools/regression/capsicum/libcasper/sysctl.c1510
1 files changed, 1510 insertions, 0 deletions
diff --git a/tools/regression/capsicum/libcasper/sysctl.c b/tools/regression/capsicum/libcasper/sysctl.c
new file mode 100644
index 000000000000..f3268204313d
--- /dev/null
+++ b/tools/regression/capsicum/libcasper/sysctl.c
@@ -0,0 +1,1510 @@
+/*-
+ * Copyright (c) 2013 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/sysctl.h>
+#include <sys/nv.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+
+#include <casper/cap_sysctl.h>
+
+/*
+ * We need some sysctls to perform the tests on.
+ * We remember their values and restore them afer the test is done.
+ */
+#define SYSCTL0_PARENT "kern"
+#define SYSCTL0_NAME "kern.sync_on_panic"
+#define SYSCTL1_PARENT "debug"
+#define SYSCTL1_NAME "debug.minidump"
+
+static int ntest = 1;
+
+#define CHECK(expr) do { \
+ if ((expr)) \
+ printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \
+ else \
+ printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \
+ ntest++; \
+} while (0)
+#define CHECKX(expr) do { \
+ if ((expr)) { \
+ printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \
+ } else { \
+ printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \
+ exit(1); \
+ } \
+ ntest++; \
+} while (0)
+
+#define SYSCTL0_READ0 0x0001
+#define SYSCTL0_READ1 0x0002
+#define SYSCTL0_READ2 0x0004
+#define SYSCTL0_WRITE 0x0008
+#define SYSCTL0_READ_WRITE 0x0010
+#define SYSCTL1_READ0 0x0020
+#define SYSCTL1_READ1 0x0040
+#define SYSCTL1_READ2 0x0080
+#define SYSCTL1_WRITE 0x0100
+#define SYSCTL1_READ_WRITE 0x0200
+
+static unsigned int
+runtest(cap_channel_t *capsysctl)
+{
+ unsigned int result;
+ int oldvalue, newvalue;
+ size_t oldsize;
+
+ result = 0;
+
+ oldsize = sizeof(oldvalue);
+ if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize,
+ NULL, 0) == 0) {
+ if (oldsize == sizeof(oldvalue))
+ result |= SYSCTL0_READ0;
+ }
+
+ newvalue = 123;
+ if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, NULL, NULL, &newvalue,
+ sizeof(newvalue)) == 0) {
+ result |= SYSCTL0_WRITE;
+ }
+
+ if ((result & SYSCTL0_WRITE) != 0) {
+ oldsize = sizeof(oldvalue);
+ if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue,
+ &oldsize, NULL, 0) == 0) {
+ if (oldsize == sizeof(oldvalue) && oldvalue == 123)
+ result |= SYSCTL0_READ1;
+ }
+ }
+
+ oldsize = sizeof(oldvalue);
+ newvalue = 4567;
+ if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize,
+ &newvalue, sizeof(newvalue)) == 0) {
+ if (oldsize == sizeof(oldvalue) && oldvalue == 123)
+ result |= SYSCTL0_READ_WRITE;
+ }
+
+ if ((result & SYSCTL0_READ_WRITE) != 0) {
+ oldsize = sizeof(oldvalue);
+ if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue,
+ &oldsize, NULL, 0) == 0) {
+ if (oldsize == sizeof(oldvalue) && oldvalue == 4567)
+ result |= SYSCTL0_READ2;
+ }
+ }
+
+ oldsize = sizeof(oldvalue);
+ if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize,
+ NULL, 0) == 0) {
+ if (oldsize == sizeof(oldvalue))
+ result |= SYSCTL1_READ0;
+ }
+
+ newvalue = 506;
+ if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, NULL, NULL, &newvalue,
+ sizeof(newvalue)) == 0) {
+ result |= SYSCTL1_WRITE;
+ }
+
+ if ((result & SYSCTL1_WRITE) != 0) {
+ oldsize = sizeof(oldvalue);
+ if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue,
+ &oldsize, NULL, 0) == 0) {
+ if (oldsize == sizeof(oldvalue) && oldvalue == 506)
+ result |= SYSCTL1_READ1;
+ }
+ }
+
+ oldsize = sizeof(oldvalue);
+ newvalue = 7008;
+ if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize,
+ &newvalue, sizeof(newvalue)) == 0) {
+ if (oldsize == sizeof(oldvalue) && oldvalue == 506)
+ result |= SYSCTL1_READ_WRITE;
+ }
+
+ if ((result & SYSCTL1_READ_WRITE) != 0) {
+ oldsize = sizeof(oldvalue);
+ if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue,
+ &oldsize, NULL, 0) == 0) {
+ if (oldsize == sizeof(oldvalue) && oldvalue == 7008)
+ result |= SYSCTL1_READ2;
+ }
+ }
+
+ return (result);
+}
+
+static void
+test_operation(cap_channel_t *origcapsysctl)
+{
+ cap_channel_t *capsysctl;
+ nvlist_t *limits;
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/RDWR/RECURSIVE
+ * SYSCTL1_PARENT/RDWR/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, "foo.bar",
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, "foo.bar",
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE |
+ SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE |
+ SYSCTL1_READ_WRITE));
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE |
+ SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE |
+ SYSCTL1_READ_WRITE));
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE));
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE));
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == SYSCTL0_READ0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/RDWR/RECURSIVE
+ * SYSCTL1_NAME/RDWR/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE |
+ SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE |
+ SYSCTL1_READ_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/RDWR
+ * SYSCTL1_PARENT/RDWR
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/RDWR
+ * SYSCTL1_NAME/RDWR
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE |
+ SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE |
+ SYSCTL1_READ_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/RDWR
+ * SYSCTL1_PARENT/RDWR/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 |
+ SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/RDWR
+ * SYSCTL1_NAME/RDWR/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE |
+ SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE |
+ SYSCTL1_READ_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ/RECURSIVE
+ * SYSCTL1_PARENT/READ/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/READ/RECURSIVE
+ * SYSCTL1_NAME/READ/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ
+ * SYSCTL1_PARENT/READ
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/READ
+ * SYSCTL1_NAME/READ
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ
+ * SYSCTL1_PARENT/READ/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_READ0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/READ
+ * SYSCTL1_NAME/READ/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/WRITE/RECURSIVE
+ * SYSCTL1_PARENT/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/WRITE/RECURSIVE
+ * SYSCTL1_NAME/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/WRITE
+ * SYSCTL1_PARENT/WRITE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/WRITE
+ * SYSCTL1_NAME/WRITE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/WRITE
+ * SYSCTL1_PARENT/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_WRITE);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/WRITE
+ * SYSCTL1_NAME/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ/RECURSIVE
+ * SYSCTL1_PARENT/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/READ/RECURSIVE
+ * SYSCTL1_NAME/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ
+ * SYSCTL1_PARENT/WRITE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/READ
+ * SYSCTL1_NAME/WRITE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ
+ * SYSCTL1_PARENT/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_WRITE);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_NAME/READ
+ * SYSCTL1_NAME/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE));
+
+ cap_close(capsysctl);
+}
+
+static void
+test_names(cap_channel_t *origcapsysctl)
+{
+ cap_channel_t *capsysctl;
+ nvlist_t *limits;
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL0_READ0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL1_NAME/READ/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_READ0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL0_WRITE);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL1_NAME/WRITE/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_WRITE);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/RDWR/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL1_NAME/RDWR/RECURSIVE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ nvlist_add_number(limits, SYSCTL1_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME,
+ CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 |
+ SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE));
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/READ
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL1_NAME/READ
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_READ0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/WRITE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL1_NAME/WRITE
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == SYSCTL1_WRITE);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL0_PARENT/RDWR
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == 0);
+
+ cap_close(capsysctl);
+
+ /*
+ * Allow:
+ * SYSCTL1_NAME/RDWR
+ */
+
+ capsysctl = cap_clone(origcapsysctl);
+ CHECK(capsysctl != NULL);
+
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == 0);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+ limits = nvlist_create(0);
+ nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR);
+ CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE);
+
+ CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 |
+ SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE));
+
+ cap_close(capsysctl);
+}
+
+int
+main(void)
+{
+ cap_channel_t *capcas, *capsysctl;
+ int scvalue0, scvalue1;
+ size_t scsize;
+
+ printf("1..256\n");
+
+ scsize = sizeof(scvalue0);
+ CHECKX(sysctlbyname(SYSCTL0_NAME, &scvalue0, &scsize, NULL, 0) == 0);
+ CHECKX(scsize == sizeof(scvalue0));
+ scsize = sizeof(scvalue1);
+ CHECKX(sysctlbyname(SYSCTL1_NAME, &scvalue1, &scsize, NULL, 0) == 0);
+ CHECKX(scsize == sizeof(scvalue1));
+
+ capcas = cap_init();
+ CHECKX(capcas != NULL);
+
+ capsysctl = cap_service_open(capcas, "system.sysctl");
+ CHECKX(capsysctl != NULL);
+
+ cap_close(capcas);
+
+ /* No limits set. */
+
+ CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 |
+ SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE |
+ SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE |
+ SYSCTL1_READ_WRITE));
+
+ test_operation(capsysctl);
+
+ test_names(capsysctl);
+
+ cap_close(capsysctl);
+
+ CHECK(sysctlbyname(SYSCTL0_NAME, NULL, NULL, &scvalue0,
+ sizeof(scvalue0)) == 0);
+ CHECK(sysctlbyname(SYSCTL1_NAME, NULL, NULL, &scvalue1,
+ sizeof(scvalue1)) == 0);
+
+ exit(0);
+}