Beyond the simple existence of the EXECVE record, we test three basic
things:
* large number of arguments spanning multiple records
* single large argument spanning multiple records
* single argument that requires hex encoding
Signed-off-by: Paul Moore <paul(a)paul-moore.com>
---
tests/Makefile | 1
tests/exec_execve/.gitignore | 1
tests/exec_execve/Makefile | 11 +++
tests/exec_execve/execve_arg_gen.c | 108 +++++++++++++++++++++++++++++++
tests/exec_execve/test | 124 ++++++++++++++++++++++++++++++++++++
5 files changed, 245 insertions(+)
create mode 100644 tests/exec_execve/.gitignore
create mode 100644 tests/exec_execve/Makefile
create mode 100644 tests/exec_execve/execve_arg_gen.c
create mode 100755 tests/exec_execve/test
diff --git a/tests/Makefile b/tests/Makefile
index decb6b2..48a8307 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -5,6 +5,7 @@ DISTRO = $(shell ./os_detect)
SUBDIRS := \
exec_name \
+ exec_execve \
file_create \
file_delete \
file_rename \
diff --git a/tests/exec_execve/.gitignore b/tests/exec_execve/.gitignore
new file mode 100644
index 0000000..fb9f5a6
--- /dev/null
+++ b/tests/exec_execve/.gitignore
@@ -0,0 +1 @@
+execve_arg_gen
diff --git a/tests/exec_execve/Makefile b/tests/exec_execve/Makefile
new file mode 100644
index 0000000..97a4ce4
--- /dev/null
+++ b/tests/exec_execve/Makefile
@@ -0,0 +1,11 @@
+TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+
+LDLIBS += -lpthread
+
+all: $(TARGETS)
+
+execve_arg_gen: execve_arg_gen.c
+ $(CC) $(CFLAGS) -o $@ $^
+
+clean:
+ rm -f $(TARGETS)
diff --git a/tests/exec_execve/execve_arg_gen.c b/tests/exec_execve/execve_arg_gen.c
new file mode 100644
index 0000000..a6da4d5
--- /dev/null
+++ b/tests/exec_execve/execve_arg_gen.c
@@ -0,0 +1,108 @@
+/**
+ * audit-testsuite EXECVE test tool
+ *
+ * Copyright (c) 2016 Red Hat <pmoore(a)redhat.com>
+ * Author: Paul Moore <paul(a)paul-moore.com>
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <
http://www.gnu.org/licenses>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#define BADCHAR 0x20
+
+char **arg_setup(const char *name, unsigned int size)
+{
+ char **args = NULL;
+
+ args = malloc(sizeof(char *) * (size + 3));
+ if (!args)
+ exit(1);
+
+ args[0] = strdup("testing");
+ if (!args[0])
+ exit(1);
+ args[1] = strdup(name);
+ if (!args[1])
+ exit(1);
+
+ return args;
+}
+
+char *arg_gen(unsigned int length, char insert)
+{
+ int iter;
+ char val;
+ char *buf;
+
+ buf = malloc(length + 1);
+ if (!buf)
+ exit(1);
+
+ for (iter = 0; iter < length; iter++) {
+ if (insert && iter % 2) {
+ buf[iter] = insert;
+ } else {
+ /* ascii: 0x0..0xF */
+ val = iter % 0x10;
+ buf[iter] = (val > 9 ? 55 + val : 48 + val);
+ }
+ }
+ buf[length] = '\0';
+
+ return buf;
+}
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ int iter;
+ int test_cfg;
+ char **exec_argv = NULL;
+
+ /* check if we are calling ourselves for testing purposes */
+ if ((argc >= 1) && (strcmp(argv[0], "testing") == 0))
+ return 0;
+
+ /* run a specific test? */
+ if (argc == 3) {
+ test_cfg = atoi(argv[2]);
+
+ if (strcmp(argv[1], "count") == 0) {
+ exec_argv = arg_setup("count", test_cfg);
+ for (iter = 0; iter < test_cfg; iter++)
+ exec_argv[iter + 2] = arg_gen(1, 0);
+ exec_argv[test_cfg + 2] = NULL;
+ } else if (strcmp(argv[1], "size") == 0) {
+ exec_argv = arg_setup("size", 1);
+ exec_argv[2] = arg_gen(test_cfg, 0);
+ exec_argv[3] = NULL;
+ } else if (strcmp(argv[1], "hex") == 0) {
+ exec_argv = arg_setup("hex", 1);
+ exec_argv[2] = arg_gen(test_cfg, BADCHAR);
+ exec_argv[3] = NULL;
+ }
+
+ rc = execve(argv[0], exec_argv, NULL);
+ return (rc < 0 ? errno : 0);
+ }
+
+ /* no idea what we were supposed to do */
+ return 2;
+}
diff --git a/tests/exec_execve/test b/tests/exec_execve/test
new file mode 100755
index 0000000..b16b0cd
--- /dev/null
+++ b/tests/exec_execve/test
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+
+use strict;
+
+use Test;
+BEGIN { plan tests => 4 }
+
+use File::Temp qw/ tempfile /;
+
+my $basedir = $0;
+$basedir =~ s|(.*)/[^/]*|$1|;
+
+###
+# 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");
+
+# 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);
+(my $fh_out2, my $stdout2) = tempfile(
+ TEMPLATE => '/tmp/audit-testsuite-out-XXXX',
+ UNLINK => 1);
+(my $fh_err2, my $stderr2) = tempfile(
+ TEMPLATE => '/tmp/audit-testsuite-err-XXXX',
+ UNLINK => 1);
+
+###
+# tests
+
+# set the audit-by-executable filter
+my $key = key_gen();
+system("auditctl -a always,exit -F arch=b64 -S execve -k $key");
+system("auditctl -a always,exit -F arch=b32 -S execve -k $key");
+
+# test parameters
+my $test_count = 2048;
+my $test_size = 7499;
+my $test_hex = 6144;
+
+# run the tests
+system("$basedir/execve_arg_gen");
+system("$basedir/execve_arg_gen count $test_count");
+system("$basedir/execve_arg_gen size $test_size");
+system("$basedir/execve_arg_gen hex $test_hex");
+
+# test if we generate any audit records from the filter rule
+my $result = system("ausearch -i -k $key > $stdout 2> $stderr");
+ok($result, 0);
+
+# test if we generate the EXECVE records correctly
+my $line;
+my $line2;
+my $id;
+my $found_count = 0;
+my $found_size = 0;
+my $found_hex = 0;
+while ($line = <$fh_out>) {
+ if ($line =~ /^type=EXECVE /) {
+ if ($line =~ / a0=testing a1=count / ) {
+ ($id) = ($line =~ / msg=audit\(.*:([0-9]*)\).* /);
+ seek($fh_out2, 0, 0);
+ system("ausearch -i -k $key -a $id" .
+ " > $stdout2 2> $stderr2");
+ while ($line2 = <$fh_out2>) {
+ if ($line2 =~ /^type=EXECVE /) {
+ $found_count += () =
+ $line2 =~ /a([0-9])*=0/g;
+ }
+ }
+ } elsif ($line =~ / a0=testing a1=size / ) {
+ ($id) = ($line =~ / msg=audit\(.*:([0-9]*)\).* /);
+ seek($fh_out2, 0, 0);
+ system("ausearch -i -k $key -a $id" .
+ " > $stdout2 2> $stderr2");
+ while ($line2 = <$fh_out2>) {
+ if ($line2 =~ /^type=EXECVE / &&
+ $line2 =~ / a2(\[.*\])?=.* /) {
+ my $arg_iter;
+ my $arg_val;
+ ($arg_iter,$arg_val) = ($line2 =~
+ / a2(\[.*\])?=(.*) /);
+ $found_size += length $arg_val;
+ }
+ }
+ } elsif ($line =~ / a0=testing a1=hex / ) {
+ ($id) = ($line =~ / msg=audit\(.*:([0-9]*)\).* /);
+ seek($fh_out2, 0, 0);
+ system("ausearch -i -k $key -a $id" .
+ " > $stdout2 2> $stderr2");
+ while ($line2 = <$fh_out2>) {
+ if ($line2 =~ /^type=EXECVE / &&
+ $line2 =~ / a2(\[.*\])?=.* /) {
+ my $arg_iter;
+ my $arg_val;
+ ($arg_iter,$arg_val) = ($line2 =~
+ / a2(\[.*\])?=(.*) /);
+ $found_hex += length $arg_val;
+ }
+ }
+ }
+ }
+}
+ok($found_count == $test_count);
+ok($found_size == $test_size);
+ok($found_hex == $test_hex);
+
+###
+# cleanup
+
+system("auditctl -D >& /dev/null");