Page MenuHomeFreeBSD

D15286.id42218.diff
No OneTemporary

D15286.id42218.diff

Index: etc/mtree/BSD.tests.dist
===================================================================
--- etc/mtree/BSD.tests.dist
+++ etc/mtree/BSD.tests.dist
@@ -430,6 +430,8 @@
..
aio
..
+ audit
+ ..
capsicum
..
cddl
Index: tests/sys/Makefile
===================================================================
--- tests/sys/Makefile
+++ tests/sys/Makefile
@@ -6,6 +6,7 @@
TESTS_SUBDIRS+= acl
TESTS_SUBDIRS+= aio
+TESTS_SUBDIRS+= audit
TESTS_SUBDIRS+= capsicum
TESTS_SUBDIRS+= ${_cddl}
TESTS_SUBDIRS+= fifo
Index: tests/sys/audit/Makefile
===================================================================
--- /dev/null
+++ tests/sys/audit/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/sys/audit
+
+ATF_TESTS_C= file-create
+
+SRCS.file-create= file-create.c
+SRCS.file-create+= utils.c
+
+TEST_METADATA.file-create+= timeout="30"
+TEST_METADATA.file-create+= required_user="root"
+WARNS?= 6
+
+CFLAGS+= -I${.CURDIR:H:H}
+LDFLAGS+= -lbsm
+
+.include <bsd.test.mk>
Index: tests/sys/audit/file-create.c
===================================================================
--- /dev/null
+++ tests/sys/audit/file-create.c
@@ -0,0 +1,583 @@
+/*-
+ * Copyright 2018 Aniket Pandey
+ * 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
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * 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
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+static struct pollfd fds[1];
+static mode_t mode = 0777;
+static dev_t dev = 0;
+static const char *path = "fileforaudit";
+static const char *successreg = "fileforaudit.*return,success";
+static const char *failurereg = "fileforaudit.*return,failure";
+
+
+ATF_TC_WITH_CLEANUP(mkdir_success);
+ATF_TC_HEAD(mkdir_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "mkdir(2) call");
+}
+
+ATF_TC_BODY(mkdir_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, mkdir(path, mode));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkdir_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkdir_failure);
+ATF_TC_HEAD(mkdir_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "mkdir(2) call");
+}
+
+ATF_TC_BODY(mkdir_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, mkdir(path, mode));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: directory already exists */
+ ATF_REQUIRE_EQ(-1, mkdir(path, mode));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkdir_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkdirat_success);
+ATF_TC_HEAD(mkdirat_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "mkdirat(2) call");
+}
+
+ATF_TC_BODY(mkdirat_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, mkdirat(AT_FDCWD, path, mode));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkdirat_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkdirat_failure);
+ATF_TC_HEAD(mkdirat_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "mkdirat(2) call");
+}
+
+ATF_TC_BODY(mkdirat_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, mkdirat(AT_FDCWD, path, mode));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: directory already exists */
+ ATF_REQUIRE_EQ(-1, mkdirat(AT_FDCWD, path, mode));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkdirat_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkfifo_success);
+ATF_TC_HEAD(mkfifo_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "mkfifo(2) call");
+}
+
+ATF_TC_BODY(mkfifo_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, mkfifo(path, mode));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkfifo_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkfifo_failure);
+ATF_TC_HEAD(mkfifo_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "mkfifo(2) call");
+}
+
+ATF_TC_BODY(mkfifo_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, mkfifo(path, mode));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: FIFO already exists */
+ ATF_REQUIRE_EQ(-1, mkfifo(path, mode));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkfifo_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkfifoat_success);
+ATF_TC_HEAD(mkfifoat_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "mkfifoat(2) call");
+}
+
+ATF_TC_BODY(mkfifoat_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, mkfifoat(AT_FDCWD, path, mode));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkfifoat_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mkfifoat_failure);
+ATF_TC_HEAD(mkfifoat_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "mkfifoat(2) call");
+}
+
+ATF_TC_BODY(mkfifoat_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, mkfifoat(AT_FDCWD, path, mode));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: FIFO already exists */
+ ATF_REQUIRE_EQ(-1, mkfifoat(AT_FDCWD, path, mode));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(mkfifoat_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mknod_success);
+ATF_TC_HEAD(mknod_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "mknod(2) call");
+}
+
+ATF_TC_BODY(mknod_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, mknod(path, S_IFIFO | S_IRWXO, dev));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(mknod_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mknod_failure);
+ATF_TC_HEAD(mknod_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "mknod(2) call");
+}
+
+ATF_TC_BODY(mknod_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, mknod(path, S_IFIFO | S_IRWXO, dev));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: FIFO node already exists */
+ ATF_REQUIRE_EQ(-1, mknod(path, S_IFIFO | S_IRWXO, dev));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(mknod_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mknodat_success);
+ATF_TC_HEAD(mknodat_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "mknodat(2) call");
+}
+
+ATF_TC_BODY(mknodat_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, mknodat(AT_FDCWD, path, S_IFIFO | S_IRWXO, dev));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(mknodat_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(mknodat_failure);
+ATF_TC_HEAD(mknodat_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "mknodat(2) call");
+}
+
+ATF_TC_BODY(mknodat_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, mknodat(AT_FDCWD, path, S_IFIFO | S_IRWXO, dev));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: FIFO node already exists */
+ ATF_REQUIRE_EQ(-1, mknodat(AT_FDCWD, path, S_IFIFO | S_IRWXO, dev));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(mknodat_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(rename_success);
+ATF_TC_HEAD(rename_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "rename(2) call");
+}
+
+ATF_TC_BODY(rename_success, tc)
+{
+ ATF_REQUIRE(open(path, O_CREAT) != -1);
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, rename(path, "renamed"));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(rename_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(rename_failure);
+ATF_TC_HEAD(rename_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "rename(2) call");
+}
+
+ATF_TC_BODY(rename_failure, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: file does not exist */
+ ATF_REQUIRE_EQ(-1, rename(path, "renamed"));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(rename_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(renameat_success);
+ATF_TC_HEAD(renameat_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "renameat(2) call");
+}
+
+ATF_TC_BODY(renameat_success, tc)
+{
+ ATF_REQUIRE(open(path, O_CREAT) != -1);
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, renameat(AT_FDCWD, path, AT_FDCWD, "renamed"));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(renameat_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(renameat_failure);
+ATF_TC_HEAD(renameat_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "renameat(2) call");
+}
+
+ATF_TC_BODY(renameat_failure, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: file does not exist */
+ ATF_REQUIRE_EQ(-1, renameat(AT_FDCWD, path, AT_FDCWD, "renamed"));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(renameat_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(link_success);
+ATF_TC_HEAD(link_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "link(2) call");
+}
+
+ATF_TC_BODY(link_success, tc)
+{
+ ATF_REQUIRE(open(path, O_CREAT) != -1);
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, link(path, "hardlink"));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(link_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(link_failure);
+ATF_TC_HEAD(link_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "link(2) call");
+}
+
+ATF_TC_BODY(link_failure, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: file does not exist */
+ ATF_REQUIRE_EQ(-1, link(path, "hardlink"));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(link_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(linkat_success);
+ATF_TC_HEAD(linkat_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "linkat(2) call");
+}
+
+ATF_TC_BODY(linkat_success, tc)
+{
+ ATF_REQUIRE(open(path, O_CREAT) != -1);
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, linkat(AT_FDCWD, path, AT_FDCWD, "hardlink", 0));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(linkat_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(linkat_failure);
+ATF_TC_HEAD(linkat_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "linkat(2) call");
+}
+
+ATF_TC_BODY(linkat_failure, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: file does not exist */
+ ATF_REQUIRE_EQ(-1, linkat(AT_FDCWD, path, AT_FDCWD, "hardlink", 0));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(linkat_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(symlink_success);
+ATF_TC_HEAD(symlink_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "symlink(2) call");
+}
+
+ATF_TC_BODY(symlink_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, symlink(path, "symlink"));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(symlink_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(symlink_failure);
+ATF_TC_HEAD(symlink_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "symlink(2) call");
+}
+
+ATF_TC_BODY(symlink_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, symlink(path, "symlink"));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: symbolic link already exists */
+ ATF_REQUIRE_EQ(-1, symlink(path, "symlink"));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(symlink_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(symlinkat_success);
+ATF_TC_HEAD(symlinkat_success, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
+ "symlinkat(2) call");
+}
+
+ATF_TC_BODY(symlinkat_success, tc)
+{
+ FILE *pipefd = setup(fds, "fc");
+ ATF_REQUIRE_EQ(0, symlinkat(path, AT_FDCWD, "symlink"));
+ check_audit(fds, successreg, pipefd);
+}
+
+ATF_TC_CLEANUP(symlinkat_success, tc)
+{
+ cleanup();
+}
+
+
+ATF_TC_WITH_CLEANUP(symlinkat_failure);
+ATF_TC_HEAD(symlinkat_failure, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
+ "symlinkat(2) call");
+}
+
+ATF_TC_BODY(symlinkat_failure, tc)
+{
+ ATF_REQUIRE_EQ(0, symlinkat(path, AT_FDCWD, "symlink"));
+ FILE *pipefd = setup(fds, "fc");
+ /* Failure reason: symbolic link already exists */
+ ATF_REQUIRE_EQ(-1, symlinkat(path, AT_FDCWD, "symlink"));
+ check_audit(fds, failurereg, pipefd);
+}
+
+ATF_TC_CLEANUP(symlinkat_failure, tc)
+{
+ cleanup();
+}
+
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, mkdir_success);
+ ATF_TP_ADD_TC(tp, mkdir_failure);
+ ATF_TP_ADD_TC(tp, mkdirat_success);
+ ATF_TP_ADD_TC(tp, mkdirat_failure);
+
+ ATF_TP_ADD_TC(tp, mkfifo_success);
+ ATF_TP_ADD_TC(tp, mkfifo_failure);
+ ATF_TP_ADD_TC(tp, mkfifoat_success);
+ ATF_TP_ADD_TC(tp, mkfifoat_failure);
+
+ ATF_TP_ADD_TC(tp, mknod_success);
+ ATF_TP_ADD_TC(tp, mknod_failure);
+ ATF_TP_ADD_TC(tp, mknodat_success);
+ ATF_TP_ADD_TC(tp, mknodat_failure);
+
+ ATF_TP_ADD_TC(tp, rename_success);
+ ATF_TP_ADD_TC(tp, rename_failure);
+ ATF_TP_ADD_TC(tp, renameat_success);
+ ATF_TP_ADD_TC(tp, renameat_failure);
+
+ ATF_TP_ADD_TC(tp, link_success);
+ ATF_TP_ADD_TC(tp, link_failure);
+ ATF_TP_ADD_TC(tp, linkat_success);
+ ATF_TP_ADD_TC(tp, linkat_failure);
+
+ ATF_TP_ADD_TC(tp, symlink_success);
+ ATF_TP_ADD_TC(tp, symlink_failure);
+ ATF_TP_ADD_TC(tp, symlinkat_success);
+ ATF_TP_ADD_TC(tp, symlinkat_failure);
+
+ return (atf_no_error());
+}
Index: tests/sys/audit/utils.h
===================================================================
--- /dev/null
+++ tests/sys/audit/utils.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright 2018 Aniket Pandey
+ * 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
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * 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
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#include <poll.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <bsm/audit.h>
+
+void check_audit(struct pollfd [], const char *, FILE *);
+FILE *setup(struct pollfd [], const char *);
+void cleanup(void);
+
+#endif /* _SETUP_H_ */
Index: tests/sys/audit/utils.c
===================================================================
--- /dev/null
+++ tests/sys/audit/utils.c
@@ -0,0 +1,231 @@
+/*-
+ * Copyright 2018 Aniket Pandey
+ * 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
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * 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
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/ioctl.h>
+
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <atf-c.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <bsm/libbsm.h>
+#include <security/audit/audit_ioctl.h>
+
+#include "utils.h"
+
+/*
+ * Checks the presence of "auditregex" in auditpipe(4) after the
+ * corresponding system call has been triggered.
+ */
+static bool
+get_records(const char *auditregex, FILE *pipestream)
+{
+ uint8_t *buff;
+ tokenstr_t token;
+ ssize_t size = 1024;
+ char membuff[size];
+ char del[] = ",";
+ int reclen, bytesread = 0;
+ FILE *memstream;
+
+ /*
+ * Open a stream on 'membuff' (address to memory buffer) for storing
+ * the audit records in the default mode.'reclen' is the length of the
+ * available records from auditpipe which is passed to the functions
+ * au_fetch_tok(3) and au_print_flags_tok(3) for further use.
+ */
+ memstream = fmemopen(membuff, size, "w");
+ reclen = au_read_rec(pipestream, &buff);
+
+ /*
+ * Iterate through each BSM token, extracting the bits that are
+ * required to start processing the token sequences.
+ */
+ while (bytesread < reclen) {
+ if (au_fetch_tok(&token, buff + bytesread, \
+ reclen - bytesread) == -1) {
+ atf_tc_fail("Incomplete audit record");
+ };
+
+ /* Print the tokens as they are obtained, in their default form */
+ au_print_flags_tok(memstream, &token, (char *)del, AU_OFLAG_NONE);
+ bytesread += token.len;
+ }
+
+ free(buff);
+ fclose(memstream);
+ return (atf_utils_grep_string("%s", membuff, auditregex));
+}
+
+/*
+ * Override the system-wide audit mask settings in /etc/security/audit_control
+ */
+static void
+set_preselect_mode(int filedesc, au_mask_t *fmask)
+{
+ int fmode = AUDITPIPE_PRESELECT_MODE_LOCAL;
+
+ /* Set local preselection mode for auditing */
+ if (ioctl(filedesc, AUDITPIPE_SET_PRESELECT_MODE, &fmode) < 0) {
+ atf_tc_fail("Preselection mode: %s", strerror(errno));
+ }
+
+ /* Set local preselection flag corresponding to the audit_event*/
+ if (ioctl(filedesc, AUDITPIPE_SET_PRESELECT_FLAGS, fmask) < 0) {
+ atf_tc_fail("Preselection flag: %s", strerror(errno));
+ }
+
+ /* This removes any outstanding record on the auditpipe */
+ if (ioctl(filedesc, AUDITPIPE_FLUSH) < 0) {
+ atf_tc_fail("Auditpipe flush: %s", strerror(errno));
+ }
+}
+
+/*
+ * Check if the auditd(8) startup was properly received at the auditpipe(4)
+ */
+static void
+check_audit_startup(struct pollfd fd[], FILE *pipestream)
+{
+ int timeout = 2000;
+ const char *auditstring = "audit startup";
+
+ if (poll(fd, 1, timeout) < 0) {
+ atf_tc_fail("Poll: %s", strerror(errno));
+ } else {
+ if (fd[0].revents & POLLIN) {
+ /* We now have a proof that auditd started smoothly */
+ ATF_REQUIRE(get_records(auditstring, pipestream));
+ } else {
+ /* revents is not POLLIN */
+ atf_tc_fail("Auditpipe returned an unknown event %#x",
+ fd[0].revents);
+ }
+ }
+}
+
+/*
+ * Get the corresponding audit_mask for class-name "name" then set the
+ * success and failure bits for fmask to be used as the ioctl argument
+ */
+static au_mask_t
+get_audit_mask(const char *name)
+{
+ au_mask_t fmask;
+ au_class_ent_t *class;
+
+ ATF_REQUIRE((class = getauclassnam(name)) != NULL);
+ fmask.am_success = class->ac_class;
+ fmask.am_failure = class->ac_class;
+ return (fmask);
+}
+
+/*
+ * Loop until the auditpipe returns something, check if it is what
+ * we want, else repeat the procedure until ppoll(2) times out.
+ */
+void
+check_audit(struct pollfd fd[], const char *auditrgx, FILE *pipestream)
+{
+ struct timespec currtime, endtime, timeout;
+
+ /* Set the expire time for poll(2) while waiting for syscall audit */
+ ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC, &endtime));
+ endtime.tv_sec += 5;
+ timeout.tv_nsec = endtime.tv_nsec;
+
+ while(true) {
+ /* Update the time left for auditpipe to return any event */
+ ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC, &currtime));
+ timeout.tv_sec = endtime.tv_sec - currtime.tv_sec;
+
+ switch(ppoll(fd, 1, &timeout, NULL)) {
+ /* ppoll(2) returns, check if it's what we want */
+ case 1:
+ if (fd[0].revents & POLLIN) {
+ if (get_records(auditrgx, pipestream)) {
+ /* Syscall's audit is confirmed */
+ atf_tc_pass();
+ }
+ } else {
+ atf_tc_fail("Auditpipe returned an "
+ "unknown event %#x", fd[0].revents);
+ }
+ break;
+
+ /* poll(2) timed out */
+ case 0:
+ atf_tc_fail("Auditpipe did not return anything "
+ "within the time limit");
+ break;
+
+ /* poll(2) standard error */
+ case -1:
+ atf_tc_fail("Poll: %s", strerror(errno));
+ break;
+
+ default:
+ atf_tc_fail("Poll returned an unknown event");
+ }
+ }
+
+ /* Cleanup */
+ fclose(pipestream);
+ close(fd[0].fd);
+}
+
+FILE
+*setup(struct pollfd fd[], const char *name)
+{
+ au_mask_t fmask;
+ fmask = get_audit_mask(name);
+ FILE *pipestream;
+
+ fd[0].fd = open("/dev/auditpipe", O_RDONLY);
+ fd[0].events = POLLIN;
+ pipestream = fdopen(fd[0].fd, "r");
+
+ ATF_REQUIRE_EQ(0, system("service auditd onestatus || \
+ { service auditd onestart && touch started_auditd ; }"));
+
+ /* If 'started_auditd' exists, that means we started auditd */
+ if (atf_utils_file_exists("started_auditd")) {
+ check_audit_startup(fd, pipestream);
+ }
+ set_preselect_mode(fd[0].fd, &fmask);
+ return (pipestream);
+}
+
+void
+cleanup(void)
+{
+ system("[ -f started_auditd ] && service auditd onestop > \
+ /dev/null 2>&1");
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 28, 2:09 AM (20 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16877666
Default Alt Text
D15286.id42218.diff (23 KB)

Event Timeline