diff --git a/tests/containerid/test b/tests/containerid/test index ab95f45..38837c0 100755 --- a/tests/containerid/test +++ b/tests/containerid/test @@ -6,7 +6,7 @@ use Test; use IO::Handle; use Sys::Syscall; #perl-Sys-Syscall.noarch require 'syscall.ph'; -BEGIN { plan tests => 37 } +BEGIN { plan tests => 52 } ### # functions @@ -66,6 +66,10 @@ my $contid1 = int( rand( 1 << 63 ) ); my $contid_unset = 18446744073709551615; my $contid1a = int( rand( 1 << 63 ) ); my $contid2 = int( rand( 1 << 63 ) ); +my $contidsig = int( rand( 1 << 63 ) ); +my $contidsigc = int( rand( 1 << 63 ) ); +my $contidsigc2 = int( rand( 1 << 63 ) ); +my $contidsigk = int( rand( 1 << 63 ) ); my $contidfilt = int( rand( 1 << 63 ) ); my $contid1net = int( rand( 1 << 63 ) ); my $contid2net = int( rand( 1 << 63 ) ); @@ -158,8 +162,8 @@ 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 ) { + my $task2c_pid = fork(); + if ( not $task2c_pid ) { sleep 2; exit; } @@ -171,9 +175,101 @@ 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? +ok( not $result ); # Did set child with child fail? +ok( $task2_pid > 0 ); # Did task2 start ok? +################################################################################ +# Test task group signal + +my $resultsig = 0; +my $tasksigc_pid = 0; +my $tasksigc2_pid = 0; +my $tasksig_pid = fork(); +if ( not $tasksig_pid ) { + setpgrp; + sleep 2; # wait for parent to set contid + + $tasksigc_pid = fork(); + if ( not $tasksigc_pid ) { + sleep 10; + exit; + } + + $tasksigc2_pid = fork(); + if ( not $tasksigc2_pid ) { + sleep 10; + exit; + } + sleep 1; # wait for child of child to start + + # set nested child with different contid + my $contidfd; + open( $contidfd, '>', "/proc/$tasksigc_pid/audit_containerid" ); + $contidfd->autoflush(1); + $resultsig = print $contidfd $contidsigc; + close($contidfd); + if ( not $resultsig ) { + $resultsig = $!; + } + close($contidfd); + + open( $contidfd, '>', "/proc/$tasksigc2_pid/audit_containerid" ); + $contidfd->autoflush(1); + $resultsig = print $contidfd $contidsigc2; + close($contidfd); + if ( not $resultsig ) { + $resultsig = $!; + } + close($contidfd); + + wait(); + exit $resultsig; +} + +sleep 1; # wait for child to start +ok( $tasksig_pid > 0 ); # Did tasksig start ok? +open( $contidfd, '>', "/proc/$tasksig_pid/audit_containerid" ); +$contidfd->autoflush(1); +$result = print $contidfd $contidsig; +close($contidfd); +ok($result); # Did set child succeed? +sleep 1; # wait for grandchild to start and get contid set + +# generate kill signal child +my $tasksigk_pid = fork(); +if ( not $tasksigk_pid ) { + sleep 2; # wait for parent to set contid + my $count = kill 'SIGTERM', -$tasksig_pid; + exit 0; +} +ok( $tasksigk_pid > 0 ); # Did tasksigk start ok? + +# Add rule to catch signals generated by kill child +$result = + system( +"auditctl -a exit,always -F arch=b$ENV{MODE} -S kill -F pid=$tasksigk_pid -F key=$key >/dev/null 2>&1" + ); +ok( $result, 0 ); # Was the rule accepted? +sleep 1; # wait for kill child to start +open( $contidfd, '>', "/proc/$tasksigk_pid/audit_containerid" ); +$contidfd->autoflush(1); +$result = print $contidfd $contidsigk; +close($contidfd); +ok( $result ); # Did set kill child succeed? +sleep 2; + +# Wait for result of setting nested children +my $wait_pid = waitpid( $tasksig_pid, 0 ); +if ( $wait_pid == $tasksig_pid ) { + $resultsig = $? >> 8; +} +ok( $resultsig != 1 ); # Did sig-set fail? + +# Delete audit rule +system( +"auditctl -d exit,always -F arch=b$ENV{MODE} -S kill -F pid=$tasksigk_pid -F key=$key >/dev/null 2>&1" +); +################################################################################ # make sure the records had a chance to bubble through to the logs system("auditctl -m sync-$key"); for ( my $i = 0 ; $i < 10 ; $i++ ) { @@ -232,11 +328,88 @@ 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? +# find the id events +seek( $fh_out, 0, 0 ); +seek( $fh_err, 0, 0 ); +$result = system( +"LC_TIME=\"en_DK.utf8\" ausearch -i -ts $startdate $starttime -m CONTAINER_ID >$stdout 2>$stderr" +); +ok( $result, 0 ); # Was an event found? + +# test if we generate the id record correctly +my $contidsig_found = 0; +my $contidsigc_found = 0; +my $contidsigc2_found = 0; +my $contidsigk_found = 0; +my $recsig_found = 0; +my $recsigc_found = 0; +my $recsigc2_found = 0; +my $recsigk_found = 0; +my $tasksig_rec = 0; +my $tasksigc_rec = 0; +my $tasksigc2_rec = 0; +my $tasksigk_rec = 0; + +while ( $line = <$fh_out> ) { + if ( $line =~ /^type=CONTAINER_ID / ) { + chomp $line; + if ( $line =~ / record=([0-9]+) contid=$contidsig $/ ) { + $contidsig_found = 1; + $tasksig_rec = $1; + } + elsif ( $line =~ / record=([0-9]+) contid=$contidsigc,/ ) { + $tasksigc_rec = $1; + $contidsigc_found = 1; + } + elsif ( $line =~ / record=([0-9]+) contid=$contidsigc2,/ ) { + $tasksigc2_rec = $1; + $contidsigc2_found = 1; + } + elsif ( $line =~ / record=([0-9]+) contid=$contidsigk $/ ) { + $tasksigk_rec = $1; + $contidsigk_found = 1; + } + } +} +seek( $fh_out, 0, 0 ); +while ( $line = <$fh_out> ) { + if ( $line =~ /^type=SYSCALL / ) { + chomp $line; + if ( $line =~ / pid=$tasksigk_pid .+ record=$tasksigk_rec $/ ) { + $recsigk_found = 1; + } + } + elsif ( $line =~ /^type=OBJ_PID / ) { + chomp $line; + if ( $line =~ / opid=([0-9]+) .+ record=$tasksig_rec $/ ) { + $tasksig_pid = $1; + $recsig_found = 1; + } + elsif ( $line =~ / opid=([0-9]+) .+ record=$tasksigc_rec $/ ) { + $tasksigc_pid = $1; + $recsigc_found = 1; + } + elsif ( $line =~ / opid=([0-9]+) .+ record=$tasksigc2_rec $/ ) { + $tasksigc2_pid = $1; + $recsigc2_found = 1; + } + } +} +ok( $contidsig_found, 1 ); # Was the contidsig message well-formed? +ok( $contidsigc_found, 1 ); # Was the contidsigc message well-formed? +ok( $contidsigc2_found, 1 ); # Was the contidsigc message well-formed? +ok( $contidsigk_found, 1 ); # Was the contidsigk message well-formed? +ok( $recsig_found, 1 ); # Was the recsig message well-formed? +ok( $recsigc_found, 1 ); # Was the recsigc message well-formed? +ok( $recsigc2_found, 1 ); # Was the recsigc message well-formed? +ok( $recsigk_found, 1 ); # Was the recsigk message well-formed? + +################################################################################ # Test filter on containerid $result = system( "auditctl -a exit,always -F arch=b$abi_bits -F dir=$tmpdir -F perm=wa -F contid=$contidfilt -F key=$key >/dev/null 2>&1" ); -ok( $result, 0 ); # Filter rule added successfully? +ok( $result, 0 ); # Filter rule added successfully? my $taskfilt_pid = fork(); if ( not $taskfilt_pid ) { sleep 1; @@ -293,40 +466,40 @@ if ( not $task1net_pid ) { sleep 2; exit; } -ok( $task1net_pid > 0 ); # Did task1net start ok? +ok( $task1net_pid > 0 ); # Did task1net start ok? sleep .01; open( $contidfd, '>', "/proc/$task1net_pid/audit_containerid" ); $contidfd->autoflush(1); $result = print $contidfd $contid1net; close($contidfd); -ok($result); # Was contid1net written to task1net? +ok($result); # Was contid1net written to task1net? my $task2net_pid = fork(); if ( not $task2net_pid ) { sleep 2; exit; } -ok( $task2net_pid > 0 ); # Did task2net start ok? +ok( $task2net_pid > 0 ); # Did task2net start ok? sleep .01; open( $contidfd, '>', "/proc/$task2net_pid/audit_containerid" ); $contidfd->autoflush(1); $result = print $contidfd $contid2net; close($contidfd); -ok($result); # Was contid2net written to task2net? +ok($result); # Was contid2net written to task2net? # 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 +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 +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? +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" @@ -353,7 +526,7 @@ $result = system( ok( $result, 0 ); # Was an event found? my $contid1net_found = 0; my $contid2net_found = 0; -my $id = ""; +my $id = ""; while ( $line = <$fh_out> ) { @@ -395,12 +568,12 @@ if ( not $taskcap_pid ) { print "syscall SYS_unshare failed with errno:" . $! . "\n"; } sleep 2; - my $taskcapchild_pid = fork(); - if ( not $taskcapchild_pid ) { + my $taskcapc_pid = fork(); + if ( not $taskcapc_pid ) { sleep 2; exit; } - open( my $contidfd, '>', "/proc/$taskcapchild_pid/audit_containerid" ); + open( my $contidfd, '>', "/proc/$taskcapc_pid/audit_containerid" ); $contidfd->autoflush(1); $resultcap = print $contidfd $contidcap; close($contidfd); @@ -446,8 +619,23 @@ if ( defined $ENV{ATS_DEBUG} && $ENV{ATS_DEBUG} == 1 ) { if ( !$contid2_found ) { print "task2_pid=$task2_pid contid2=$contid2\n"; } + if ( !$recsig_found + || !$recsigc_found + || !$recsigc2_found + || !$recsigk_found ) + { + print +"script=$$ tasksig pid=$tasksig_pid contid=$contidsig record=$tasksig_rec\n"; + print +" child pid=$tasksigc_pid contid=$contidsigc record=$tasksigc_rec result=$resultsig \n"; + print +" child2 pid=$tasksigc2_pid contid=$contidsigc2 record=$tasksigc2_rec \n"; + print + " kill pid=$tasksigk_pid contid=$contidsigk record=$tasksigk_rec\n"; + } if ( !$contidfilt_found ) { - print "taskfilt_pid=$taskfilt_pid contidfilt=$contidfilt dir=$tmpdir key=$key\n"; + print +"taskfilt_pid=$taskfilt_pid contidfilt=$contidfilt dir=$tmpdir key=$key\n"; } if ( !$contid1net_found ) { print "mark=$mark id=$id contid1net=$contid1net\n";