#!/usr/bin/perl # Adapted from: # newrules.pl, Copyright (C) 2001 Justin R. Smith (jsmith@mcs.drexel.edu) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA # 2003 Oct 11: Add -l option by Yuichi Nakamura(ynakam@users.sourceforge.jp) $load_policy_pattern="avc:.*granted.*{.*load_policy.*}"; while ($opt = shift @ARGV) { if ($opt eq "-d") { $read_dmesg++; } elsif ($opt eq "-v") { $verbose++; } elsif ($opt eq "-i") { $input = shift @ARGV; } elsif ($opt eq "-o") { $output= shift @ARGV; } elsif ($opt eq "-l") { $load_policy++; } elsif ($opt eq "--help") { &printUsage; } else { print "unknown option, '$opt'\n\n"; &printUsage; } } if ($read_dmesg && $input) { print "Error, can't read from both dmesg and $input\n\n"; &printUsage; } if ($read_dmesg) { open (IN, "/bin/dmesg|"); } elsif ($input) { open (IN, "$input"); } else { open (IN, "-"); } # STDIN if ($output) { open (OUT, ">>$output"); } else { open (OUT, ">-"); } # STDOUT if($load_policy){ #store logs after last "load_policy" in @log_buf while ($line = ) { if($line=~/$load_policy_pattern/) { #stored logs are unnecessary undef @log_buf; } else { push @log_buf,$line; } } } while ($line=&readNewline) { next unless ($line =~ m/avc:\s*denied\s*\{((\w|\s)*)\}/); @types=split /\ /,$line; $info=""; $group=""; $command=""; foreach $i(0..$#types){ next if($types[$i]!~/[=\{]/); if($types[$i]=~/\{/){ $j=$i+1; while($types[$j]!~/\}/){ $command.=" $types[$j]"; $j++; } next; } my($a,$b) = split /=/,$types[$i]; next if($a eq "pid"); next if($a eq "dev"); next if($a eq "ino"); if(($a eq "scontext")||($a eq "tcontext")||($a eq "tclass")){ if($a ne "tclass"){ my($c,$c,$c) = split /:/, $b; $b=$c; } $b=~s/\n//; $group.="|$b"; next; } $b=~s/:\[\d+\]//; $a=uc $a; $info.="$a=$b "; } my($c,$c,$c,$c) = split /\|/, $group; $info=~s/\ $c=\S+\ //gi; # escape regexp patterns -- $info=~s/([^\w])/\\$1/g; @atypes=split /\ /,$command; foreach $i(0..$#atypes){ $rules{$group}{$atypes[$i]}++; } $info.=" "; if($occur{$group}!~$info){ $occur{$group}.="\t#$info: $command\n"; } else{ my ($a,$b) = split /$info:\ /, $occur{$group}; my ($temp) = split /\n/, $b; @com=split /\ /, $command; foreach $i(1..$#com){ $b=" $com[$i]$b" if($temp!~$com[$i]); } $occur{$group}="$a$info: $b"; } } # done with the input file # now generate the rules foreach $k (sort keys %rules) { my ($a,$scontext,$tcontext,$tclass) = split /\|/, $k; print OUT "allow $scontext $tcontext:$tclass {"; my $access_types = $rules{$k}; foreach $t (sort keys %$access_types) { print OUT "$t "; } print OUT "};\n"; $occur{$k} =~ s/\\(.)/$1/g; # de-escape string print OUT "$occur{$k}\n" if ($verbose); } exit; sub readNewline { if($load_policy){ $newline=shift @log_buf; }else{ $newline=; } return $newline; } sub printUsage { print "newrules [-d] [-v] [-l] [-i ] [-o ] -d read input from output of /bin/dmesg -v verbose output -l read input only after last \"load_policy\" -i read input from -o append output to \n"; exit; }