diff mbox series

audit-testsuite: tests for subject and object correctness

Message ID e7be279c-0599-8dbd-5dd8-8fc8d0931b2e@schaufler-ca.com (mailing list archive)
State New
Headers show
Series audit-testsuite: tests for subject and object correctness | expand

Commit Message

Casey Schaufler Nov. 12, 2020, 1:31 a.m. UTC
Verify that there are subj= and obj= fields in a record
if and only if they are expected. A system without a security
module that provides these fields should not include them.
A system with multiple security modules providing these fields
(e.g. SELinux and AppArmor) should always provide "?" for the
data and also include a AUDIT_MAC_TASK_CONTEXTS or
AUDIT_MAC_OBJ_CONTEXTS record. The test uses the LSM list from
/sys/kernel/security/lsm to determine which format is expected.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 tests/Makefile               |   1 +
 tests/multiple_lsms/Makefile |  12 +++
 tests/multiple_lsms/test     | 166 +++++++++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+)
 create mode 100644 tests/multiple_lsms/Makefile
 create mode 100755 tests/multiple_lsms/test
diff mbox series

Patch

diff --git a/tests/Makefile b/tests/Makefile
index a7f242a..253e906 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -18,6 +18,7 @@  TESTS := \
 	file_create \
 	file_delete \
 	file_rename \
+	multiple_lsms \
 	filter_exclude \
 	filter_saddr_fam \
 	filter_sessionid \
diff --git a/tests/multiple_lsms/Makefile b/tests/multiple_lsms/Makefile
new file mode 100644
index 0000000..c2a8e87
--- /dev/null
+++ b/tests/multiple_lsms/Makefile
@@ -0,0 +1,12 @@ 
+#
+# Copyright (C) Intel Corporation, 2020
+#
+
+TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+
+LDLIBS += -lpthread
+
+all: $(TARGETS)
+clean:
+	rm -f $(TARGETS)
+
diff --git a/tests/multiple_lsms/test b/tests/multiple_lsms/test
new file mode 100755
index 0000000..c9afed5
--- /dev/null
+++ b/tests/multiple_lsms/test
@@ -0,0 +1,166 @@ 
+#!/usr/bin/perl
+#
+# Copyright (C) Intel Corporation, 2020
+#
+
+use strict;
+
+use Test;
+BEGIN { plan tests => 3 }
+
+use File::Temp qw/ tempdir tempfile /;
+
+###
+# functions
+
+sub key_gen {
+    my @chars = ( "A" .. "Z", "a" .. "z" );
+    my $key   = "testsuite-" . time . "-";
+    $key .= $chars[ rand @chars ] for 1 .. 8;
+    return $key;
+}
+
+###
+# setup
+
+# reset audit
+system("auditctl -D >& /dev/null");
+
+my $line;
+my $lsm_out;
+my $lsm_count = 0;
+my $bpf_enabled = 0;
+
+open($lsm_out, "cat /sys/kernel/security/lsm |");
+while ( $line = <$lsm_out> ) {
+    if ( $line =~ /selinux/ ) {
+        $lsm_count = $lsm_count + 1;
+    }
+    if ( $line =~ /smack/ ) {
+        $lsm_count = $lsm_count + 1;
+    }
+    if ( $line =~ /apparmor/ ) {
+        $lsm_count = $lsm_count + 1;
+    }
+    if ( $line =~ /bpf/ ) {
+        $bpf_enabled = 1;
+    }
+}
+close($lsm_out);
+
+if ( $lsm_count and $bpf_enabled ) {
+    $lsm_count = $lsm_count + 1;
+}
+# create temp directory
+my $dir = tempdir( TEMPLATE => '/tmp/audit-testsuite-XXXX', CLEANUP => 1 );
+
+# create stdout/stderr sinks
+( my $fh_out, my $stdout ) = tempfile(
+    TEMPLATE => '/tmp/audit-testsuite-out-XXXX',
+    UNLINK   => 1
+);
+( my $fh_err, my $stderr ) = tempfile(
+    TEMPLATE => '/tmp/audit-testsuite-err-XXXX',
+    UNLINK   => 1
+);
+
+###
+# tests
+
+# create a test file
+( my $fh, my $filename ) =
+  tempfile( TEMPLATE => $dir . "/file-XXXX", UNLINK => 1 );
+
+# set the directory watch
+my $key = key_gen();
+system("auditctl -w $dir -k $key");
+
+# delete file
+unlink($filename);
+
+# make sure the records had a chance to bubble through to the logs
+system("auditctl -m syncmarker-$key");
+for ( my $i = 0 ; $i < 10 ; $i++ ) {
+    if ( system("ausearch -m USER | grep -q syncmarker-$key") eq 0 ) {
+        last;
+    }
+    sleep(0.2);
+}
+
+# test if we generate any audit records from the watch
+my $result = system("ausearch -i -k $key > $stdout 2> $stderr");
+ok( $result, 0 );
+
+# test if we generate a MAC_TASK_CONTEXTS record if and
+# only if it is required.
+#
+# test if we generate a MAC_OBJ_CONTEXTS record if and
+# only if it is required.
+
+my $found_auxsubj = 0;
+my $found_subjattr = 0;
+my $found_regsubj = 0;
+
+my $found_auxobj = 0;
+my $found_objattr = 0;
+my $found_regobj = 0;
+
+while ( $line = <$fh_out> ) {
+
+    if ( $line =~ / subj=\? / ) {
+        $found_auxsubj = 1;
+    } elsif ( $line =~ / subj=/ ) {
+        $found_regsubj = 1;
+    }
+    if ( $line =~ / subj_selinux=/ ) {
+        $found_subjattr = 1;
+    }
+    if ( $line =~ / subj_apparmor=/ ) {
+        $found_subjattr = 1;
+    }
+    if ( $line =~ / subj_smack=/ ) {
+        $found_subjattr = 1;
+    }
+
+    if ( $line =~ / obj=\? / ) {
+        $found_auxobj = 1;
+    } elsif ( $line =~ / obj=/ ) {
+        $found_regobj = 1;
+    }
+    if ( $line =~ / obj_selinux=/ ) {
+        $found_objattr = 1;
+    }
+    if ( $line =~ / obj_apparmor=/ ) {
+        $found_objattr = 1;
+    }
+    if ( $line =~ / obj_smack=/ ) {
+        $found_objattr = 1;
+    }
+}
+
+# three cases:
+# no subj= field or MAC_TASK_CONTEXTS when no supplying LSM
+# subj=$value field, no MAC_TASK_CONTEXTS for exactly one supplying LSM
+# subj=? field and a MAC_TASK_CONTEXTS for more than one supplying LSM
+#
+if ($lsm_count == 0) {
+    ok($found_regsubj == 0 and $found_auxsubj == 0);
+} elsif ($lsm_count == 1) {
+    ok($found_regsubj and $found_auxsubj == 0);
+} else {
+    ok($found_subjattr and $found_auxsubj);
+}
+
+if ($lsm_count == 0) {
+    ok($found_regobj == 0 and $found_auxobj == 0);
+} elsif ($lsm_count == 1) {
+    ok($found_regobj and $found_auxobj == 0);
+} else {
+    ok($found_objattr and $found_auxobj);
+}
+
+###
+# cleanup
+
+system("auditctl -D >& /dev/null");
+