forked from freebsd/freebsd-src
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import capsicum-test into ^/vendor/google/capsicum-test/dist
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
Showing
34 changed files
with
8,346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 $@ $< |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.