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