summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-12-29 19:56:26 +0000
committerngie <ngie@FreeBSD.org>2015-12-29 19:56:26 +0000
commit48b72481dba08c5185c1dd6a70b82b326be43d6b (patch)
treebfa4f047c73b138c59732a37297737fa1ffd3e91 /tests
parentf8c5cd12c37a92500da3f42f1d25bae9cc70e30a (diff)
parentc0ae58548ada98f553239a091b8764ea9e1b474b (diff)
downloadFreeBSD-src-48b72481dba08c5185c1dd6a70b82b326be43d6b.zip
FreeBSD-src-48b72481dba08c5185c1dd6a70b82b326be43d6b.tar.gz
MFhead @ r292618
Diffstat (limited to 'tests')
-rw-r--r--tests/sys/Makefile1
-rw-r--r--tests/sys/aio/aio_kqueue_test.c37
-rw-r--r--tests/sys/aio/lio_kqueue_test.c101
-rwxr-xr-xtests/sys/file/flock_test.sh5
-rw-r--r--tests/sys/kern/pipe/pipe_overcommit1_test.c7
-rw-r--r--tests/sys/kern/unix_seqpacket_test.c54
-rw-r--r--tests/sys/mac/Makefile8
-rw-r--r--tests/sys/mac/bsdextended/Makefile13
-rw-r--r--tests/sys/mac/bsdextended/matches_test.sh353
-rw-r--r--tests/sys/mac/bsdextended/ugidfw_test.c252
-rw-r--r--tests/sys/mac/portacl/LICENSE27
-rw-r--r--tests/sys/mac/portacl/Makefile16
-rwxr-xr-xtests/sys/mac/portacl/misc.sh106
-rwxr-xr-xtests/sys/mac/portacl/nobody_test.sh67
-rwxr-xr-xtests/sys/mac/portacl/root_test.sh51
15 files changed, 996 insertions, 102 deletions
diff --git a/tests/sys/Makefile b/tests/sys/Makefile
index 3adf81e..702f664 100644
--- a/tests/sys/Makefile
+++ b/tests/sys/Makefile
@@ -10,6 +10,7 @@ TESTS_SUBDIRS+= fifo
TESTS_SUBDIRS+= file
TESTS_SUBDIRS+= kern
TESTS_SUBDIRS+= kqueue
+TESTS_SUBDIRS+= mac
TESTS_SUBDIRS+= mqueue
TESTS_SUBDIRS+= netinet
TESTS_SUBDIRS+= opencrypto
diff --git a/tests/sys/aio/aio_kqueue_test.c b/tests/sys/aio/aio_kqueue_test.c
index 14e4729..97c2c38f 100644
--- a/tests/sys/aio/aio_kqueue_test.c
+++ b/tests/sys/aio/aio_kqueue_test.c
@@ -62,7 +62,10 @@ main (int argc, char *argv[])
struct kevent ke, kq_returned;
struct timespec ts;
char buffer[32768];
- int cancel, error, failed = 0, fd, kq, pending, result, run;
+#ifdef DEBUG
+ int cancel, error;
+#endif
+ int failed = 0, fd, kq, pending, result, run;
int tmp_file = 0;
unsigned i, j;
@@ -96,19 +99,19 @@ main (int argc, char *argv[])
if (iocb[i] == NULL)
err(1, "calloc");
}
-
- pending = 0;
+
+ pending = 0;
for (i = 0; i < nitems(iocb); i++) {
pending++;
iocb[i]->aio_nbytes = sizeof(buffer);
iocb[i]->aio_buf = buffer;
iocb[i]->aio_fildes = fd;
iocb[i]->aio_offset = iocb[i]->aio_nbytes * i * run;
-
+
iocb[i]->aio_sigevent.sigev_notify_kqueue = kq;
iocb[i]->aio_sigevent.sigev_value.sival_ptr = iocb[i];
iocb[i]->aio_sigevent.sigev_notify = SIGEV_KEVENT;
-
+
result = aio_write(iocb[i]);
if (result != 0) {
perror("aio_write");
@@ -133,7 +136,9 @@ main (int argc, char *argv[])
}
}
}
+#ifdef DEBUG
cancel = nitems(iocb) - pending;
+#endif
i = 0;
while (pending) {
@@ -144,34 +149,36 @@ main (int argc, char *argv[])
bzero(&kq_returned, sizeof(ke));
ts.tv_sec = 0;
ts.tv_nsec = 1;
- result = kevent(kq, NULL, 0,
+ result = kevent(kq, NULL, 0,
&kq_returned, 1, &ts);
+#ifdef DEBUG
error = errno;
+#endif
if (result < 0)
perror("kevent error: ");
kq_iocb = kq_returned.udata;
#ifdef DEBUG
printf("kevent %d %d errno %d return.ident %p "
- "return.data %p return.udata %p %p\n",
- i, result, error,
- kq_returned.ident, kq_returned.data,
- kq_returned.udata,
+ "return.data %p return.udata %p %p\n",
+ i, result, error,
+ kq_returned.ident, kq_returned.data,
+ kq_returned.udata,
kq_iocb);
#endif
-
+
if (kq_iocb)
break;
#ifdef DEBUG
printf("Try again left %d out of %d %d\n",
pending, nitems(iocb), cancel);
#endif
- }
-
+ }
+
for (j = 0; j < nitems(iocb) && iocb[j] != kq_iocb;
j++) ;
#ifdef DEBUG
printf("kq_iocb %p\n", kq_iocb);
-
+
printf("Error Result for %d is %d pending %d\n",
j, result, pending);
#endif
@@ -192,7 +199,7 @@ main (int argc, char *argv[])
iocb[j] = NULL;
pending--;
i++;
- }
+ }
for (i = 0; i < nitems(iocb); i++)
free(iocb[i]);
diff --git a/tests/sys/aio/lio_kqueue_test.c b/tests/sys/aio/lio_kqueue_test.c
index 5cc87b3..e69b9c9 100644
--- a/tests/sys/aio/lio_kqueue_test.c
+++ b/tests/sys/aio/lio_kqueue_test.c
@@ -42,6 +42,7 @@
#include <sys/time.h>
#include <aio.h>
#include <fcntl.h>
+#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -57,26 +58,26 @@
#define MAX_RUNS 300
int
-main(int argc, char *argv[]){
+main(int argc, char *argv[])
+{
int fd;
struct aiocb *iocb[MAX_IOCBS];
- struct aiocb **lio[LIO_MAX], **lio_element, **kq_lio;
+ struct aiocb **lio[LIO_MAX], **kq_lio;
int i, result, run, error, j, k;
char buffer[32768];
- int kq = kqueue();
+ int kq;
struct kevent ke, kq_returned;
struct timespec ts;
struct sigevent sig;
time_t time1, time2;
- char *file, pathname[sizeof(PATH_TEMPLATE)-1];
+ char *file, pathname[sizeof(PATH_TEMPLATE)];
int tmp_file = 0, failed = 0;
PLAIN_REQUIRE_KERNEL_MODULE("aio", 0);
- if (kq < 0) {
- perror("No kqeueue\n");
- exit(1);
- }
+ kq = kqueue();
+ if (kq < 0)
+ err(1, "kqeueue(2) failed");
if (argc == 1) {
strcpy(pathname, PATH_TEMPLATE);
@@ -87,34 +88,29 @@ main(int argc, char *argv[]){
file = argv[1];
fd = open(file, O_RDWR|O_CREAT, 0666);
}
- if (fd < 0){
- fprintf(stderr, "Can't open %s\n", argv[1]);
- perror("");
- exit(1);
- }
+ if (fd < 0)
+ err(1, "can't open %s", argv[1]);
#ifdef DEBUG
printf("Hello kq %d fd %d\n", kq, fd);
#endif
- for (run = 0; run < MAX_RUNS; run++){
+ for (run = 0; run < MAX_RUNS; run++) {
#ifdef DEBUG
printf("Run %d\n", run);
#endif
for (j = 0; j < LIO_MAX; j++) {
- lio[j] = (struct aiocb **)
+ lio[j] =
malloc(sizeof(struct aiocb *) * MAX_IOCBS/LIO_MAX);
- for(i = 0; i < MAX_IOCBS / LIO_MAX; i++) {
+ for (i = 0; i < MAX_IOCBS / LIO_MAX; i++) {
k = (MAX_IOCBS / LIO_MAX * j) + i;
- lio_element = lio[j];
- lio[j][i] = iocb[k] = (struct aiocb *)
- malloc(sizeof(struct aiocb));
- bzero(iocb[k], sizeof(struct aiocb));
+ lio[j][i] = iocb[k] =
+ calloc(1, sizeof(struct aiocb));
iocb[k]->aio_nbytes = sizeof(buffer);
iocb[k]->aio_buf = buffer;
iocb[k]->aio_fildes = fd;
- iocb[k]->aio_offset
- = iocb[k]->aio_nbytes * k * (run + 1);
+ iocb[k]->aio_offset
+ = iocb[k]->aio_nbytes * k * (run + 1);
#ifdef DEBUG
printf("hello iocb[k] %d\n",
@@ -131,27 +127,26 @@ main(int argc, char *argv[]){
error = errno;
time(&time2);
#ifdef DEBUG
- printf("Time %d %d %d result -> %d\n",
+ printf("Time %d %d %d result -> %d\n",
time1, time2, time2-time1, result);
#endif
if (result != 0) {
errno = error;
- perror("list_listio");
- printf("FAIL: Result %d iteration %d\n",result, j);
- exit(1);
+ err(1, "FAIL: Result %d iteration %d\n",
+ result, j);
}
#ifdef DEBUG
printf("write %d is at %p\n", j, lio[j]);
#endif
}
- for(i = 0; i < LIO_MAX; i++) {
- for(j = LIO_MAX - 1; j >=0; j--) {
+ for (i = 0; i < LIO_MAX; i++) {
+ for (j = LIO_MAX - 1; j >=0; j--) {
if (lio[j])
break;
}
- for(;;) {
+ for (;;) {
bzero(&ke, sizeof(ke));
bzero(&kq_returned, sizeof(ke));
ts.tv_sec = 0;
@@ -159,9 +154,9 @@ main(int argc, char *argv[]){
#ifdef DEBUG
printf("FOO lio %d -> %p\n", j, lio[j]);
#endif
- EV_SET(&ke, (uintptr_t)lio[j],
+ EV_SET(&ke, (uintptr_t)lio[j],
EVFILT_LIO, EV_ONESHOT, 0, 0, iocb[j]);
- result = kevent(kq, NULL, 0,
+ result = kevent(kq, NULL, 0,
&kq_returned, 1, &ts);
error = errno;
if (result < 0) {
@@ -170,14 +165,14 @@ main(int argc, char *argv[]){
kq_lio = kq_returned.udata;
#ifdef DEBUG
printf("kevent %d %d errno %d return.ident %p "
- "return.data %p return.udata %p %p\n",
- i, result, error,
- kq_returned.ident, kq_returned.data,
- kq_returned.udata,
+ "return.data %p return.udata %p %p\n",
+ i, result, error,
+ kq_returned.ident, kq_returned.data,
+ kq_returned.udata,
lio[j]);
#endif
- if(kq_lio)
+ if (kq_lio)
break;
#ifdef DEBUG
printf("Try again\n");
@@ -189,25 +184,21 @@ main(int argc, char *argv[]){
#endif
for (j = 0; j < LIO_MAX; j++) {
- if (lio[j] == kq_lio) {
+ if (lio[j] == kq_lio)
break;
- }
- }
- if (j == LIO_MAX) {
- printf("FAIL:\n");
- exit(1);
}
+ if (j == LIO_MAX)
+ errx(1, "FAIL: ");
#ifdef DEBUG
printf("Error Result for %d is %d\n", j, result);
#endif
if (result < 0) {
printf("FAIL: run %d, operation %d result %d \n", run, LIO_MAX - i -1, result);
- failed = 1;
- } else {
+ failed++;
+ } else
printf("PASS: run %d, operation %d result %d \n", run, LIO_MAX - i -1, result);
- }
- for(k = 0; k < MAX_IOCBS / LIO_MAX; k++){
+ for (k = 0; k < MAX_IOCBS / LIO_MAX; k++) {
result = aio_return(kq_lio[k]);
#ifdef DEBUG
printf("Return Resulto for %d %d is %d\n", j, k, result);
@@ -224,9 +215,8 @@ main(int argc, char *argv[]){
printf("\n");
#endif
- for(k = 0; k < MAX_IOCBS / LIO_MAX; k++) {
+ for (k = 0; k < MAX_IOCBS / LIO_MAX; k++)
free(lio[j][k]);
- }
free(lio[j]);
lio[j] = NULL;
}
@@ -235,15 +225,12 @@ main(int argc, char *argv[]){
printf("Done\n");
#endif
- if (tmp_file) {
+ if (tmp_file)
unlink(pathname);
- }
- if (failed) {
- printf("FAIL: Atleast one\n");
- exit(1);
- } else {
- printf("PASS: All\n");
- exit(0);
- }
+ if (failed)
+ errx(1, "FAIL: %d testcases failed", failed);
+ else
+ errx(0, "PASS: All\n");
+
}
diff --git a/tests/sys/file/flock_test.sh b/tests/sys/file/flock_test.sh
index f963cde..ead4ff1 100755
--- a/tests/sys/file/flock_test.sh
+++ b/tests/sys/file/flock_test.sh
@@ -43,10 +43,11 @@ for n in `seq 1 $last_testcase`; do
todomsg=" # TODO: racy testcase"
fi
- $(dirname $0)/flock_helper . $n | grep -q SUCCEED
- if [ $? -eq 0 ]; then
+ output=$($(dirname $0)/flock_helper . $n)
+ if echo "$output" | grep -q SUCCEED; then
echo "ok $n$todomsg"
else
echo "not ok $n$todomsg"
+ echo "$output" >&2
fi
done
diff --git a/tests/sys/kern/pipe/pipe_overcommit1_test.c b/tests/sys/kern/pipe/pipe_overcommit1_test.c
index f8f881d..4e40be7 100644
--- a/tests/sys/kern/pipe/pipe_overcommit1_test.c
+++ b/tests/sys/kern/pipe/pipe_overcommit1_test.c
@@ -40,12 +40,11 @@
int
main(void)
{
- int pipes[10000], returnval;
+ int pipes[10000];
unsigned int i;
- for (i = 0; i < nitems(pipes); i++) {
- returnval = pipe(&pipes[i]);
- }
+ for (i = 0; i < nitems(pipes); i++)
+ (void)pipe(&pipes[i]);
printf("PASS\n");
exit(0);
diff --git a/tests/sys/kern/unix_seqpacket_test.c b/tests/sys/kern/unix_seqpacket_test.c
index 986b70e..7305ab3 100644
--- a/tests/sys/kern/unix_seqpacket_test.c
+++ b/tests/sys/kern/unix_seqpacket_test.c
@@ -47,7 +47,7 @@ static void
do_socketpair(int *sv)
{
int s;
-
+
s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
ATF_REQUIRE_EQ(0, s);
ATF_REQUIRE(sv[0] >= 0);
@@ -59,7 +59,7 @@ static void
do_socketpair_nonblocking(int *sv)
{
int s;
-
+
s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
ATF_REQUIRE_EQ(0, s);
ATF_REQUIRE(sv[0] >= 0);
@@ -69,7 +69,7 @@ do_socketpair_nonblocking(int *sv)
ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
}
-/*
+/*
* Returns a pair of sockets made the hard way: bind, listen, connect & accept
* @return const char* The path to the socket
*/
@@ -100,7 +100,7 @@ mk_pair_of_sockets(int *sv)
perror("connect");
atf_tc_fail("connect(2) failed");
}
-
+
/* Accept it */
s1 = accept(s, NULL, NULL);
if (s1 == -1) {
@@ -239,7 +239,7 @@ test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
memset(sndbuf, num_sent, pktsize);
ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
if (ssize < 0) {
- /*
+ /*
* XXX: This is bug-compatible with the kernel.
* The kernel returns EMSGSIZE when it should
* return EAGAIN
@@ -275,7 +275,7 @@ test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
pktsize, rsize);
memset(comparebuf, num_received, pktsize);
ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
- pktsize),
+ pktsize),
"Received data miscompare");
num_received++;
}
@@ -333,7 +333,7 @@ test_pipe_reader(void* args)
"expected %zd=send(...) but got %zd",
td->pktsize, rsize);
d = memcmp(comparebuf, rcvbuf, td->pktsize);
- ATF_CHECK_EQ_MSG(0, d,
+ ATF_CHECK_EQ_MSG(0, d,
"Received data miscompare on packet %d", i);
}
return (0);
@@ -369,7 +369,7 @@ test_pipe(size_t sndbufsize, size_t rcvbufsize)
reader_data.so = sv[1];
ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
(void*)&writer_data));
- /*
+ /*
* Give the writer time to start writing, and hopefully block, before
* starting the reader. This increases the likelihood of the test case
* failing due to PR kern/185812
@@ -561,7 +561,7 @@ ATF_TC_BODY(resize_buffers, tc)
ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
printf("After changing SNDBUF | %7d | %7d |\n", xs, xr);
-
+
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
perror("setsockopt");
atf_tc_fail("setsockopt(SO_RCVBUF) failed");
@@ -671,7 +671,9 @@ ATF_TC_BODY(send_recv, tc)
ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
ATF_TC_BODY(sendto_recvfrom, tc)
{
+#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
const char* path;
+#endif
struct sockaddr_storage from;
int sv[2];
const int bufsize = 64;
@@ -682,7 +684,10 @@ ATF_TC_BODY(sendto_recvfrom, tc)
socklen_t fromlen;
/* setup the socket pair */
- path = mk_pair_of_sockets(sv);
+#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
+ path =
+#endif
+ mk_pair_of_sockets(sv);
/* send and receive a small packet */
datalen = strlen(data) + 1; /* +1 for the null */
@@ -703,19 +708,21 @@ ATF_TC_BODY(sendto_recvfrom, tc)
}
ATF_CHECK_EQ(datalen, rsize);
- /*
+#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
+ /*
* FreeBSD does not currently provide the source address for SEQ_PACKET
* AF_UNIX sockets, and POSIX does not require it, so these two checks
* are disabled. If FreeBSD gains that feature in the future, then
* these checks may be reenabled
*/
- /* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
- /* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
+ ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
+ ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path);
+#endif
close(sv[0]);
close(sv[1]);
}
-/*
+/*
* send(2) and recv(2) a single short record with sockets created the
* traditional way, involving bind, listen, connect, and accept
*/
@@ -795,7 +802,6 @@ ATF_TC_BODY(shutdown_send_sigpipe, tc)
/* ATF's isolation mechanisms will guarantee uniqueness of this file */
const char *path = "sock";
const char *data = "data";
- ssize_t ssize;
int s, err, s2;
s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
@@ -820,7 +826,7 @@ ATF_TC_BODY(shutdown_send_sigpipe, tc)
ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
- ssize = send(s2, data, sizeof(data), MSG_EOR);
+ (void)send(s2, data, sizeof(data), MSG_EOR);
ATF_CHECK_EQ(1, got_sigpipe);
close(s);
close(s2);
@@ -861,7 +867,7 @@ ATF_TC_BODY(send_recv_nonblocking, tc)
close(sv[1]);
}
-/*
+/*
* We should get EMSGSIZE if we try to send a message larger than the socket
* buffer, with blocking sockets
*/
@@ -890,7 +896,7 @@ ATF_TC_BODY(emsgsize, tc)
close(sv[1]);
}
-/*
+/*
* We should get EMSGSIZE if we try to send a message larger than the socket
* buffer, with nonblocking sockets
*/
@@ -920,7 +926,7 @@ ATF_TC_BODY(emsgsize_nonblocking, tc)
}
-/*
+/*
* We should get EAGAIN if we try to send a message larger than the socket
* buffer, with nonblocking sockets. Test with several different sockbuf sizes
*/
@@ -946,7 +952,7 @@ ATF_TC_BODY(eagain_128k_128k, tc)
}
-/*
+/*
* nonblocking send(2) and recv(2) of several records, which should collectively
* fill up the send buffer but not the receive buffer
*/
@@ -971,7 +977,7 @@ ATF_TC_BODY(rcvbuf_oversized, tc)
ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
sizeof(rcvbufsize)));
- /*
+ /*
* Send and receive packets that are collectively greater than the send
* buffer, but less than the receive buffer
*/
@@ -999,7 +1005,7 @@ ATF_TC_BODY(rcvbuf_oversized, tc)
"expected %zd=send(...) but got %zd", pktsize, rsize);
/* Verify the contents */
- ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
+ ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
"Received data miscompare");
}
@@ -1011,7 +1017,7 @@ ATF_TC_BODY(rcvbuf_oversized, tc)
close(sv[1]);
}
-/*
+/*
* Simulate the behavior of a blocking pipe. The sender will send until his
* buffer fills up, then we'll simulate a scheduler switch that will allow the
* receiver to read until his buffer empties. Repeat the process until the
@@ -1042,7 +1048,7 @@ ATF_TC_BODY(pipe_simulator_128k_128k, tc)
test_pipe_simulator(131072, 131072);
}
-/*
+/*
* Test blocking I/O by passing data between two threads. The total amount of
* data will be >> buffer size to force blocking. Repeat the test with multiple
* send and receive buffer sizes
diff --git a/tests/sys/mac/Makefile b/tests/sys/mac/Makefile
new file mode 100644
index 0000000..ae2c491
--- /dev/null
+++ b/tests/sys/mac/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/sys/mac
+
+TESTS_SUBDIRS+= bsdextended
+TESTS_SUBDIRS+= portacl
+
+.include <bsd.test.mk>
diff --git a/tests/sys/mac/bsdextended/Makefile b/tests/sys/mac/bsdextended/Makefile
new file mode 100644
index 0000000..9d0b6f6
--- /dev/null
+++ b/tests/sys/mac/bsdextended/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/sys/mac/bsdextended
+
+TAP_TESTS_C+= ugidfw_test
+TAP_TESTS_SH+= matches_test
+
+LIBADD.ugidfw_test+= ugidfw
+
+TEST_METADATA.matches_test+= required_user="root"
+TEST_METADATA.ugidfw_test+= required_user="root"
+
+.include <bsd.test.mk>
diff --git a/tests/sys/mac/bsdextended/matches_test.sh b/tests/sys/mac/bsdextended/matches_test.sh
new file mode 100644
index 0000000..5aff413
--- /dev/null
+++ b/tests/sys/mac/bsdextended/matches_test.sh
@@ -0,0 +1,353 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+uidrange="60000:100000"
+gidrange="60000:100000"
+uidinrange="nobody"
+uidoutrange="daemon"
+gidinrange="nobody" # We expect $uidinrange in this group
+gidoutrange="daemon" # We expect $uidinrange in this group
+
+test_num=1
+pass()
+{
+ echo "ok $test_num # $@"
+ : $(( test_num += 1 ))
+}
+
+fail()
+{
+ echo "not ok $test_num # $@"
+ : $(( test_num += 1 ))
+}
+
+#
+# Setup
+#
+
+: ${TMPDIR=/tmp}
+if [ $(id -u) -ne 0 ]; then
+ echo "1..0 # SKIP test must be run as root"
+ exit 0
+fi
+if ! sysctl -N security.mac.bsdextended >/dev/null 2>&1; then
+ echo "1..0 # SKIP mac_bsdextended(4) support isn't available"
+ exit 0
+fi
+if ! playground=$(mktemp -d $TMPDIR/tmp.XXXXXXX); then
+ echo "1..0 # SKIP failed to create temporary directory"
+ exit 0
+fi
+trap "rmdir $playground" EXIT INT TERM
+if ! mdmfs -s 25m md $playground; then
+ echo "1..0 # SKIP failed to mount md device"
+ exit 0
+fi
+chmod a+rwx $playground
+md_device=$(mount -p | grep "$playground" | awk '{ gsub(/^\/dev\//, "", $1); print $1 }')
+trap "umount -f $playground; mdconfig -d -u $md_device; rmdir $playground" EXIT INT TERM
+if [ -z "$md_device" ]; then
+ mount -p | grep $playground
+ echo "1..0 # SKIP md device not properly attached to the system"
+fi
+
+ugidfw remove 1
+
+file1=$playground/test-$uidinrange
+file2=$playground/test-$uidoutrange
+cat > $playground/test-script.sh <<'EOF'
+#!/bin/sh
+: > $1
+EOF
+if [ $? -ne 0 ]; then
+ echo "1..0 # SKIP failed to create test script"
+ exit 0
+fi
+echo "1..30"
+
+command1="sh $playground/test-script.sh $file1"
+command2="sh $playground/test-script.sh $file2"
+
+desc="$uidinrange file"
+if su -m $uidinrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+chown "$uidinrange":"$gidinrange" $file1
+chmod a+w $file1
+
+desc="$uidoutrange file"
+if $command2; then
+ pass $desc
+else
+ fail $desc
+fi
+
+chown "$uidoutrange":"$gidoutrange" $file2
+chmod a+w $file2
+
+#
+# No rules
+#
+desc="no rules $uidinrange"
+if su -fm $uidinrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+desc="no rules $uidoutrange"
+if su -fm $uidoutrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+#
+# Subject Match on uid
+#
+ugidfw set 1 subject uid $uidrange object mode rasx
+desc="subject uid in range"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+desc="subject uid out range"
+if su -fm $uidoutrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+#
+# Subject Match on gid
+#
+ugidfw set 1 subject gid $gidrange object mode rasx
+
+desc="subject gid in range"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+desc="subject gid out range"
+if su -fm $uidoutrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+#
+# Subject Match on jail
+#
+rm -f $playground/test-jail
+
+desc="subject matching jailid"
+jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 5; touch $playground/test-jail) &"`
+ugidfw set 1 subject jailid $jailid object mode rasx
+sleep 10
+
+if [ -f $playground/test-jail ]; then
+ fail "TODO $desc: this testcase fails (see bug # 205481)"
+else
+ pass $desc
+fi
+
+rm -f $playground/test-jail
+desc="subject nonmatching jailid"
+jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 5; touch $playground/test-jail) &"`
+sleep 10
+if [ -f $playground/test-jail ]; then
+ pass $desc
+else
+ fail $desc
+fi
+
+#
+# Object uid
+#
+ugidfw set 1 subject object uid $uidrange mode rasx
+
+desc="object uid in range"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+desc="object uid out range"
+if su -fm $uidinrange -c "$command2"; then
+ pass $desc
+else
+ fail $desc
+fi
+ugidfw set 1 subject object uid $uidrange mode rasx
+
+desc="object uid in range (different subject)"
+if su -fm $uidoutrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+desc="object uid out range (different subject)"
+if su -fm $uidoutrange -c "$command2"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+#
+# Object gid
+#
+ugidfw set 1 subject object gid $uidrange mode rasx
+
+desc="object gid in range"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+desc="object gid out range"
+if su -fm $uidinrange -c "$command2"; then
+ pass $desc
+else
+ fail $desc
+fi
+desc="object gid in range (different subject)"
+if su -fm $uidoutrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+desc="object gid out range (different subject)"
+if su -fm $uidoutrange -c "$command2"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+#
+# Object filesys
+#
+ugidfw set 1 subject uid $uidrange object filesys / mode rasx
+desc="object out of filesys"
+if su -fm $uidinrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+ugidfw set 1 subject uid $uidrange object filesys $playground mode rasx
+desc="object in filesys"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+#
+# Object suid
+#
+ugidfw set 1 subject uid $uidrange object suid mode rasx
+desc="object notsuid"
+if su -fm $uidinrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+chmod u+s $file1
+desc="object suid"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+chmod u-s $file1
+
+#
+# Object sgid
+#
+ugidfw set 1 subject uid $uidrange object sgid mode rasx
+desc="object notsgid"
+if su -fm $uidinrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+chmod g+s $file1
+desc="object sgid"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+chmod g-s $file1
+
+#
+# Object uid matches subject
+#
+ugidfw set 1 subject uid $uidrange object uid_of_subject mode rasx
+
+desc="object uid notmatches subject"
+if su -fm $uidinrange -c "$command2"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+desc="object uid matches subject"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+#
+# Object gid matches subject
+#
+ugidfw set 1 subject uid $uidrange object gid_of_subject mode rasx
+
+desc="object gid notmatches subject"
+if su -fm $uidinrange -c "$command2"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+desc="object gid matches subject"
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
+
+#
+# Object type
+#
+desc="object not type"
+ugidfw set 1 subject uid $uidrange object type dbclsp mode rasx
+if su -fm $uidinrange -c "$command1"; then
+ pass $desc
+else
+ fail $desc
+fi
+
+desc="object type"
+ugidfw set 1 subject uid $uidrange object type r mode rasx
+if su -fm $uidinrange -c "$command1"; then
+ fail $desc
+else
+ pass $desc
+fi
diff --git a/tests/sys/mac/bsdextended/ugidfw_test.c b/tests/sys/mac/bsdextended/ugidfw_test.c
new file mode 100644
index 0000000..aab8553
--- /dev/null
+++ b/tests/sys/mac/bsdextended/ugidfw_test.c
@@ -0,0 +1,252 @@
+/*-
+ * Copyright (c) 2005 McAfee, 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/mac.h>
+#include <sys/mount.h>
+
+#include <security/mac_bsdextended/mac_bsdextended.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ugidfw.h>
+#include <unistd.h>
+
+/*
+ * Starting point for a regression test for mac_bsdextended(4) and the
+ * supporting libugidfw(3).
+ */
+
+/*
+ * This section of the regression test passes some test cases through the
+ * rule<->string routines to confirm they work approximately as desired.
+ */
+
+/*
+ * List of users and groups we must check exists before we can begin, since
+ * they are used in the string test rules. We use users and groups that will
+ * always exist in a default install used for regression testing.
+ */
+static const char *test_users[] = {
+ "root",
+ "daemon",
+ "operator",
+ "bin",
+};
+
+static const char *test_groups[] = {
+ "wheel",
+ "daemon",
+ "operator",
+ "bin",
+};
+
+int test_num;
+
+/*
+ * List of test strings that must go in (and come out) of libugidfw intact.
+ */
+static const char *test_strings[] = {
+ /* Variations on subject and object uids. */
+ "subject uid root object uid root mode n",
+ "subject uid root object uid daemon mode n",
+ "subject uid daemon object uid root mode n",
+ "subject uid daemon object uid daemon mode n",
+ /* Variations on mode. */
+ "subject uid root object uid root mode a",
+ "subject uid root object uid root mode r",
+ "subject uid root object uid root mode s",
+ "subject uid root object uid root mode w",
+ "subject uid root object uid root mode x",
+ "subject uid root object uid root mode arswx",
+ /* Variations on subject and object gids. */
+ "subject gid wheel object gid wheel mode n",
+ "subject gid wheel object gid daemon mode n",
+ "subject gid daemon object gid wheel mode n",
+ "subject gid daemon object gid daemon mode n",
+ /* Subject uids and subject gids. */
+ "subject uid bin gid daemon object uid operator gid wheel mode n",
+ /* Not */
+ "subject not uid operator object uid bin mode n",
+ "subject uid bin object not uid operator mode n",
+ "subject not uid daemon object not uid operator mode n",
+ /* Ranges */
+ "subject uid root:operator object gid wheel:bin mode n",
+ /* Jail ID */
+ "subject jailid 1 object uid root mode n",
+ /* Filesys */
+ "subject uid root object filesys / mode n",
+ "subject uid root object filesys /dev mode n",
+ /* S/UGID */
+ "subject not uid root object sgid mode n",
+ "subject not uid root object sgid mode n",
+ /* Matching uid/gid */
+ "subject not uid root:operator object not uid_of_subject mode n",
+ "subject not gid wheel:bin object not gid_of_subject mode n",
+ /* Object types */
+ "subject uid root object type a mode a",
+ "subject uid root object type r mode a",
+ "subject uid root object type d mode a",
+ "subject uid root object type b mode a",
+ "subject uid root object type c mode a",
+ "subject uid root object type l mode a",
+ "subject uid root object type s mode a",
+ "subject uid root object type rbc mode a",
+ "subject uid root object type dls mode a",
+ /* Empty rules always match */
+ "subject object mode a",
+ /* Partial negations */
+ "subject ! uid root object mode n",
+ "subject ! gid wheel object mode n",
+ "subject ! jailid 2 object mode n",
+ "subject object ! uid root mode n",
+ "subject object ! gid wheel mode n",
+ "subject object ! filesys / mode n",
+ "subject object ! suid mode n",
+ "subject object ! sgid mode n",
+ "subject object ! uid_of_subject mode n",
+ "subject object ! gid_of_subject mode n",
+ "subject object ! type d mode n",
+ /* All out nonsense */
+ "subject uid root ! gid wheel:bin ! jailid 1 "
+ "object ! uid root:daemon gid daemon filesys / suid sgid uid_of_subject gid_of_subject ! type r "
+ "mode rsx",
+};
+
+static void
+test_libugidfw_strings(void)
+{
+ struct mac_bsdextended_rule rule;
+ char errorstr[256];
+ char rulestr[256];
+ int error, i;
+
+ for (i = 0; i < nitems(test_users); i++, test_num++) {
+ if (getpwnam(test_users[i]) == NULL)
+ printf("not ok %d # test_libugidfw_strings: getpwnam(%s) "
+ "failed: %s\n", test_num, test_users[i], strerror(errno));
+ else
+ printf("ok %d\n", test_num);
+ }
+
+ for (i = 0; i < nitems(test_groups); i++, test_num++) {
+ if (getgrnam(test_groups[i]) == NULL)
+ printf("not ok %d # test_libugidfw_strings: getgrnam(%s) "
+ "failed: %s\n", test_num, test_groups[i], strerror(errno));
+ else
+ printf("ok %d\n", test_num);
+ }
+
+ for (i = 0; i < nitems(test_strings); i++) {
+ error = bsde_parse_rule_string(test_strings[i], &rule,
+ sizeof(errorstr), errorstr);
+ if (error == -1)
+ printf("not ok %d # bsde_parse_rule_string: '%s' (%d) "
+ "failed: %s\n", test_num, test_strings[i], i, errorstr);
+ else
+ printf("ok %d\n", test_num);
+ test_num++;
+
+ error = bsde_rule_to_string(&rule, rulestr, sizeof(rulestr));
+ if (error < 0)
+ printf("not ok %d # bsde_rule_to_string: rule for '%s' "
+ "returned %d\n", test_num, test_strings[i], error);
+ else
+ printf("ok %d\n", test_num);
+ test_num++;
+
+ if (strcmp(test_strings[i], rulestr) != 0)
+ printf("not ok %d # test_libugidfw: '%s' in, '%s' "
+ "out\n", test_num, test_strings[i], rulestr);
+ else
+ printf("ok %d\n", test_num);
+ test_num++;
+ }
+}
+
+int
+main(void)
+{
+ char errorstr[256];
+ int count, slots;
+
+ test_num = 1;
+
+ /* Print an error if a non-root user attemps to run the tests. */
+ if (getuid() != 0) {
+ printf("1..0 # SKIP you must be root\n");
+ return (0);
+ }
+
+ switch (mac_is_present("bsdextended")) {
+ case -1:
+ printf("1..0 # SKIP mac_is_present failed: %s\n",
+ strerror(errno));
+ return (0);
+ case 1:
+ break;
+ case 0:
+ default:
+ printf("1..0 # SKIP mac_bsdextended not loaded\n");
+ return (0);
+ }
+
+ printf("1..%lu\n", nitems(test_users) + nitems(test_groups) +
+ 3 * nitems(test_strings) + 2);
+
+ test_libugidfw_strings();
+
+ /*
+ * Some simple up-front checks to see if we're able to query the
+ * policy for basic state. We want the rule count to be 0 before
+ * starting, but "slots" is a property of prior runs and so we ignore
+ * the return value.
+ */
+ count = bsde_get_rule_count(sizeof(errorstr), errorstr);
+ if (count == -1)
+ printf("not ok %d # bsde_get_rule_count: %s\n", test_num,
+ errorstr);
+ else
+ printf("ok %d\n", test_num);
+
+ test_num++;
+
+ slots = bsde_get_rule_slots(sizeof(errorstr), errorstr);
+ if (slots == -1)
+ printf("not ok %d # bsde_get_rule_slots: %s\n", test_num,
+ errorstr);
+ else
+ printf("ok %d\n", test_num);
+
+ return (0);
+}
diff --git a/tests/sys/mac/portacl/LICENSE b/tests/sys/mac/portacl/LICENSE
new file mode 100644
index 0000000..c95c149
--- /dev/null
+++ b/tests/sys/mac/portacl/LICENSE
@@ -0,0 +1,27 @@
+$FreeBSD$
+
+License for all mac_portacl regression tests:
+
+Copyright (c) 2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+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.
diff --git a/tests/sys/mac/portacl/Makefile b/tests/sys/mac/portacl/Makefile
new file mode 100644
index 0000000..129d486
--- /dev/null
+++ b/tests/sys/mac/portacl/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/sys/mac/portacl
+BINDIR= ${TESTSDIR}
+
+FILES+= misc.sh
+
+TAP_TESTS_SH+= nobody_test
+TAP_TESTS_SH+= root_test
+
+.for t in ${TAP_TESTS_SH}
+TEST_METADATA.$t+= required_user="root"
+TEST_METADATA.$t+= timeout="450"
+.endfor
+
+.include <bsd.test.mk>
diff --git a/tests/sys/mac/portacl/misc.sh b/tests/sys/mac/portacl/misc.sh
new file mode 100755
index 0000000..5a9e67b
--- /dev/null
+++ b/tests/sys/mac/portacl/misc.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+# $FreeBSD$
+
+sysctl security.mac.portacl >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "1..0 # SKIP MAC_PORTACL is unavailable."
+ exit 0
+fi
+if [ $(id -u) -ne 0 ]; then
+ echo "1..0 # SKIP testcases must be run as root"
+ exit 0
+fi
+
+ntest=1
+
+check_bind() {
+ local host idtype name proto port udpflag
+
+ host="127.0.0.1"
+
+ idtype=${1}
+ name=${2}
+ proto=${3}
+ port=${4}
+
+ [ "${proto}" = "udp" ] && udpflag="-u"
+
+ out=$(
+ case "${idtype}" in
+ uid|gid)
+ ( echo -n | su -m ${name} -c "nc ${udpflag} -l -w 10 $host $port" 2>&1 ) &
+ ;;
+ jail)
+ kill $$
+ ;;
+ *)
+ kill $$
+ esac
+ sleep 0.3
+ echo | nc ${udpflag} -w 10 $host $port >/dev/null 2>&1
+ wait
+ )
+ case "${out}" in
+ "nc: Permission denied"*|"nc: Operation not permitted"*)
+ echo fl
+ ;;
+ "")
+ echo ok
+ ;;
+ *)
+ echo ${out}
+ ;;
+ esac
+}
+
+bind_test() {
+ local expect_without_rule expect_with_rule idtype name proto port
+
+ expect_without_rule=${1}
+ expect_with_rule=${2}
+ idtype=${3}
+ name=${4}
+ proto=${5}
+ port=${6}
+
+ sysctl security.mac.portacl.rules= >/dev/null
+ out=$(check_bind ${idtype} ${name} ${proto} ${port})
+ if [ "${out}" = "${expect_without_rule}" ]; then
+ echo "ok ${ntest}"
+ elif [ "${out}" = "ok" -o "${out}" = "fl" ]; then
+ echo "not ok ${ntest} # '${out}' != '${expect_without_rule}'"
+ else
+ echo "not ok ${ntest} # unexpected output: '${out}'"
+ fi
+ : $(( ntest += 1 ))
+
+ if [ "${idtype}" = "uid" ]; then
+ idstr=$(id -u ${name})
+ elif [ "${idtype}" = "gid" ]; then
+ idstr=$(id -g ${name})
+ else
+ idstr=${name}
+ fi
+ sysctl security.mac.portacl.rules=${idtype}:${idstr}:${proto}:${port} >/dev/null
+ out=$(check_bind ${idtype} ${name} ${proto} ${port})
+ if [ "${out}" = "${expect_with_rule}" ]; then
+ echo "ok ${ntest}"
+ elif [ "${out}" = "ok" -o "${out}" = "fl" ]; then
+ echo "not ok ${ntest} # '${out}' != '${expect_with_rule}'"
+ else
+ echo "not ok ${ntest} # unexpected output: '${out}'"
+ fi
+ : $(( ntest += 1 ))
+
+ sysctl security.mac.portacl.rules= >/dev/null
+}
+
+reserved_high=$(sysctl -n net.inet.ip.portrange.reservedhigh)
+suser_exempt=$(sysctl -n security.mac.portacl.suser_exempt)
+port_high=$(sysctl -n security.mac.portacl.port_high)
+
+restore_settings() {
+ sysctl -n net.inet.ip.portrange.reservedhigh=${reserved_high} >/dev/null
+ sysctl -n security.mac.portacl.suser_exempt=${suser_exempt} >/dev/null
+ sysctl -n security.mac.portacl.port_high=${port_high} >/dev/null
+}
diff --git a/tests/sys/mac/portacl/nobody_test.sh b/tests/sys/mac/portacl/nobody_test.sh
new file mode 100755
index 0000000..7d8dbd6
--- /dev/null
+++ b/tests/sys/mac/portacl/nobody_test.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# $FreeBSD$
+
+dir=`dirname $0`
+. ${dir}/misc.sh
+
+echo "1..64"
+
+# security.mac.portacl.suser_exempt value doesn't affect unprivileged users
+# behaviour.
+# mac_portacl has no impact on ports <= net.inet.ip.portrange.reservedhigh.
+
+trap restore_settings EXIT INT TERM
+
+sysctl security.mac.portacl.suser_exempt=1 >/dev/null
+sysctl net.inet.ip.portrange.reservedhigh=78 >/dev/null
+
+bind_test fl fl uid nobody tcp 77
+bind_test ok ok uid nobody tcp 7777
+bind_test fl fl uid nobody udp 77
+bind_test ok ok uid nobody udp 7777
+
+bind_test fl fl gid nobody tcp 77
+bind_test ok ok gid nobody tcp 7777
+bind_test fl fl gid nobody udp 77
+bind_test ok ok gid nobody udp 7777
+
+sysctl security.mac.portacl.suser_exempt=0 >/dev/null
+
+bind_test fl fl uid nobody tcp 77
+bind_test ok ok uid nobody tcp 7777
+bind_test fl fl uid nobody udp 77
+bind_test ok ok uid nobody udp 7777
+
+bind_test fl fl gid nobody tcp 77
+bind_test ok ok gid nobody tcp 7777
+bind_test fl fl gid nobody udp 77
+bind_test ok ok gid nobody udp 7777
+
+# Verify if security.mac.portacl.port_high works.
+
+sysctl security.mac.portacl.port_high=7778 >/dev/null
+
+bind_test fl fl uid nobody tcp 77
+bind_test fl ok uid nobody tcp 7777
+bind_test fl fl uid nobody udp 77
+bind_test fl ok uid nobody udp 7777
+
+bind_test fl fl gid nobody tcp 77
+bind_test fl ok gid nobody tcp 7777
+bind_test fl fl gid nobody udp 77
+bind_test fl ok gid nobody udp 7777
+
+# Verify if mac_portacl rules work.
+
+sysctl net.inet.ip.portrange.reservedhigh=76 >/dev/null
+sysctl security.mac.portacl.port_high=7776 >/dev/null
+
+bind_test fl ok uid nobody tcp 77
+bind_test ok ok uid nobody tcp 7777
+bind_test fl ok uid nobody udp 77
+bind_test ok ok uid nobody udp 7777
+
+bind_test fl ok gid nobody tcp 77
+bind_test ok ok gid nobody tcp 7777
+bind_test fl ok gid nobody udp 77
+bind_test ok ok gid nobody udp 7777
diff --git a/tests/sys/mac/portacl/root_test.sh b/tests/sys/mac/portacl/root_test.sh
new file mode 100755
index 0000000..9ed452f
--- /dev/null
+++ b/tests/sys/mac/portacl/root_test.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+# $FreeBSD$
+
+dir=`dirname $0`
+. ${dir}/misc.sh
+
+echo "1..48"
+
+# Verify if security.mac.portacl.suser_exempt=1 really exempts super-user.
+
+trap restore_settings EXIT INT TERM
+
+sysctl security.mac.portacl.suser_exempt=1 >/dev/null
+
+bind_test ok ok uid root tcp 77
+bind_test ok ok uid root tcp 7777
+bind_test ok ok uid root udp 77
+bind_test ok ok uid root udp 7777
+
+bind_test ok ok gid root tcp 77
+bind_test ok ok gid root tcp 7777
+bind_test ok ok gid root udp 77
+bind_test ok ok gid root udp 7777
+
+# Verify if security.mac.portacl.suser_exempt=0 really doesn't exempt super-user.
+
+sysctl security.mac.portacl.suser_exempt=0 >/dev/null
+
+bind_test fl ok uid root tcp 77
+bind_test ok ok uid root tcp 7777
+bind_test fl ok uid root udp 77
+bind_test ok ok uid root udp 7777
+
+bind_test fl ok gid root tcp 77
+bind_test ok ok gid root tcp 7777
+bind_test fl ok gid root udp 77
+bind_test ok ok gid root udp 7777
+
+# Verify if security.mac.portacl.port_high works for super-user.
+
+sysctl security.mac.portacl.port_high=7778 >/dev/null
+
+bind_test fl ok uid root tcp 77
+bind_test fl ok uid root tcp 7777
+bind_test fl ok uid root udp 77
+bind_test fl ok uid root udp 7777
+
+bind_test fl ok gid root tcp 77
+bind_test fl ok gid root tcp 7777
+bind_test fl ok gid root udp 77
+bind_test fl ok gid root udp 7777
OpenPOWER on IntegriCloud