#!/usr/bin/perl -wi # automatically repair apparmor profiles that have had their supporting # infrastructure refactored out from underneath them # note -i in shebang line -- this program will modify in-place # profiles or #include chunks specified on the command line without # backups. Please make some yourself and inspect the changes made by # this tool to ensure they look correct. # It'll try to fix up #include files (supplied by SUSE/Immunix) that have # moved; it will also inspect many #include files that exist solely # for netdomain rule separation, and either remove the #include line # from profiles/includes or suck in the contents of the specific file, # depending if there was any non-netdomain content. # If you haven't modified any of the files listed in the @useless array, # you probably don't have to concern yourself with the complicated part # of the previous paragraph. If you did modify any of those files, this # tool will inspect those for changes, try to update any lines in those # files for correctness, and insert those lines directly into the # referencing profiles. our %count_cache; # count the number of 'interesting' lines in the file sub numlines ($) { my $name = $_[0]; return $count_cache{$name} if $count_cache{$name}; open FH, $name or return 1; # can't tell -> not empty my $linecount=0; while() { if (m/^[^#]*#include/) { $linecount++; } elsif (m/^\s*#/) { # just a comment, skip it } elsif (m/\s*tcp_/) { # netdomain rules are unenforced, skip it } elsif (m/\s*udp_/) { # netdomain rules are unenforced, skip it } elsif (m/\S+/) { $linecount++; } } close FH; $count_cache{$name} = $linecount; return $linecount; } # given a single line from a profile, perform some search/replace # operations to reflect new locations for old files. # # change #include lines that reference files in the @useless array: # don't print the #include any more, and either suck in the contents of # the referenced file (calling itself recursively to fix up _those_ # files) or just leave well enough alone, if the file had no # 'interesting' lines as defined above. %transforms = ( # renamed around SuSE 9.3 "abstractions/kde3" => "abstractions/kde", "abstractions/user-GTK" => "abstractions/gnome", "abstractions/user-Xauthority" => "abstractions/X", # user-custom -> program-chunks around SHASS 1.1, but these changed dirs "user-custom/fonts" => "abstractions/fonts", "user-custom/kde3" => "abstractions/kde", "user-custom/user-GTK" => "abstractions/gnome", "user-custom/user-mail" => "abstractions/user-mail", "user-custom/user-manpages" => "abstractions/user-manpages", "user-custom/user-Xauthority" => "abstractions/X", "user-custom/user-tmp" => "abstractions/user-tmp", # try to forget the -files "program-chunks/base-files" => "abstractions/base", "program-chunks/nameservice-files" => "abstractions/nameservice", "immunix-standard/base-files" => "abstractions/base", "immunix-standard/nameservice-files" => "abstractions/nameservice", # immunix-standard -> program-chunks "immunix-standard/postfix-bounce" => "program-chunks/postfix-bounce", "immunix-standard/postfix-cleanup" => "program-chunks/postfix-cleanup", "immunix-standard/postfix-common" => "program-chunks/postfix-common", "immunix-standard/postfix-flush" => "program-chunks/postfix-flush", "immunix-standard/postfix-local" => "program-chunks/postfix-local", "immunix-standard/postfix-master" => "program-chunks/postfix-master", "immunix-standard/postfix-nqmgr" => "program-chunks/postfix-nqmgr", "immunix-standard/postfix-pickup" => "program-chunks/postfix-pickup", "immunix-standard/postfix-proxymap" => "program-chunks/postfix-proxymap", "immunix-standard/postfix-qmgr" => "program-chunks/postfix-qmgr", "immunix-standard/postfix-showq" => "program-chunks/postfix-showq", "immunix-standard/postfix-smtp" => "program-chunks/postfix-smtp", "immunix-standard/postfix-smtpd" => "program-chunks/postfix-smtpd", "immunix-standard/postfix-trivial-rewrite" => "program-chunks/postfix-trivial-rewrite", "immunix-standard/apache-default-uri" => "program-chunks/apache-default-uri", "immunix-standard/at" => "program-chunks/at", ); # chunks that immunix tools never populated -- lets remove the ones that # don't have any useful information my @useless = qw{ program-chunks/base-nd program-chunks/portmap-nd program-chunks/postfix-local-nd program-chunks/postfix-master-nd program-chunks/postfix-proxymap-nd program-chunks/postfix-smtpd-nd program-chunks/postfix-smtp-nd user-custom/base-nd user-custom/portmap-nd user-custom/postfix-local-nd user-custom/postfix-master-nd user-custom/postfix-proxymap-nd user-custom/postfix-smtpd-nd user-custom/postfix-smtp-nd immunix-standard/base-nd immunix-standard/portmap-nd immunix-standard/postfix-local-nd immunix-standard/postfix-master-nd immunix-standard/postfix-proxymap-nd immunix-standard/postfix-smtpd-nd immunix-standard/postfix-smtp-nd program-chunks/at program-chunks/fam program-chunks/httpd program-chunks/identd program-chunks/imapd program-chunks/ipop2d program-chunks/ipop3d program-chunks/lpd program-chunks/mutt program-chunks/named program-chunks/nmbd program-chunks/ntalkd program-chunks/ntpd program-chunks/postgres program-chunks/rpc.lockd program-chunks/rpc.nfsd program-chunks/rpc.statd program-chunks/samba program-chunks/sendmail.sendmail program-chunks/shells program-chunks/slocate program-chunks/snmpd program-chunks/spamc program-chunks/sshd program-chunks/swat program-chunks/syslogd program-chunks/talk program-chunks/xfs }; # create an alternation to speed up the regexp below my $useless = join('|', @useless); sub fixup ($) { $line = $_[0]; $line =~ s/#include\s+<([^>]+)>/$i = (exists $transforms{$1}) ? $transforms{$1} : "$1"; "#include <$i>"/e; if ($line =~ m/\s*#include\s+<($useless)>/) { my $file = $1; if (numlines("/etc/subdomain.d/$file") > 0) { my $succ = open INC, "/etc/subdomain.d/$file"; if (not $succ) { print STDERR "Error opening /etc/subdomain.d/$file\n"; } else { while(my $included_line = ) { print fixup_loop($included_line); } close INC; } } $line = ""; # this line has been handled by the file } return $line; } # call fixup on a single entry repeatedly -- this way, we can encode # 'small' changes in the fixup routine when they are made, rather than # encoding all possible starting points and which specific end point # they should go to. sub fixup_loop ($) { my $line = $_[0]; my $saved; do { $saved = $line; $line = fixup($saved); } until ($line eq $saved); return $line; } # main entry point; fix each line in every file in argv. while(<>) { print fixup_loop($_); }