This patch moves the ldd analysis of binaries to the mkprofile.pl helper
and take the convoluted code out of the bash prologue.inc. It also
detects if the binary is a script and performs ldd analysis on the
interpreter.
---
 tests/regression/apparmor/environ.sh   |    6 -
 tests/regression/apparmor/mkprofile.pl |  105 +++++++++++++++++++++++++++
 tests/regression/apparmor/prologue.inc |  124 +--------------------------------
 3 files changed, 112 insertions(+), 123 deletions(-)

Index: b/tests/regression/apparmor/mkprofile.pl
===================================================================
--- a/tests/regression/apparmor/mkprofile.pl
+++ b/tests/regression/apparmor/mkprofile.pl
@@ -9,9 +9,11 @@ my $__VERSION__=$0;
 
 use strict;
 use Getopt::Long;
+use Cwd 'realpath';
 
 my $help = '';
 my $nowarn = '';
+my $nodefault;
 my $escape = '';
 my %output_rules;
 my $hat = "__no_hat";
@@ -21,6 +23,7 @@ GetOptions(
   'escape|E' => \$escape,
   'nowarn' => \$nowarn,
   'help|h' => \$help,
+  'nodefault|N' => \$nodefault,
 );
 
 sub usage {
@@ -28,12 +31,108 @@ sub usage {
   print STDERR "Usage $0 [--nowarn|--escape] execname [rules]\n";
   print STDERR "      $0 --help\n";
   print STDERR "  nowarn:      don't warn if execname does not exist\n";
+  print STDERR "  nodefault:   don't include default rules/ldd output\n";
   print STDERR "  escape:      escape stuff that would be treated as regexs\n";
   print STDERR "  help:        print this message\n";
 }
 
 &usage && exit 0 if ($help || @ARGV < 1);
 
+sub head ($) {
+  my $file = shift;
+
+  my $first = "";
+  if (open(FILE, $file)) {
+    $first = <FILE>;
+    close(FILE);
+  }
+
+  return $first;
+}
+
+sub get_output ($@) {
+  my ($program, @args) = @_;
+
+  my $ret = -1;
+
+  my $pid;
+  my @output;
+
+  if (-x $program) {
+    $pid = open(KID_TO_READ, "-|");
+    unless (defined $pid) {
+      die "can't fork: $!";
+    }
+
+    if ($pid) {
+      while (<KID_TO_READ>) {
+        chomp;
+        push @output, $_;
+      }
+      close(KID_TO_READ);
+      $ret = $?;
+    } else {
+      ($>, $)) = ($<, $();
+      open(STDERR, ">&STDOUT")
+        || die "can't dup stdout to stderr";
+      exec($program, @args) || die "can't exec program: $!";
+
+      # NOTREACHED
+    }
+  }
+
+  return ($ret, @output);
+}
+
+sub gen_default_rules() {
+  gen_file("/etc/ld.so.cache:r");
+
+  # give every profile access to change_hat
+  gen_file("/proc/*/attr/current:w");
+
+  # give every profile access to /dev/urandom (propolice, etc.)
+  gen_file("/dev/urandom:r");
+}
+
+sub gen_elf_binary($) {
+  my $bin = shift;
+
+  my ($ret, @ldd) = get_output("/usr/bin/ldd", $bin);
+  if ($ret == 0) {
+    for my $line (@ldd) {
+      last if $line =~ /not a dynamic executable/;
+      last if $line =~ /cannot read header/;
+      last if $line =~ /statically linked/;
+
+      # avoid new kernel 2.6 poo
+      next if $line =~ /linux-(gate|vdso(32|64)).so/;
+
+      if ($line =~ /^\s*\S+ => (\/\S+)/) {
+        # shared libraries
+        gen_file(realpath($1) . ":mr")
+      } elsif ($line =~ /^\s*(\/\S+)/) {
+        # match loader lines like "/lib64/ld-linux-x86-64.so.2 
(0x00007fbb46999000)"
+       gen_file(realpath($1) . ":rix")
+      }
+    }
+  }
+}
+
+sub gen_binary($) {
+  my $bin = shift;
+
+  gen_file("$bin:r");
+
+  my $hashbang = head($bin);
+  if ($hashbang && $hashbang =~ /^#!\s*(\S+)/) {
+    my $interpreter = $1;
+    gen_file("$interpreter:rix");
+    gen_elf_binary($interpreter);
+  } else {
+    gen_elf_binary($bin)
+  }
+}
+
 sub gen_netdomain($) {
   my $rule = shift;
   # only split on single ':'s
@@ -103,8 +202,10 @@ sub gen_hat($) {
 my $bin = shift @ARGV;
 !(-e $bin || $nowarn) && print STDERR "Warning: execname '$bin': no such file 
or directory\n";
 
-# give every profile/hat access to change_hat
-gen_file("/proc/*/attr/current:w");
+unless ($nodefault) {
+  gen_default_rules();
+  gen_binary($bin);
+}
 
 for my $rule (@ARGV) {
   #($fn, @rules) = split (/:/, $rule);
Index: b/tests/regression/apparmor/environ.sh
===================================================================
--- a/tests/regression/apparmor/environ.sh
+++ b/tests/regression/apparmor/environ.sh
@@ -61,11 +61,11 @@ genprofile ${helper_sh}:Ux
 runchecktest "ENVIRON (shell script): Ux & regular env" pass ${helper_sh} 
FOO=BAR
 runchecktest "ENVIRON (shell script): Ux & sensitive env" fail ${helper_sh} 
LD_LIBRARY_PATH=.
 
-genprofile ${helper_sh}:px -- image=${helper_sh} /bin/bash:rix "/lib*/lib*:mr"
+genprofile ${helper_sh}:px -- image=${helper_sh}
 runchecktest "ENVIRON (shell script): px & regular env" pass ${helper_sh} 
FOO=BAR
 runchecktest "ENVIRON (shell script): px & sensitive env" pass ${helper_sh} 
LD_LIBRARY_PATH=.
 
-genprofile ${helper_sh}:Px -- image=${helper_sh} /bin/bash:rix "/lib*/lib*:mr"
+genprofile ${helper_sh}:Px -- image=${helper_sh}
 runchecktest "ENVIRON (shell script): Px & regular env" pass ${helper_sh} 
FOO=BAR
 runchecktest "ENVIRON (shell script): Px & sensitive env" fail ${helper_sh} 
LD_LIBRARY_PATH=.
 
@@ -73,7 +73,7 @@ genprofile ${helper_sh}:rix /bin/bash:ri
 runchecktest "ENVIRON (shell script): ix & regular env" pass ${helper_sh} 
FOO=BAR
 runchecktest "ENVIRON (shell script): ix & sensitive env" pass ${helper_sh} 
LD_LIBRARY_PATH=.
 
-genprofile image=${helper_sh} /bin/bash:rix "/lib*/lib*:mr"
+genprofile image=${helper_sh}
 runchecktest "ENVIRON (shell script): unconfined --> confined & regular env" 
pass ${helper_sh} FOO=BAR
 runchecktest "ENVIRON (shell script): unconfined --> confined & sensitive env" 
pass ${helper_sh} LD_LIBRARY_PATH=.
 
Index: b/tests/regression/apparmor/prologue.inc
===================================================================
--- a/tests/regression/apparmor/prologue.inc
+++ b/tests/regression/apparmor/prologue.inc
@@ -85,102 +85,6 @@ genrunscript()
        fi
 }
 
-resolve_symlink()
-{
-       if [ -z "${__NO_TRAP_ERR}" ]
-       then
-               trap "error_handler" ERR
-       fi
-
-       local link linkdir targetdir targetname
-
-       link=$1
-
-       while [ -h ${link} ]
-       do
-               if [ -x /usr/bin/readlink ] ; then
-                       target=$(/usr/bin/readlink -f ${link})
-               elif [ -x /bin/readlink ] ; then
-                       target=$(/bin/readlink -f ${link})
-               else 
-                       # I'm sure there's a more perlish way to do this
-                       target=$( perl -e "printf (\"%s\n\", 
readlink(\"${link}\"));") 
-                       #target=$( perl -e "if (\$foo = readlink(\"${link}\")){ 
\
-                       #                       printf (\"%s\n\", \$foo) \
-                       #                   } else { \
-                       #                       print \"${link}\n\"; \
-                       #                   };")
-               fi
-               case "${target}" in
-                       /*)  link=${target}
-                            ;;
-                       *) linkdir=$(dirname ${link})
-                          targetdir=$(dirname ${target})
-                          targetname=$(basename ${target})
-                          linkdir=$(cd ${linkdir}/${targetdir} ; pwd)
-                          link=${linkdir}/${targetname}
-                          ;;
-               esac
-                               
-       done
-
-       if [ -e ${link} ]
-       then
-               echo ${link}
-               return 0
-       else
-               echo "Could not resolve '$link'" >&2
-               return 1
-       fi
-}
-
-resolve_libs()
-{
-       if [ -z "${__NO_TRAP_ERR}" ]
-       then
-               trap "error_handler" ERR
-       fi
-
-       local exec mode libpath libs
-       # global dynlibs
-
-       exec=$1
-
-       if [ ! -x $1 ]
-       then
-               fatalerror "invalid test executable $test"
-       fi
-
-       # Suck. SuSE's ldd has a line "linux-gate.so.1 =>  (0xffffe000)"
-       #       Red Hat's ldd has "/lib/ld-linux.so.2 (0x007b1000)"
-       # good ${DIETY}, what gross kludgage.
-       libs=$(ldd $exec | egrep -v "linux-(vdso(32|64)?|gate).so.1" | sed 
's~^.*=> \(/.*\) (.*$~\1~' | awk '{print $1}')
-
-       dynlibs="/etc/ld.so.cache:r"
-
-       # bleah, this is cheeseball. on systems with a stackguard
-       # compiler, we also need access to /dev/urandom
-       for i in $libs /dev/urandom
-       do
-               mode=rm
-               # resolve possible symlinks before checking for ld pattern
-               # this is necessary because some architectures (zSeries)
-               # use nonconforming ld symlink names, like ld64.so
-               libpath=`resolve_symlink $i`            
-               case $libpath in
-               /lib/ld[.-]*) mode=${mode}px
-                          ;;
-               /lib32/ld[.-]*) mode=${mode}px
-                          ;;
-               /lib64/ld[.-]*) mode=${mode}px
-                          ;;
-               *) mode=${mode}ix
-                          ;;
-               esac
-               dynlibs="$dynlibs ${libpath}:${mode}"
-       done
-}
-
 runtestbg()
 {
        if [ -z "${__NO_TRAP_ERR}" ]
@@ -337,31 +241,21 @@ emit_profile()
                trap "error_handler" ERR
        fi
 
-       local subprofile wflag
+       local wflag
        #global name outfile profile dynlibs profilenames
 
-       subprofile=0
        wflag=""
 
-       case "$1" in 
-               *^*) wflag="--nowarn"
-                    subprofile=1
-                    ;;
-       esac
-
        mkflags="${wflag} ${escapeflag}"
 
-       name=$1; perm=$2; shift 2
-
-       if [ "$subprofile" -eq 1 -o "$nodefaults" -eq 1 ]
+       if [ "$nodefaults" -eq 1 ]
        then
-               # skip dynamic libs for subprofiles
-               $bin/mkprofile.pl ${mkflags} "$name" ${outfile}:w "$@" >> 
$profile
+               mkflags="${mkflags} -N"
+       fi
 
-       else
+       name=$1; perm=$2; shift 2
 
-               $bin/mkprofile.pl ${mkflags} "$name" ${name}:${perm} $dynlibs 
${outfile}:w "$@" >> $profile
-       fi
+       $bin/mkprofile.pl ${mkflags} "$name" ${outfile}:w "$@" >> $profile
 
        echo $name >> $profilenames
 }
@@ -579,12 +473,6 @@ settest()
 
        outfile=$tmpdir/output.$1
 
-       if [ -x $test ]
-       then
-               # build list of dynamic libraries required by this executable
-               resolve_libs $test
-       fi
-
        # Remove any current profile if loaded
        if [ $profileloaded -eq 1 ]
        then


-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to