Skip to content

Commit

Permalink
Import capsicum-test into ^/vendor/google/capsicum-test/dist
Browse files Browse the repository at this point in the history
The following change imports google/capsicum-test@9333154 from GitHub, omitting
the embedded version of googletest, as well as the incomplete libcasper.

This test suite helps verify capsicum(3) support via functional tests
written in the GoogleTest test framework.

Kernel support for capsicum(4) is tested by side-effect of testing
capsicum(3).

NB: as discussed in a previous [closed] PR [1], the casper(3) tests are
incomplete/buggy and will not pass on FreeBSD. Thus, I have no intention of
integrating them into the build/test on FreeBSD as-is.

The import command used was:
```
curl -L https://github.com/google/capsicum-test/tarball/9333154 | tar --strip-components=1 -xvzf - -C dist/
rm -Rf dist/*/
```

1. google/capsicum-test#26

Reviewed by:	emaste (mentor)
Differential Revision:	https://reviews.freebsd.org/D19261


git-svn-id: https://svn.freebsd.org/base/vendor/google/capsicum-test@345046 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
  • Loading branch information
ngie committed Mar 12, 2019
0 parents commit 6b2fdde
Show file tree
Hide file tree
Showing 34 changed files with 8,346 additions and 0 deletions.
19 changes: 19 additions & 0 deletions dist/.gitignore
@@ -0,0 +1,19 @@
capsicum-test
mini-me
mini-me.noexec
mini-me.setuid
mini-me.32
mini-me.x32
mini-me.64
libgtest.a
smoketest
*.o
libcap*.deb
libcap*.dsc
libcap*.tar.gz
libcap*.changes
casper*.deb
casper*.dsc
casper*.tar.gz
casper*.changes
libcaprights.a
20 changes: 20 additions & 0 deletions dist/CONTRIBUTING.md
@@ -0,0 +1,20 @@
## Contributor License Agreement ##

Contributions to any Google project must be accompanied by a Contributor
License Agreement. This is not a copyright **assignment**, it simply gives
Google permission to use and redistribute your contributions as part of the
project.

* If you are an individual writing original source code and you're sure you
own the intellectual property, then you'll need to sign an [individual
CLA][].

* If you work for a company that wants to allow you to contribute your work,
then you'll need to sign a [corporate CLA][].

You generally only need to submit a CLA once, so if you've already submitted
one (even if it was for a different project), you probably don't need to do it
again.

[individual CLA]: https://developers.google.com/open-source/cla/individual
[corporate CLA]: https://developers.google.com/open-source/cla/corporate
78 changes: 78 additions & 0 deletions dist/GNUmakefile
@@ -0,0 +1,78 @@
OS:=$(shell uname)

# Set ARCH to 32 or x32 for i386/x32 ABIs
ARCH?=64
ARCHFLAG=-m$(ARCH)

ifeq ($(OS),Linux)
PROCESSOR:=$(shell uname -p)

ifneq ($(wildcard /usr/lib/$(PROCESSOR)-linux-gnu),)
# Can use standard Debian location for static libraries.
PLATFORM_LIBDIR=/usr/lib/$(PROCESSOR)-linux-gnu
else
# Attempt to determine library location from gcc configuration.
PLATFORM_LIBDIR=$(shell gcc -v 2>&1 | grep "Configured with:" | sed 's/.*--libdir=\(\/usr\/[^ ]*\).*/\1/g')
endif

# Override for explicitly specified ARCHFLAG.
# Use locally compiled libcaprights in this case, on the
# assumption that any installed version is 64-bit.
ifeq ($(ARCHFLAG),-m32)
PROCESSOR=i386
PLATFORM_LIBDIR=/usr/lib32
LIBCAPRIGHTS=./libcaprights.a
endif
ifeq ($(ARCHFLAG),-mx32)
PROCESSOR=x32
PLATFORM_LIBDIR=/usr/libx32
LIBCAPRIGHTS=./libcaprights.a
endif

# Detect presence of libsctp in normal Debian location
ifneq ($(wildcard $(PLATFORM_LIBDIR)/libsctp.a),)
LIBSCTP=-lsctp
CXXFLAGS=-DHAVE_SCTP
endif

