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
