forked from linux-audit/audit-testsuite
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
See: linux-audit#64 Signed-off-by: Richard Guy Briggs <[email protected]>
- Loading branch information
Showing
3 changed files
with
390 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 |
---|---|---|
|
@@ -13,6 +13,7 @@ endif | |
|
||
# all of the tests | ||
TESTS := \ | ||
containerid \ | ||
exec_execve \ | ||
exec_name \ | ||
file_create \ | ||
|
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,8 @@ | ||
TARGETS=$(patsubst %.c,%,$(wildcard *.c)) | ||
|
||
LDLIBS += -lpthread | ||
|
||
all: $(TARGETS) | ||
clean: | ||
rm -f $(TARGETS) | ||
|
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,381 @@ | ||
#!/usr/bin/perl | ||
|
||
use strict; | ||
use File::Temp qw/ tempdir tempfile /; | ||
use Test; | ||
use IO::Handle; | ||
BEGIN { plan tests => 34 } | ||
|
||
### | ||
# functions | ||
|
||
sub key_gen { | ||
my @chars = ( "A" .. "Z", "a" .. "z" ); | ||
my $key = "testsuite-" . time . "-"; | ||
$key .= $chars[ rand @chars ] for 1 .. 8; | ||
return $key; | ||
} | ||
|
||
sub mark_gen { | ||
my @chars = ( "A" .. "Z", "a" .. "z" ); | ||
my $key = "testsuite-" . time . "-"; | ||
$key .= $chars[ rand @chars ] for 1 .. 8; | ||
return $key; | ||
} | ||
|
||
### | ||
# setup | ||
|
||
# reset audit rules | ||
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_tmp, my $tmpout ) = tempfile( | ||
TEMPLATE => '/tmp/audit-testsuite-tmp-XXXX', | ||
UNLINK => 1 | ||
); | ||
my $tmpdir = tempdir( | ||
TEMPLATE => '/tmp/audit-testsuite-dir-XXXX', | ||
CLEANUP => 1 | ||
); | ||
|
||
my $key = key_gen(); | ||
my $result; | ||
|
||
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = | ||
localtime(time); | ||
$year += 1900; | ||
$mon += 1; | ||
my $startdate = "$year-$mon-$mday"; | ||
my $starttime = "$hour:$min:$sec"; | ||
|
||
my $contidself = int( rand( 1 << 63 ) ); | ||
my $contid1 = int( rand( 1 << 63 ) ); | ||
my $contid_unset = 18446744073709551615; | ||
my $contid1a = int( rand( 1 << 63 ) ); | ||
my $contid2 = int( rand( 1 << 63 ) ); | ||
my $contid3 = int( rand( 1 << 63 ) ); | ||
my $contid4 = int( rand( 1 << 63 ) ); | ||
my $contid5 = int( rand( 1 << 63 ) ); | ||
|
||
### | ||
# tests | ||
# Test self-set | ||
seek( $fh_out, 0, 0 ); | ||
|
||
# Set the audit container identifier and save the pid responsible | ||
my $resultself; | ||
my $self_pid = fork(); | ||
if ( not $self_pid ) { | ||
open( my $contidfd, '>', "/proc/self/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$resultself = print $contidfd $contidself; | ||
if ( not $resultself ) { | ||
$resultself = $!; | ||
} | ||
close($contidfd); | ||
exit $resultself; | ||
} | ||
my $wait_pid = wait(); | ||
$resultself = $? >> 8; | ||
ok( $self_pid > 0 ); # Did taskself start ok? | ||
ok( $resultself != 1 ); # Did self-set fail? | ||
|
||
# Start sleep to provide target task | ||
my $task1_pid = fork(); | ||
if ( not $task1_pid ) { | ||
sleep 2; | ||
exit; | ||
} | ||
sleep .01; | ||
ok( $task1_pid > 0 ); # Did task1 start ok? | ||
|
||
# Test set | ||
open( my $contidfd, '>', "/proc/$task1_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd "$contid1\n"; | ||
close($contidfd); | ||
ok($result); # Did set succeed? | ||
|
||
# Test set same | ||
open( $contidfd, '>', "/proc/$task1_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd "$contid1\n"; | ||
close($contidfd); | ||
ok( not $result ); # Did set same fail? | ||
|
||
# Test unset | ||
open( $contidfd, '>', "/proc/$task1_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd $contid_unset; | ||
close($contidfd); | ||
ok( not $result ); # Did unset fail? | ||
|
||
# Test set again by same orch | ||
open( $contidfd, '>', "/proc/$task1_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd $contid1a; | ||
close($contidfd); | ||
ok( not $result ); # Did set again fail? | ||
|
||
# Test task injection to existing container | ||
# Start sleep to provide injection target task | ||
my $task1a_pid = fork(); | ||
if ( not $task1a_pid ) { | ||
sleep 2; | ||
exit; | ||
} | ||
sleep .01; | ||
ok( $task1a_pid > 0 ); # Did task1a start ok? | ||
|
||
# Test task injection | ||
open( $contidfd, '>', "/proc/$task1a_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd "$contid1\n"; | ||
close($contidfd); | ||
ok($result); # Did injection succeed? | ||
|
||
# Test child with child fail | ||
my $task2_pid = fork(); | ||
if ( not $task2_pid ) { | ||
my $task2child_pid = fork(); | ||
if ( not $task2child_pid ) { | ||
sleep 2; | ||
exit; | ||
} | ||
wait(); | ||
exit; | ||
} | ||
sleep 1; | ||
open( $contidfd, '>', "/proc/$task2_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd $contid2; | ||
close($contidfd); | ||
ok( not $result ); # Did set child with child fail? | ||
ok( $task2_pid > 0 ); # Did task2 start ok? | ||
|
||
# find the events | ||
seek( $fh_out, 0, 0 ); | ||
seek( $fh_err, 0, 0 ); | ||
$result = system( | ||
"LC_TIME=\"en_DK.utf8\" ausearch -ts $startdate $starttime -m CONTAINER_OP >$stdout 2>$stderr" | ||
); | ||
ok( $result, 0 ); # Was an event found? | ||
|
||
# test if we generate the lost reset record correctly | ||
my $line; | ||
my $contidself_found = 0; | ||
my $contid1_found = 0; | ||
my $contid_unset_found = 0; | ||
my $contid1a_found = 0; | ||
my $contid1i_found = 0; | ||
my $contid2_found = 0; | ||
|
||
while ( $line = <$fh_out> ) { | ||
|
||
if ( $line =~ /^type=CONTAINER_OP / ) { | ||
if ( $line =~ / opid=([0-9]+) contid=([0-9]+) / ) { | ||
if ( $1 == $self_pid && $2 == $contidself ) { | ||
$contidself_found = 1; | ||
} | ||
elsif ( $1 == $task1_pid && $2 == $contid1 ) { | ||
$contid1_found = 1; | ||
} | ||
elsif ( $1 == $task1_pid && $2 == $contid_unset ) { | ||
$contid_unset_found = 1; | ||
} | ||
elsif ( $1 == $task1_pid && $2 == $contid1a ) { | ||
$contid1a_found = 1; | ||
} | ||
elsif ( $1 == $task1a_pid && $2 == $contid1 ) { | ||
$contid1i_found = 1; | ||
} | ||
elsif ( $1 == $task2_pid && $2 == $contid2 ) { | ||
$contid2_found = 1; | ||
} | ||
} | ||
} | ||
} | ||
ok( $contidself_found, 1 ); # Was the contidself message well-formed? | ||
ok( $contid1_found, 1 ); # Was the contid1 message well-formed? | ||
ok( $contid_unset_found, 1 ); # Was the contid_unset message well-formed? | ||
ok( $contid1a_found, 1 ); # Was the contid1a message well-formed? | ||
ok( $contid1i_found, 1 ); # Was the contid1i message well-formed? | ||
ok( $contid2_found, 1 ); # Was the contid2 message well-formed? | ||
|
||
# Test filter on containerid | ||
$result = system( | ||
"auditctl -a exit,always -F arch=b$ENV{MODE} -F dir=$tmpdir -F perm=wa -F contid=$contid3 -F key=$key >/dev/null 2>&1" | ||
); | ||
ok( $result, 0 ); # Filter rule added successfully? | ||
my $task3_pid = fork(); | ||
if ( not $task3_pid ) { | ||
sleep 1; | ||
open( $contidfd, '>', "$tmpdir/$key" ); | ||
$contidfd->autoflush(1); | ||
print $contidfd $contid3; | ||
close($contidfd); | ||
exit; | ||
} | ||
sleep .01; | ||
open( $contidfd, '>', "/proc/$task3_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd $contid3; | ||
close($contidfd); | ||
ok($result); # Was the filter trigger successfully run? | ||
ok( $task3_pid > 0 ); # Did task3 start ok? | ||
sleep 1; | ||
system( | ||
"auditctl -d exit,always -F arch=b$ENV{MODE} -F dir=$tmpdir -F perm=wa -F contid=$contid3 -F key=$key >/dev/null 2>&1" | ||
); | ||
|
||
# find the event | ||
seek( $fh_out, 0, 0 ); | ||
seek( $fh_err, 0, 0 ); | ||
$result = | ||
system("ausearch -ts recent -i -m CONTAINER_ID -k $key >$stdout 2>$stderr"); | ||
ok( $result, 0 ); # Was an event found? | ||
my $contid3_found = 0; | ||
while ( $line = <$fh_out> ) { | ||
if ( $line =~ /^type=CONTAINER_ID / ) { | ||
if ( $line =~ / contid=([0-9]+)/ ) { | ||
if ( $1 == $contid3 ) { | ||
$contid3_found = 1; | ||
} | ||
} | ||
} | ||
} | ||
ok( $contid3_found, 1 ); # Was the contid3 message well-formed? | ||
|
||
# Test multiple containers on one netns | ||
# Create two child processes | ||
my $task4_pid = fork(); | ||
if ( not $task4_pid ) { | ||
sleep 2; | ||
exit; | ||
} | ||
ok( $task4_pid > 0 ); # Did task4 start ok? | ||
sleep .01; | ||
open( $contidfd, '>', "/proc/$task4_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd $contid4; | ||
close($contidfd); | ||
ok($result); # Was contid4 written to task4? | ||
my $task5_pid = fork(); | ||
|
||
if ( not $task5_pid ) { | ||
sleep 2; | ||
exit; | ||
} | ||
ok( $task5_pid > 0 ); # Did task5 start ok? | ||
sleep .01; | ||
open( $contidfd, '>', "/proc/$task5_pid/audit_containerid" ); | ||
$contidfd->autoflush(1); | ||
$result = print $contidfd $contid5; | ||
close($contidfd); | ||
ok($result); # Was contid5 written to task5? | ||
|
||
# Set up audit rules in netfilter and send a test packet | ||
my $mark = int( rand(99999999) ); | ||
$result = system( | ||
"iptables -I INPUT -i lo -p icmp --icmp-type echo-request -j AUDIT --type accept >/dev/null 2>&1" | ||
); | ||
ok( $result, 0 ); # Was the iptables filter rule added successful | ||
$result = system( | ||
"iptables -I INPUT -t mangle -i lo -p icmp --icmp-type echo-request -j MARK --set-mark 0x$mark >/dev/null 2>&1" | ||
); | ||
ok( $result, 0 ); # Was the iptables mangle rule added successful | ||
sleep 1; | ||
$result = system("ping -q -c 1 127.0.0.1 >/dev/null 2>&1"); | ||
ok( $result, 0 ); # Was ping successful? | ||
sleep 1; | ||
system( | ||
"iptables -D INPUT -i lo -p icmp --icmp-type echo-request -j AUDIT --type accept >/dev/null 2>&1" | ||
); | ||
system( | ||
"iptables -D INPUT -t mangle -i lo -p icmp --icmp-type echo-request -j MARK --set-mark 0x$mark >/dev/null 2>&1" | ||
); | ||
|
||
# find the event | ||
seek( $fh_out, 0, 0 ); | ||
seek( $fh_err, 0, 0 ); | ||
$result = system( | ||
"LC_TIME=\"en_DK.utf8\" ausearch -ts $startdate $starttime -i -m NETFILTER_PKT >$stdout 2>$stderr" | ||
); | ||
ok( $result, 0 ); # Was an event found? | ||
my $contid4_found = 0; | ||
my $contid5_found = 0; | ||
my $id = ""; | ||
|
||
while ( $line = <$fh_out> ) { | ||
|
||
if ( $line =~ /^type=NETFILTER_PKT / ) { | ||
if ( $line =~ / mark=0x$mark / ) { | ||
($id) = ( $line =~ / msg=audit\(.*:([0-9]*)\).* / ); | ||
} | ||
} | ||
} | ||
seek( $fh_out, 0, 0 ); | ||
seek( $fh_err, 0, 0 ); | ||
$result = system("ausearch -ts boot -a $id >$stdout 2>$stderr"); | ||
ok( $result, 0 ); # Was an event found? | ||
while ( $line = <$fh_out> ) { | ||
if ( $line =~ /^type=CONTAINER_ID / ) { | ||
if ( $line =~ / contid=([,0-9]+)/ ) { | ||
my $contids = $1; | ||
if ( $contids =~ /$contid4/ ) { | ||
$contid4_found = 1; | ||
} | ||
if ( $contids =~ /$contid5/ ) { | ||
$contid5_found = 1; | ||
} | ||
} | ||
} | ||
} | ||
ok( $contid4_found, 1 ); # Was the contid4 message well-formed? | ||
ok( $contid5_found, 1 ); # Was the contid5 message well-formed? | ||
|
||
if ( defined $ENV{ATS_DEBUG} && $ENV{ATS_DEBUG} == 1 ) { | ||
print "\ndebug: start\n"; | ||
if ( !$contidself_found || !$resultself ) { | ||
"self_pid=$self_pid contidself=$contidself resultself=$resultself\n"; | ||
} | ||
if ( !$contid1_found ) { | ||
print "task1_pid=$task1_pid contid1=$contid1\n"; | ||
} | ||
if ( !$contid_unset_found ) { | ||
print "task1_pid=$task1_pid contid_unset=$contid_unset\n"; | ||
} | ||
if ( !$contid1a_found ) { | ||
print "task1_pid=$task1_pid contid1a=$contid1a\n"; | ||
} | ||
if ( !$contid1i_found ) { | ||
print "task1a_pid=$task1a_pid contid1i=$contid1\n"; | ||
} | ||
if ( !$contid2_found ) { | ||
print "task2_pid=$task2_pid contid2=$contid2\n"; | ||
} | ||
if ( !$contid3_found ) { | ||
print "task3_pid=$task3_pid contid3=$contid3 dir=$tmpdir key=$key\n"; | ||
} | ||
if ( !$contid4_found ) { | ||
print "mark=$mark id=$id contid4=$contid4\n"; | ||
} | ||
if ( !$contid5_found ) { | ||
print "mark=$mark id=$id contid5=$contid5\n"; | ||
} | ||
print "debug: end\n\n\n"; | ||
} | ||
|
||
### | ||
# cleanup | ||
system("service auditd restart 2>/dev/null"); |