ifneq ($(LIBCAPRIGHTS),)
# Build local libcaprights.a (assuming ./configure
# has already been done in libcaprights/)
LOCAL_LIBS=$(LIBCAPRIGHTS)
LIBCAPRIGHTS_OBJS=libcaprights/capsicum.o libcaprights/linux-bpf-capmode.o libcaprights/procdesc.o libcaprights/signal.o
LOCAL_CLEAN=$(LOCAL_LIBS) $(LIBCAPRIGHTS_OBJS)
else
# Detect installed libcaprights static library.
ifneq ($(wildcard $(PLATFORM_LIBDIR)/libcaprights.a),)
LIBCAPRIGHTS=$(PLATFORM_LIBDIR)/libcaprights.a
else
ifneq ($(wildcard /usr/lib/libcaprights.a),)
LIBCAPRIGHTS=/usr/lib/libcaprights.a
endif
endif
endif

endif

# Extra test programs for arch-transition tests
EXTRA_PROGS = mini-me.32 mini-me.64
ifneq ($(wildcard /usr/include/gnu/stubs-x32.h),)
EXTRA_PROGS += mini-me.x32
endif

# Chain on to the master makefile
include makefile

./libcaprights.a: $(LIBCAPRIGHTS_OBJS)
ar cr $@ $^

# Small static programs of known architectures
# These may require additional packages to be installed; for example, for Debian:
# - libc6-dev-i386 provides 32-bit headers for a 64-bit system
# - libc6-dev-x32 provides headers for the x32 ABI.
mini-me.32: mini-me.c
$(CC) $(CFLAGS) -m32 -static -o $@ $<
mini-me.x32: mini-me.c
$(CC) $(CFLAGS) -mx32 -static -o $@ $<
mini-me.64: mini-me.c
$(CC) $(CFLAGS) -m64 -static -o $@ $<
26 changes: 26 additions & 0 deletions dist/LICENSE
@@ -0,0 +1,26 @@
Copyright (c) 2009-2011 Robert N. M. Watson
Copyright (c) 2011 Jonathan Anderson
Copyright (C) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
Copyright (c) 2013-2014 Google Inc.
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 AUTHOR 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 AUTHOR 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.
62 changes: 62 additions & 0 deletions dist/README.md
@@ -0,0 +1,62 @@
# Capsicum User Space Tests

