apparmor/parser/tst/caching.sh
Steve Beattie 2fec3758ed Subject: [patch] fix apparmor cache tempfile location to use passed arg v2
Merge from trunk revision 2142

This patch fixes problems in the handling of both the final cache
name location and the temporary cache file when an alternate location
is specified.

The first issue is that if the alternate cache directory location was
specified, the alternate directory name would be used as the final
location for the cache file, rather than the alternate directory +
the basename of the profile.

The second issue is that it would generate the temporary file that it
stores the cache file in [basedir]/cache even if an alternate cache
location was specified on the command line. This causes a problem
if [basedir]/cache is on a separate device than the alternate cache
location, because the rename() of the tempfile into the final location
would fail (which the parser would not check the return code of).

This patch fixes the above by incorporating the basename into the cache
file name if the alternate cache location has been specified, bases the
temporary cache file name on the destination cache name (such that they
end up in the same directory), and finally detects if the rename fails
and unlinks the temporary file if that happens (rather than leave it
around). It also has been updated to add a couple of testcases to verify
that writing and reading from an alternate cache location work.

Patch history:
  v1: first draft of patch
  v2: add testcases, convert PERROR() to pwarn() if rename() fails for
      placing cachefile into place.

For 2.8 branch:

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-07-29 09:52:18 -07:00

171 lines
6.7 KiB
Bash
Executable file

#!/bin/bash
# These tests will stop running as soon as a failure is seen since they tend to build
# on the actions and results of the prior tests.
set -e
# This test requires introspection
if [ ! -d /sys/kernel/security/apparmor ]; then
echo "WARNING: /sys/kernel/security/apparmor does not exist. Skipping tests"
echo "requiring introspection."
exit 0
fi
# fake base directory
basedir=$(mktemp -d -t aa-cache-XXXXXX)
altcachedir=$(mktemp -d -t aa-alt-cache-XXXXXXXX)
trap "rm -rf $basedir $altcachedir" EXIT
mkdir -p $basedir/cache
ARGS="--base $basedir --skip-kernel-load"
profile=sbin.pingy
cp caching.profile $basedir/$profile
# Detect and slow down cache test when filesystem can't represent nanosecond delays.
timeout=0.1
_count=10
for ((i = 0; i < ${_count} ; i++)) ; do
touch $basedir/test${i}
sleep $timeout
done
TIMES=$(stat $basedir/test* -c %z | cut -d" " -f2 | cut -d: -f3 | sort -u | wc -l)
if [ $TIMES -ne ${_count} ]; then
echo "WARNING: $basedir lacks nanosecond timestamp resolution, falling back to slower test"
timeout=1
fi
rm -f $basedir/test*
echo -n "Profiles are not cached by default: "
../apparmor_parser $ARGS -q -r $basedir/$profile
[ -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile exists)" && exit 1
echo "ok"
echo -n "Profiles are not cached when using --skip-cache: "
../apparmor_parser $ARGS -q --write-cache --skip-cache -r $basedir/$profile
[ -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile exists)" && exit 1
echo "ok"
sleep $timeout
echo -n "Profiles are cached when requested: "
../apparmor_parser $ARGS -q --write-cache -r $basedir/$profile
[ ! -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile does not exist)" && exit 1
echo "ok"
read_features_dir()
{
directory="$1"
if [ ! -d "$directory" ] ; then
return
fi
for f in `ls -AU "$directory"` ; do
if [ -f "$directory/$f" ] ; then
read -r -d "" KF < "$directory/$f" || true
echo -e "$f {$KF\n}"
elif [ -d "$directory/$f" ] ; then
echo -n "$f {"
KF=`read_features_dir "$directory/$f" "$KF"` || true
echo "$KF"
echo -e "}"
fi
done
}
echo -n "Kernel features are written to cache: "
[ ! -f $basedir/cache/.features ] && echo "FAIL ($basedir/cache/.features missing)" && exit 1
read -r -d "" CF < $basedir/cache/.features || true
if [ -d /sys/kernel/security/apparmor/features ] ; then
KF=`read_features_dir /sys/kernel/security/apparmor/features`
else
read -r -d "" KF < /sys/kernel/security/apparmor/features || true
fi
[ "$CF" != "$KF" ] && echo -e "FAIL (feature text mismatch:\n cache '$CF'\nvs\n kernel '$KF')" && exit 1
echo "ok"
echo -n "Cache is loaded when it exists and features match: "
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache is not loaded when skipping is requested: "
../apparmor_parser $ARGS -v --skip-read-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
../apparmor_parser $ARGS -v --skip-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when features do not match cache: "
echo -n "monkey" > $basedir/cache/.features
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache writing is skipped when features do not match and not cleared: "
rm $basedir/cache/$profile
../apparmor_parser $ARGS -v --write-cache --skip-bad-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
[ -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile exists)" && exit 1
echo "ok"
rm -f $basedir/cache/.features || true
rm -f $basedir/cache/$profile || true
echo -n "monkey" > $basedir/cache/.features
echo -n "monkey" > $basedir/cache/$profile
echo -n "monkey" > $basedir/cache/monkey
../apparmor_parser $ARGS -v --write-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "Cache clear setup FAIL"; exit 1; }
echo -n "Cache clear updates features: "
echo -n "monkey" | diff -q $basedir/cache/.features - | grep -q 'differ' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache clear writes updated profile: "
echo -n "monkey" | diff -q $basedir/cache/$profile - | grep -q 'differ' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache clear cleans out all files: "
[ -f $basedir/cache/monkey ] && { echo "FAIL"; exit 1; }
echo "ok"
rm -f $basedir/cache/monkey
rm -f $basedir/cache/.features || true
rm -f $basedir/cache/$profile || true
echo -n "monkey" > $basedir/cache/.features
echo -n "monkey" > $basedir/cache/$profile
echo -n "monkey" > $basedir/cache/monkey
echo -n "Cache purge remove profiles unconditionally: "
../apparmor_parser $ARGS -v --purge-cache -r $basedir/$profile || { echo "Cache purge setup FAIL"; exit 1; }
[ -f $basedir/cache/.features ] && { echo "FAIL"; exit 1; }
[ -f $basedir/cache/$profile ] && { echo "FAIL"; exit 1; }
[ -f $basedir/cache/monkey ] && { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Profiles are cached when requested (again): "
rm -f $basedir/cache/.features || true
rm -f $basedir/cache/$profile || true
../apparmor_parser $ARGS -q --write-cache -r $basedir/$profile
[ ! -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile does not exist)" && exit 1
echo "ok"
echo -n "Cache reading is skipped when profile is newer: "
sleep $timeout
touch $basedir/$profile
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache is used when cache is newer: "
sleep $timeout
touch $basedir/cache/$profile
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when parser is newer: "
mkdir $basedir/parser
cp ../apparmor_parser $basedir/parser/
$basedir/parser/apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when parser in \$PATH is newer: "
(PATH=$basedir/parser/ /bin/sh -c "apparmor_parser $ARGS -v -r $basedir/$profile") | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Profiles are cached in alternate location when requested: "
../apparmor_parser $ARGS -q --write-cache --cache-loc $altcachedir -r $basedir/$profile
[ ! -f $altcachedir/$profile ] && echo "FAIL ($altcachedir/$profile does not exist)" && exit 1
echo "ok"
echo -n "Cache is loaded from alt location when it exists and features match: "
../apparmor_parser $ARGS -v -r $basedir/$profile --cache-loc $altcachedir | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
echo "ok"