On 01/12/2012 10:08 AM, Steve Beattie wrote:
> 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.

fix the little niggle below and then
Acked-by: John Johansen <[email protected]>

> ---
>  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")

fix the indent here

> +      }
> +    }
> +  }
> +}
> +
> +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
> 


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

Reply via email to