This directory holds unit tests for [Capsicum](http://www.cl.cam.ac.uk/research/security/capsicum/)
object-capabilities. The tests exercise the syscall interface to a Capsicum-enabled operating system,
currently either [FreeBSD >=10.x](http://www.freebsd.org) or a modified Linux kernel (the
[capsicum-linux](http://github.com/google/capsicum-linux) project).

The tests are written in C++98, and use the [Google Test](https://code.google.com/p/googletest/)
framework, with some additions to fork off particular tests (because a process that enters capability
mode cannot leave it again).

## Provenance

The original basis for these tests was:

- [unit tests](https://github.com/freebsd/freebsd/tree/master/tools/regression/security/cap_test)
written by Robert Watson and Jonathan Anderson for the original FreeBSD 9.x Capsicum implementation
- [unit tests](http://git.chromium.org/gitweb/?p=chromiumos/third_party/kernel-capsicum.git;a=tree;f=tools/testing/capsicum_tests;hb=refs/heads/capsicum) written by Meredydd Luff for the original Capsicum-Linux port.

These tests were coalesced and moved into an independent repository to enable
comparative testing across multiple OSes, and then substantially extended.

## OS Configuration

### Linux

The following kernel configuration options are needed to run the tests:

- `CONFIG_SECURITY_CAPSICUM`: enable the Capsicum framework
- `CONFIG_PROCDESC`: enable Capsicum process-descriptor functionality
- `CONFIG_DEBUG_FS`: enable debug filesystem
- `CONFIG_IP_SCTP`: enable SCTP support

### FreeBSD (>= 10.x)

The following kernel configuration options are needed so that all tests can run:

- `options P1003_1B_MQUEUE`: Enable POSIX message queues (or `kldload mqueuefs`)

## Other Dependencies

### Linux

The following additional development packages are needed to build the full test suite on Linux.

- `libcaprights`: See below
- `libcap-dev`: Provides headers for POSIX.1e capabilities.
- `libsctp1`: Provides SCTP library functions.
- `libsctp-dev`: Provides headers for SCTP library functions.


## Linux libcaprights

The Capsicum userspace library is held in the `libcaprights/` subdirectory. Ideally, this
library should be built (with `./configure; make` or `dpkg-buildpackage -uc -us`) and
installed (with `make install` or `dpkg -i libcaprights*.deb`) so that the tests will
use behave like a normal Capsicum-aware application.

However, if no installed copy of the library is found, the `GNUmakefile` will attempt
to use the local `libcaprights/*.c` source; this requires `./configure` to have been
performed in the `libcaprights` subdirectory. The local code is also used for
cross-compiled builds of the test suite (e.g. `make ARCH=32` or `make ARCH=x32`).
188 changes: 188 additions & 0 deletions dist/capability-fd-pair.cc
@@ -0,0 +1,188 @@
// Tests involving 2 capability file descriptors.
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>

#include "capsicum.h"
#include "syscalls.h"
#include "capsicum-test.h"

TEST(CapabilityPair, sendfile) {
int in_fd = open(TmpFile("cap_sendfile_in"), O_CREAT|O_RDWR, 0644);
EXPECT_OK(write(in_fd, "1234", 4));
// Output fd for sendfile must be a stream socket in FreeBSD.
int sock_fds[2];
EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds));

cap_rights_t r_rs;
cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);
cap_rights_t r_ws;
cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK);

int cap_in_ro = dup(in_fd);
EXPECT_OK(cap_in_ro);
EXPECT_OK(cap_rights_limit(cap_in_ro, &r_rs));
int cap_in_wo = dup(in_fd);
EXPECT_OK(cap_in_wo);
EXPECT_OK(cap_rights_limit(cap_in_wo, &r_ws));
int cap_out_ro = dup(sock_fds[0]);
EXPECT_OK(cap_out_ro);
EXPECT_OK(cap_rights_limit(cap_out_ro, &r_rs));
int cap_out_wo = dup(sock_fds[0]);
EXPECT_OK(cap_out_wo);
EXPECT_OK(cap_rights_limit(cap_out_wo, &r_ws));

off_t offset = 0;
EXPECT_NOTCAPABLE(sendfile_(cap_out_ro, cap_in_ro, &offset, 4));
EXPECT_NOTCAPABLE(sendfile_(cap_out_wo, cap_in_wo, &offset, 4));
EXPECT_OK(sendfile_(cap_out_wo, cap_in_ro, &offset, 4));

close(cap_in_ro);
close(cap_in_wo);
close(cap_out_ro);
close(cap_out_wo);
close(in_fd);
close(sock_fds[0]);
close(sock_fds[1]);
unlink(TmpFile("cap_sendfile_in"));
}

#ifdef HAVE_TEE
TEST(CapabilityPair, tee) {
int pipe1_fds[2];
EXPECT_OK(pipe2(pipe1_fds, O_NONBLOCK));
int pipe2_fds[2];
EXPECT_OK(pipe2(pipe2_fds, O_NONBLOCK));

// Put some data into pipe1.
unsigned char buffer[4] = {1, 2, 3, 4};
EXPECT_OK(write(pipe1_fds[1], buffer, 4));

cap_rights_t r_ro;
cap_rights_init(&r_ro, CAP_READ);
cap_rights_t r_wo;
cap_rights_init(&r_wo, CAP_WRITE);
cap_rights_t r_rw;
cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);

// Various attempts to tee into pipe2.
int cap_in_wo = dup(pipe1_fds[0]);
EXPECT_OK(cap_in_wo);
EXPECT_OK(cap_rights_limit(cap_in_wo, &r_wo));
int cap_in_rw = dup(pipe1_fds[0]);
EXPECT_OK(cap_in_rw);
EXPECT_OK(cap_rights_limit(cap_in_rw, &r_rw));
int cap_out_ro = dup(pipe2_fds[1]);
EXPECT_OK(cap_out_ro);
EXPECT_OK(cap_rights_limit(cap_out_ro, &r_ro));
int cap_out_rw = dup(pipe2_fds[1]);
EXPECT_OK(cap_out_rw);
EXPECT_OK(cap_rights_limit(cap_out_rw, &r_rw));

EXPECT_NOTCAPABLE(tee(cap_in_wo, cap_out_rw, 4, SPLICE_F_NONBLOCK));
EXPECT_NOTCAPABLE(tee(cap_in_rw, cap_out_ro, 4, SPLICE_F_NONBLOCK));
EXPECT_OK(tee(cap_in_rw, cap_out_rw, 4, SPLICE_F_NONBLOCK));

close(cap_in_wo);
close(cap_in_rw);
close(cap_out_ro);
close(cap_out_rw);
close(pipe1_fds[0]);
close(pipe1_fds[1]);
close(pipe2_fds[0]);
close(pipe2_fds[1]);
}
#endif

#ifdef HAVE_SPLICE
TEST(CapabilityPair, splice) {
int pipe1_fds[2];
EXPECT_OK(pipe2(pipe1_fds, O_NONBLOCK));
int pipe2_fds[2];
EXPECT_OK(pipe2(pipe2_fds, O_NONBLOCK));

// Put some data into pipe1.
unsigned char buffer[4] = {1, 2, 3, 4};
EXPECT_OK(write(pipe1_fds[1], buffer, 4));

cap_rights_t r_ro;
cap_rights_init(&r_ro, CAP_READ);
cap_rights_t r_wo;
cap_rights_init(&r_wo, CAP_WRITE);
cap_rights_t r_rs;
cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);
cap_rights_t r_ws;
cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK);

// Various attempts to splice.
int cap_in_wo = dup(pipe1_fds[0]);
EXPECT_OK(cap_in_wo);
EXPECT_OK(cap_rights_limit(cap_in_wo, &r_wo));
int cap_in_ro = dup(pipe1_fds[0]);
EXPECT_OK(cap_in_ro);
EXPECT_OK(cap_rights_limit(cap_in_ro, &r_ro));
int cap_in_ro_seek = dup(pipe1_fds[0]);
EXPECT_OK(cap_in_ro_seek);
EXPECT_OK(cap_rights_limit(cap_in_ro_seek, &r_rs));
int cap_out_wo = dup(pipe2_fds[1]);
EXPECT_OK(cap_out_wo);
EXPECT_OK(cap_rights_limit(cap_out_wo, &r_wo));
int cap_out_ro = dup(pipe2_fds[1]);
EXPECT_OK(cap_out_ro);
EXPECT_OK(cap_rights_limit(cap_out_ro, &r_ro));
int cap_out_wo_seek = dup(pipe2_fds[1]);
EXPECT_OK(cap_out_wo_seek);
EXPECT_OK(cap_rights_limit(cap_out_wo_seek, &r_ws));

EXPECT_NOTCAPABLE(splice(cap_in_ro, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK));
EXPECT_NOTCAPABLE(splice(cap_in_wo, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK));
EXPECT_NOTCAPABLE(splice(cap_in_ro_seek, NULL, cap_out_ro, NULL, 4, SPLICE_F_NONBLOCK));
EXPECT_NOTCAPABLE(splice(cap_in_ro_seek, NULL, cap_out_wo, NULL, 4, SPLICE_F_NONBLOCK));
EXPECT_OK(splice(cap_in_ro_seek, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK));

close(cap_in_wo);
close(cap_in_ro);
close(cap_in_ro_seek);
close(cap_out_wo);
close(cap_out_ro);
close(cap_out_wo_seek);
close(pipe1_fds[0]);
close(pipe1_fds[1]);
close(pipe2_fds[0]);
close(pipe2_fds[1]);
}
#endif

#ifdef HAVE_VMSPLICE
// Although it only involves a single file descriptor, test vmsplice(2) here too.
TEST(CapabilityPair, vmsplice) {
int pipe_fds[2];
EXPECT_OK(pipe2(pipe_fds, O_NONBLOCK));

cap_rights_t r_ro;
cap_rights_init(&r_ro, CAP_READ);
cap_rights_t r_rw;
cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);

int cap_ro = dup(pipe_fds[1]);
EXPECT_OK(cap_ro);
EXPECT_OK(cap_rights_limit(cap_ro, &r_ro));
int cap_rw = dup(pipe_fds[1]);
EXPECT_OK(cap_rw);
EXPECT_OK(cap_rights_limit(cap_rw, &r_rw));

unsigned char buffer[4] = {1, 2, 3, 4};
struct iovec iov;
memset(&iov, 0, sizeof(iov));
iov.iov_base = buffer;
iov.iov_len = sizeof(buffer);

EXPECT_NOTCAPABLE(vmsplice(cap_ro, &iov, 1, SPLICE_F_NONBLOCK));
EXPECT_OK(vmsplice(cap_rw, &iov, 1, SPLICE_F_NONBLOCK));

close(cap_ro);
close(cap_rw);
close(pipe_fds[0]);
close(pipe_fds[1]);
}
#endif

0 comments on commit 6b2fdde

Please sign in to comment.