mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 10:07:12 +00:00
currently the equality tests require the tests to PASS as known equality or inequality. Add the ability to add tests that are a known problem and are expected to fail the equality, or inequality test. This is done by using verify_binary_xequality verify_binary_xinequality This allows new tests to be added to document a known issue, without having to develop the fix for the issue. The use of this facility is expected to be temporary, so any test marked as xequality or xinequality will be noisy but not fail the other tests until they are fixed, at which point they will cause the tests to fail to force them to be updated to the correct equality or inequality test. Signed-off-by: John Johansen <john.johansen@canonical.com>
923 lines
38 KiB
Bash
Executable File
923 lines
38 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2013
|
|
# Canonical, Ltd. (All rights reserved)
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of version 2 of the GNU General Public
|
|
# License published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, contact Canonical Ltd.
|
|
#
|
|
|
|
# Tests for post-parser equality among multiple profiles. These tests are
|
|
# useful to verify that keyword aliases, formatting differences, etc., all
|
|
# result in the same parser output.
|
|
|
|
set -o pipefail
|
|
|
|
_SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}" )
|
|
|
|
APPARMOR_PARSER="${APPARMOR_PARSER:-${_SCRIPTDIR}/../apparmor_parser}"
|
|
fails=0
|
|
errors=0
|
|
verbose="${VERBOSE:-}"
|
|
default_features_file="features.all"
|
|
features_file=$default_features_file
|
|
|
|
hash_binary_policy()
|
|
{
|
|
printf %s "$1" | ${APPARMOR_PARSER} --features-file "${_SCRIPTDIR}/features_files/$features_file" -qS 2>/dev/null| md5sum | cut -d ' ' -f 1
|
|
return $?
|
|
}
|
|
|
|
# verify_binary - compares the binary policy of multiple profiles
|
|
# $1: Test type (equality or inequality)
|
|
# $2: A short description of the test
|
|
# $3: The known-good profile
|
|
# $4..$n: The profiles to compare against $3
|
|
#
|
|
# Upon failure/error, prints out the test description and profiles that failed
|
|
# and increments $fails or $errors for each failure and error, respectively
|
|
verify_binary()
|
|
{
|
|
local t=$1
|
|
local desc=$2
|
|
local good_profile=$3
|
|
local good_hash
|
|
local ret=0
|
|
|
|
shift
|
|
shift
|
|
shift
|
|
|
|
if [ "$t" != "equality" ] && [ "$t" != "inequality" ] && \
|
|
[ "$t" != "xequality" ] && [ "$t" != "xinequality" ]
|
|
then
|
|
printf "\nERROR: Unknown test mode:\n%s\n\n" "$t" 1>&2
|
|
((errors++))
|
|
return $((ret + 1))
|
|
fi
|
|
|
|
if [ -n "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
if ! good_hash=$(hash_binary_policy "$good_profile")
|
|
then
|
|
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
printf "\nERROR: Error hashing the following \"known-good\" profile:\n%s\n\n" \
|
|
"$good_profile" 1>&2
|
|
((errors++))
|
|
return $((ret + 1))
|
|
fi
|
|
|
|
for profile in "$@"
|
|
do
|
|
if ! hash=$(hash_binary_policy "$profile")
|
|
then
|
|
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
printf "\nERROR: Error hashing the following profile:\n%s\n\n" \
|
|
"$profile" 1>&2
|
|
((errors++))
|
|
((ret++))
|
|
elif [ "$t" == "equality" ] && [ "$hash" != "$good_hash" ]
|
|
then
|
|
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
printf "\nFAIL: Hash values do not match\n" 2>&1
|
|
printf "known-good (%s) != profile-under-test (%s) for the following profile:\n%s\n\n" \
|
|
"$good_hash" "$hash" "$profile" 1>&2
|
|
((fails++))
|
|
((ret++))
|
|
elif [ "$t" == "xequality" ] && [ "$hash" == "$good_hash" ]
|
|
then
|
|
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
printf "\nunexpected PASS: equality test with known problem, Hash values match\n" 2>&1
|
|
printf "known-good (%s) == profile-under-test (%s) for the following profile:\n%s\n\n" \
|
|
"$good_hash" "$hash" "$profile" 1>&2
|
|
((fails++))
|
|
((ret++))
|
|
elif [ "$t" == "xequality" ] && [ "$hash" != "$good_hash" ]
|
|
then
|
|
printf "\nknown problem %s %s: unchanged" "$t" "$desc" 1>&2
|
|
elif [ "$t" == "inequality" ] && [ "$hash" == "$good_hash" ]
|
|
then
|
|
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
printf "\nFAIL: Hash values match\n" 2>&1
|
|
printf "known-good (%s) == profile-under-test (%s) for the following profile:\n%s\n\n" \
|
|
"$good_hash" "$hash" "$profile" 1>&2
|
|
((fails++))
|
|
((ret++))
|
|
elif [ "$t" == "xinequality" ] && [ "$hash" != "$good_hash" ]
|
|
then
|
|
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
|
printf "\nunexpected PASS: inequality test with known problem, Hash values do not match\n" 2>&1
|
|
printf "known-good (%s) != profile-under-test (%s) for the following profile:\n%s\n\n" \
|
|
"$good_hash" "$hash" "$profile" 1>&2
|
|
((fails++))
|
|
((ret++))
|
|
elif [ "$t" == "xinequality" ] && [ "$hash" == "$good_hash" ]
|
|
then
|
|
printf "\nknown problem %s %s: unchanged" "$t" "$desc" 1>&2
|
|
fi
|
|
done
|
|
|
|
if [ $ret -eq 0 ]
|
|
then
|
|
if [ -z "$verbose" ] ; then
|
|
printf "."
|
|
else
|
|
printf " ok\n"
|
|
|
|
fi
|
|
fi
|
|
return $ret
|
|
}
|
|
|
|
verify_binary_equality()
|
|
{
|
|
verify_binary "equality" "$@"
|
|
}
|
|
|
|
# test we want to be equal but is currently a known problem
|
|
verify_binary_xequality()
|
|
{
|
|
verify_binary "xequality" "$@"
|
|
}
|
|
|
|
verify_binary_inequality()
|
|
{
|
|
verify_binary "inequality" "$@"
|
|
}
|
|
|
|
# test we want to be not equal but is currently a know problem
|
|
verify_binary_xinequality()
|
|
{
|
|
verify_binary "xinequality" "$@"
|
|
}
|
|
|
|
# kernel_features - test whether path(s) are present
|
|
# $@: feature path(s) to test
|
|
# Returns: 0 and outputs "true" if all paths exist
|
|
# 1 and error message if features dir is not available
|
|
# 2 and error message if path does not exist
|
|
kernel_features()
|
|
{
|
|
features_dir="/sys/kernel/security/apparmor/features/"
|
|
if [ ! -e "$features_dir" ] ; then
|
|
echo "Kernel feature masks not supported."
|
|
return 1;
|
|
fi
|
|
|
|
for f in $@ ; do
|
|
if [ ! -e "$features_dir/$f" ] ; then
|
|
# check if feature is in file
|
|
feature=$(basename "$features_dir/$f")
|
|
file=$(dirname "$features_dir/$f")
|
|
if [ -f $file ]; then
|
|
if ! grep -q $feature $file; then
|
|
echo "Required feature '$f' not available."
|
|
return 2;
|
|
fi
|
|
else
|
|
echo "Required feature '$f' not available."
|
|
return 3;
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo "true"
|
|
return 0;
|
|
}
|
|
|
|
##########################################################################
|
|
### wrapper fn, should be indented but isn't to reduce wrap
|
|
verify_set()
|
|
{
|
|
local p1="$1"
|
|
local p2="$2"
|
|
echo -e "\n equality $e of '$p1' vs '$p2'\n"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus send" \
|
|
"/t { $p1 dbus send, }" \
|
|
"/t { $p2 dbus write, }" \
|
|
"/t { $p2 dbus w, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus receive" \
|
|
"/t { $p1 dbus receive, }" \
|
|
"/t { $p2 dbus read, }" \
|
|
"/t { $p2 dbus r, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus send + receive" \
|
|
"/t { $p1 dbus (send, receive), }" \
|
|
"/t { $p2 dbus (read, write), }" \
|
|
"/t { $p2 dbus (r, w), }" \
|
|
"/t { $p2 dbus (rw), }" \
|
|
"/t { $p2 dbus rw, }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus all accesses" \
|
|
"/t { $p1 dbus (send, receive, bind, eavesdrop), }" \
|
|
"/t { $p2 dbus (read, write, bind, eavesdrop), }" \
|
|
"/t { $p2 dbus (r, w, bind, eavesdrop), }" \
|
|
"/t { $p2 dbus (rw, bind, eavesdrop), }" \
|
|
"/t { $p2 dbus (), }" \
|
|
"/t { $p2 dbus, }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus implied accesses with a bus conditional" \
|
|
"/t { $p1 dbus (send, receive, bind, eavesdrop) bus=session, }" \
|
|
"/t { $p2 dbus (read, write, bind, eavesdrop) bus=session, }" \
|
|
"/t { $p2 dbus (r, w, bind, eavesdrop) bus=session, }" \
|
|
"/t { $p2 dbus (rw, bind, eavesdrop) bus=session, }" \
|
|
"/t { $p2 dbus () bus=session, }" \
|
|
"/t { $p2 dbus bus=session, }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for services" \
|
|
"/t { $p1 dbus bind name=com.foo, }" \
|
|
"/t { $p2 dbus name=com.foo, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for messages" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo interface=org.foo, }" \
|
|
"/t { $p2 dbus path=/com/foo interface=org.foo, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for messages with peer names" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo interface=org.foo peer=(name=com.foo), }" \
|
|
"/t { $p2 dbus path=/com/foo interface=org.foo peer=(name=com.foo), }" \
|
|
"/t { $p2 dbus (send, receive) path=/com/foo interface=org.foo peer=(name=(com.foo)), }" \
|
|
"/t { $p2 dbus path=/com/foo interface=org.foo peer=(name=(com.foo)), }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for messages with peer labels" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo interface=org.foo peer=(label=/usr/bin/app), }" \
|
|
"/t { $p2 dbus path=/com/foo interface=org.foo peer=(label=/usr/bin/app), }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus element parsing" \
|
|
"/t { $p1 dbus bus=b path=/ interface=i member=m peer=(name=n label=l), }" \
|
|
"/t { $p2 dbus bus=\"b\" path=\"/\" interface=\"i\" member=\"m\" peer=(name=\"n\" label=\"l\"), }" \
|
|
"/t { $p2 dbus bus=(b) path=(/) interface=(i) member=(m) peer=(name=(n) label=(l)), }" \
|
|
"/t { $p2 dbus bus=(\"b\") path=(\"/\") interface=(\"i\") member=(\"m\") peer=(name=(\"n\") label=(\"l\")), }" \
|
|
"/t { $p2 dbus bus =b path =/ interface =i member =m peer =(name =n label =l), }" \
|
|
"/t { $p2 dbus bus= b path= / interface= i member= m peer= (name= n label= l), }" \
|
|
"/t { $p2 dbus bus = b path = / interface = i member = m peer = ( name = n label = l ), }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus access parsing" \
|
|
"/t { $p1 dbus, }" \
|
|
"/t { $p2 dbus (), }" \
|
|
"/t { $p2 dbus (send, receive, bind, eavesdrop), }" \
|
|
"/t { $p2 dbus (send receive bind eavesdrop), }" \
|
|
"/t { $p2 dbus (send, receive bind, eavesdrop), }" \
|
|
"/t { $p2 dbus (send,receive,bind,eavesdrop), }" \
|
|
"/t { $p2 dbus (send,receive,,,,,,,,,,,,,,,,bind,eavesdrop), }" \
|
|
"/t { $p2 dbus (send,send,send,send send receive,bind eavesdrop), }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus variable expansion" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo member=spork interface=org.foo peer=(name=com.foo label=/com/foo), }" \
|
|
"@{FOO}=foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO} member=spork interface=org.@{FOO} peer=(name=com.@{FOO} label=/com/@{FOO}), }" \
|
|
"@{FOO}=foo
|
|
@{SPORK}=spork
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO} member=@{SPORK} interface=org.@{FOO} peer=(name=com.@{FOO} label=/com/@{FOO}), }" \
|
|
"@{FOO}=/com/foo
|
|
/t { $p2 dbus (send, receive) path=@{FOO} member=spork interface=org.foo peer=(name=com.foo label=@{FOO}), }" \
|
|
"@{FOO}=com
|
|
/t { $p2 dbus (send, receive) path=/@{FOO}/foo member=spork interface=org.foo peer=(name=@{FOO}.foo label=/@{FOO}/foo), }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, multiple values/rules" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo, $p1 dbus (send, receive) path=/com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com/{foo,bar}, }" \
|
|
"/t { $p2 dbus (send, receive) path={/com/foo,/com/bar}, }" \
|
|
"@{FOO}=foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/bar, }" \
|
|
"@{FOO}=foo bar
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=bar foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}={bar,foo}
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=foo
|
|
@{BAR}=bar
|
|
/t { $p2 dbus (send, receive) path=/com/{@{FOO},@{BAR}}, }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, ensure rule de-duping occurs" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo, $p1 dbus (send, receive) path=/com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com/foo, $p2 dbus (send, receive) path=/com/bar, dbus (send, receive) path=/com/bar, }" \
|
|
"@{FOO}=bar foo bar foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=bar foo bar foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/@{FOO}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with all perms" \
|
|
"/t { $p1 dbus, }" \
|
|
"/t { $p2 dbus bus=session, $p2 dbus, }" \
|
|
"/t { $p2 dbus (send, receive, bind, eavesdrop), $p2 dbus, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with bind" \
|
|
"/t { $p1 dbus bind, }" \
|
|
"/t { $p2 dbus bind bus=session, $p2 dbus bind, }" \
|
|
"/t { $p2 dbus bind bus=system name=com.foo, $p2 dbus bind, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with send and a bus conditional" \
|
|
"/t { $p1 dbus send bus=system, }" \
|
|
"/t { $p2 dbus send bus=system path=/com/foo interface=com.foo member=bar, dbus send bus=system, }" \
|
|
"/t { $p2 dbus send bus=system peer=(label=/usr/bin/foo), $p2 dbus send bus=system, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with an audit modifier" \
|
|
"/t { $p1 audit dbus eavesdrop, }" \
|
|
"/t { $p2 audit dbus eavesdrop bus=session, $p2 audit dbus eavesdrop, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with a deny modifier" \
|
|
"/t { $p1 deny dbus send bus=system peer=(name=com.foo), }" \
|
|
"/t { $p2 deny dbus send bus=system peer=(name=com.foo label=/usr/bin/foo), $p2 deny dbus send bus=system peer=(name=com.foo), }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization found in dbus abstractions" \
|
|
"/t { $p1 dbus send bus=session, }" \
|
|
"/t { $p2 dbus send
|
|
bus=session
|
|
path=/org/freedesktop/DBus
|
|
interface=org.freedesktop.DBus
|
|
member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName}
|
|
peer=(name=org.freedesktop.DBus),
|
|
$p2 dbus send bus=session, }"
|
|
|
|
# verify slash filtering for dbus paths.
|
|
verify_binary_equality "'$p1'x'$p2' dbus slash filtering for paths" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo, $p1 dbus (send, receive) path=/com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com///foo, $p2 dbus (send, receive) path=///com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com//{foo,bar}, }" \
|
|
"/t { $p2 dbus (send, receive) path={//com/foo,/com//bar}, }" \
|
|
"@{FOO}=/foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/bar, }" \
|
|
"@{FOO}=/foo /bar
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=/bar //foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=//{bar,foo}
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=/foo
|
|
@{BAR}=bar
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com//@{BAR}, }"
|
|
|
|
# Rules compatible with audit, deny, and audit deny
|
|
# note: change_profile does not support audit/allow/deny atm
|
|
for rule in "capability" "capability mac_admin" \
|
|
"mount" "mount /a" "mount /a -> /b" "mount options in (ro) /a -> b" \
|
|
"remount" "remount /a" \
|
|
"umount" "umount /a" \
|
|
"pivot_root" "pivot_root /a" "pivot_root oldroot=/" \
|
|
"pivot_root oldroot=/ /a" "pivot_root oldroot=/ /a -> foo" \
|
|
"ptrace" "ptrace trace" "ptrace (readby,tracedby) peer=unconfined" \
|
|
"signal" "signal (send,receive)" "signal peer=unconfined" \
|
|
"signal receive set=(kill)" \
|
|
"dbus" "dbus send" "dbus bus=system" "dbus bind name=foo" \
|
|
"dbus peer=(label=foo)" "dbus eavesdrop" \
|
|
"unix" "unix (create, listen, accept)" "unix addr=@*" "unix addr=none" \
|
|
"unix peer=(label=foo)" \
|
|
"/f r" "/f w" "/f rwmlk" "/** r" "/**/ w" \
|
|
"file /f r" "file /f w" "file /f rwmlk" \
|
|
"link /a -> /b" "link subset /a -> /b" \
|
|
"l /a -> /b" "l subset /a -> /b" \
|
|
"file l /a -> /b" "l subset /a -> /b"
|
|
do
|
|
verify_binary_equality "'$p1'x'$p2' allow modifier for \"${rule}\"" \
|
|
"/t { $p1 ${rule}, }" \
|
|
"/t { $p2 allow ${rule}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' audit allow modifier for \"${rule}\"" \
|
|
"/t { $p1 audit ${rule}, }" \
|
|
"/t { $p2 audit allow ${rule}, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' audit, deny, and audit deny modifiers for \"${rule}\"" \
|
|
"/t { $p1 ${rule}, }" \
|
|
"/t { $p2 audit ${rule}, }" \
|
|
"/t { $p2 audit allow ${rule}, }" \
|
|
"/t { $p2 deny ${rule}, }" \
|
|
"/t { $p2 audit deny ${rule}, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' audit vs deny and audit deny modifiers for \"${rule}\"" \
|
|
"/t { $p1 audit ${rule}, }" \
|
|
"/t { $p2 deny ${rule}, }" \
|
|
"/t { $p2 audit deny ${rule}, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' deny and audit deny modifiers for \"${rule}\"" \
|
|
"/t { $p1 deny ${rule}, }" \
|
|
"/t { $p2 audit deny ${rule}, }"
|
|
done
|
|
|
|
####### special case for network TODO: for network above when network
|
|
####### rules fixed
|
|
for rule in "network" "network tcp" "network inet6 tcp"
|
|
do
|
|
verify_binary_equality "allow modifier for \"${rule}\"" \
|
|
"/t { ${rule}, }" \
|
|
"/t { allow ${rule}, }"
|
|
|
|
verify_binary_equality "audit allow modifier for \"${rule}\"" \
|
|
"/t { audit ${rule}, }" \
|
|
"/t { audit allow ${rule}, }"
|
|
|
|
verify_binary_inequality "audit, deny, and audit deny modifiers for \"${rule}\"" \
|
|
"/t { ${rule}, }" \
|
|
"/t { audit ${rule}, }" \
|
|
"/t { audit allow ${rule}, }" \
|
|
"/t { deny ${rule}, }" \
|
|
"/t { audit deny ${rule}, }"
|
|
|
|
verify_binary_inequality "audit vs deny and audit deny modifiers for \"${rule}\"" \
|
|
"/t { audit ${rule}, }" \
|
|
"/t { deny ${rule}, }" \
|
|
"/t { audit deny ${rule}, }"
|
|
|
|
verify_binary_inequality "deny and audit deny modifiers for \"${rule}\"" \
|
|
"/t { deny ${rule}, }" \
|
|
"/t { audit deny ${rule}, }"
|
|
done
|
|
|
|
# Rules that need special treatment for the deny modifier
|
|
for rule in "/f ux" "/f Ux" "/f px" "/f Px" "/f cx" "/f Cx" "/f ix" \
|
|
"/f pux" "/f Pux" "/f pix" "/f Pix" \
|
|
"/f cux" "/f Cux" "/f cix" "/f Cix" \
|
|
"/* ux" "/* Ux" "/* px" "/* Px" "/* cx" "/* Cx" "/* ix" \
|
|
"/* pux" "/* Pux" "/* pix" "/* Pix" \
|
|
"/* cux" "/* Cux" "/* cix" "/* Cix" \
|
|
"/f px -> b " "/f Px -> b" "/f cx -> b" "/f Cx -> b" \
|
|
"/f pux -> b" "/f Pux -> b" "/f pix -> b" "/f Pix -> b" \
|
|
"/f cux -> b" "/f Cux -> b" "/f cix -> b" "/f Cix -> b" \
|
|
"/* px -> b" "/* Px -> b" "/* cx -> b" "/* Cx -> b" \
|
|
"/* pux -> b" "/* Pux -> b" "/* pix -> b" "/* Pix -> b" \
|
|
"/* cux -> b" "/* Cux -> b" "/* cix -> b" "/* Cix -> b" \
|
|
"file /f ux" "file /f Ux" "file /f px" "file /f Px" \
|
|
"file /f cx" "file /f Cx" "file /f ix" \
|
|
"file /f pux" "file /f Pux" "file /f pix" "file /f Pix" \
|
|
"/f cux" "/f Cux" "/f cix" "/f Cix" \
|
|
"file /* ux" "file /* Ux" "file /* px" "file /* Px" \
|
|
"file /* cx" "file /* Cx" "file /* ix" \
|
|
"file /* pux" "file /* Pux" "file /* pix" "file /* Pix" \
|
|
"file /* cux" "file /* Cux" "file /* cix" "file /* Cix" \
|
|
"file /f px -> b " "file /f Px -> b" "file /f cx -> b" "file /f Cx -> b" \
|
|
"file /f pux -> b" "file /f Pux -> b" "file /f pix -> b" "file /f Pix -> b" \
|
|
"file /f cux -> b" "file /f Cux -> b" "file /f cix -> b" "file /f Cix -> b" \
|
|
"file /* px -> b" "file /* Px -> b" "file /* cx -> b" "file /* Cx -> b" \
|
|
"file /* pux -> b" "file /* Pux -> b" "file /* pix -> b" "file /* Pix -> b" \
|
|
"file /* cux -> b" "file /* Cux -> b" "file /* cix -> b" "file /* Cix -> b"
|
|
|
|
do
|
|
verify_binary_equality "'$p1'x'$p2' allow modifier for \"${rule}\"" \
|
|
"/t { $p1 ${rule}, }" \
|
|
"/t { $p2 allow ${rule}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' audit allow modifier for \"${rule}\"" \
|
|
"/t { $p1 audit ${rule}, }" \
|
|
"/t { $p2 audit allow ${rule}, }"
|
|
|
|
# skip rules that don't end with x perm
|
|
if [ -n "${rule##*x}" ] ; then continue ; fi
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' deny, audit deny modifier for \"${rule}\"" \
|
|
"/t { $p1 ${rule}, }" \
|
|
"/t { $p2 audit ${rule}, }" \
|
|
"/t { $p2 audit allow ${rule}, }" \
|
|
"/t { $p2 deny ${rule% *} x, }" \
|
|
"/t { $p2 audit deny ${rule% *} x, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' audit vs deny and audit deny modifiers for \"${rule}\"" \
|
|
"/t { $p1 audit ${rule}, }" \
|
|
"/t { $p2 deny ${rule% *} x, }" \
|
|
"/t { $p2 audit deny ${rule% *} x, }"
|
|
|
|
done
|
|
|
|
# verify deny and audit deny differ for x perms
|
|
for prefix in "/f" "/*" "file /f" "file /*" ; do
|
|
verify_binary_inequality "'$p1'x'$p2' deny and audit deny x modifiers for \"${prefix}\"" \
|
|
"/t { $p1 deny ${prefix} x, }" \
|
|
"/t { $p2 audit deny ${prefix} x, }"
|
|
done
|
|
|
|
#Test equality of leading and trailing file permissions
|
|
for audit in "" "audit" ; do
|
|
for allow in "" "allow" "deny" ; do
|
|
for owner in "" "owner" ; do
|
|
for f in "" "file" ; do
|
|
prefix="$audit $allow $owner $f"
|
|
for perm in "r" "w" "a" "l" "k" "m" "rw" "ra" \
|
|
"rl" "rk" "rm" "wl" "wk" "wm" \
|
|
"rwl" "rwk" "rwm" "ral" "rak" \
|
|
"ram" "rlk" "rlm" "rkm" "wlk" \
|
|
"wlm" "wkm" "alk" "alm" "akm" \
|
|
"lkm" "rwlk" "rwlm" "rwkm" \
|
|
"ralk" "ralm" "wlkm" "alkm" \
|
|
"rwlkm" "ralkm" ; do
|
|
verify_binary_equality "'$p1'x'$p2' leading and trailing perms for \"${perm}\"" \
|
|
"/t { $p1 ${prefix} /f ${perm}, }" \
|
|
"/t { $p2 ${prefix} ${perm} /f, }"
|
|
done
|
|
if [ "$allow" == "deny" ] ; then continue ; fi
|
|
for perm in "ux" "Ux" "px" "Px" "cx" "Cx" \
|
|
"ix" "pux" "Pux" "pix" "Pix" \
|
|
"cux" "Cux" "cix" "Cix"
|
|
do
|
|
verify_binary_equality "'$p1'x'$p2' leading and trailing perms for \"${perm}\"" \
|
|
"/t { $p1 ${prefix} /f ${perm}, }" \
|
|
"/t { $p2 ${prefix} ${perm} /f, }"
|
|
done
|
|
for perm in "px" "Px" "cx" "Cx" \
|
|
"pux" "Pux" "pix" "Pix" \
|
|
"cux" "Cux" "cix" "Cix"
|
|
do
|
|
verify_binary_equality "'$p1'x'$p2' leading and trailing perms for x-transition \"${perm}\"" \
|
|
"/t { $p1 ${prefix} /f ${perm} -> b, }" \
|
|
"/t { $p2 ${prefix} ${perm} /f -> b, }"
|
|
done
|
|
done
|
|
done
|
|
done
|
|
done
|
|
|
|
#Test rule overlap for x most specific match
|
|
for perm1 in "ux" "Ux" "px" "Px" "cx" "Cx" "ix" "pux" "Pux" \
|
|
"pix" "Pix" "cux" "Cux" "cix" "Cix" "px -> b" \
|
|
"Px -> b" "cx -> b" "Cx -> b" "pux -> b" "Pux ->b" \
|
|
"pix -> b" "Pix -> b" "cux -> b" "Cux -> b" \
|
|
"cix -> b" "Cix -> b"
|
|
do
|
|
for perm2 in "ux" "Ux" "px" "Px" "cx" "Cx" "ix" "pux" "Pux" \
|
|
"pix" "Pix" "cux" "Cux" "cix" "Cix" "px -> b" \
|
|
"Px -> b" "cx -> b" "Cx -> b" "pux -> b" "Pux ->b" \
|
|
"pix -> b" "Pix -> b" "cux -> b" "Cux -> b" \
|
|
"cix -> b" "Cix -> b"
|
|
do
|
|
if [ "$perm1" == "$perm2" ] ; then
|
|
verify_binary_equality "'$p1'x'$p2' Exec perm \"${perm1}\" - most specific match: same as glob" \
|
|
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
|
|
"/t { $p2 /* ${perm1}, }"
|
|
else
|
|
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs \"${perm2}\" - most specific match: different from glob" \
|
|
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
|
|
"/t { $p2 /* ${perm1}, }"
|
|
fi
|
|
done
|
|
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
|
|
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
|
|
"/t { $p2 /* ${perm1}, }"
|
|
|
|
done
|
|
|
|
#Test deny carves out permission
|
|
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
|
|
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
|
"/t { $p2 /foo/[abc] r, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
|
|
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
|
"/t { $p2 /foo/[ac] r, }"
|
|
|
|
#this one may not be true in the future depending on if the compiled profile
|
|
#is explicitly including deny permissions for dynamic composition
|
|
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
|
|
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
|
|
"/t { $p2 /foo/[abc] r, }"
|
|
|
|
|
|
verify_binary_equality "'$p1'x'$p2' change_profile == change_profile -> **" \
|
|
"/t { $p1 change_profile, }" \
|
|
"/t { $p2 change_profile -> **, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
|
"/t { $p1 change_profile /**, }" \
|
|
"/t { $p2 change_profile /** -> **, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
|
"/t { $p1 change_profile unsafe /**, }" \
|
|
"/t { $p2 change_profile unsafe /** -> **, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
|
"/t { $p1 change_profile /**, }" \
|
|
"/t { $p2 change_profile safe /** -> **, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
|
"/t { $p1 change_profile /**, }" \
|
|
"/t { $p2 change_profile unsafe /**, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' profile name is hname in rule" \
|
|
":ns:/hname { $p1 signal peer=/hname, }" \
|
|
":ns:/hname { $p2 signal peer=@{profile_name}, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' profile name is NOT fq name in rule" \
|
|
":ns:/hname { $p1 signal peer=:ns:/hname, }" \
|
|
":ns:/hname { $p2 signal peer=@{profile_name}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' profile name is hname in sub pofile rule" \
|
|
":ns:/hname { profile child { $p1 signal peer=/hname//child, } }" \
|
|
":ns:/hname { profile child { $p2 signal peer=@{profile_name}, } }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' profile name is NOT fq name in sub profile rule" \
|
|
":ns:/hname { profile child { $p1 signal peer=:ns:/hname//child, } }" \
|
|
":ns:/hname { profile child { $p2 signal peer=@{profile_name}, } }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' profile name is hname in hat rule" \
|
|
":ns:/hname { ^child { $p1 signal peer=/hname//child, } }" \
|
|
":ns:/hname { ^child { $p2 signal peer=@{profile_name}, } }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' profile name is NOT fq name in hat rule" \
|
|
":ns:/hname { ^child { $p1 signal peer=:ns:/hname//child, } }" \
|
|
":ns:/hname { ^child { $p2 signal peer=@{profile_name}, } }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer" \
|
|
"/{a,b} { $p1 signal peer=/\{a,b\}, }" \
|
|
"/{a,b} { $p2 signal peer=@{profile_name}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with pattern" \
|
|
"/{a,b} { $p1 signal peer={/\{a,b\},c}, }" \
|
|
"/{a,b} { $p2 signal peer={@{profile_name},c}, }"
|
|
|
|
verify_binary_inequality "'$p1'x'$p2' @{profile_name} is not pattern in peer" \
|
|
"/{a,b} { $p1 signal peer=/{a,b}, }" \
|
|
"/{a,b} { $p2 signal peer=@{profile_name}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with esc sequence" \
|
|
"/\\\\a { $p1 signal peer=/\\\\a, }" \
|
|
"/\\\\a { $p2 signal peer=@{profile_name}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with esc alt sequence" \
|
|
"/\\{a,b\\},c { $p1 signal peer=/\\{a,b\\},c, }" \
|
|
"/\\{a,b\\},c { $p2 signal peer=@{profile_name}, }"
|
|
|
|
|
|
|
|
# Unfortunately we can not just compare an empty profile and hat to a
|
|
# ie. "/t { ^test { /f r, }}"
|
|
# to the second profile with the equivalent rule inserted manually
|
|
# because policy write permission "w" actually expands to multiple permissions
|
|
# under the hood, and the parser is not adding those permissions
|
|
# to the rules it auto generates
|
|
# So we insert the rule with "append" permissions, and rely on the parser
|
|
# merging permissions of rules.
|
|
# If the parser isn't adding the rules "append" is not equivalent to
|
|
# the "write" permission in the second profile and the test will fail.
|
|
# If the parser is adding the change_hat proc attr rules then the
|
|
# rules should merge and be equivalent.
|
|
verify_binary_equality "'$p1'x'$p2' change_hat rules automatically inserted"\
|
|
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
|
|
"/t { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
|
|
|
|
# verify slash filtering for unix socket address paths.
|
|
# see https://bugs.launchpad.net/apparmor/+bug/1856738
|
|
verify_binary_equality "'$p1'x'$p2' unix rules addr conditional" \
|
|
"/t { $p1 unix bind addr=@/a/bar, }" \
|
|
"/t { $p2 unix bind addr=@/a//bar, }" \
|
|
"/t { $p2 unix bind addr=@//a/bar, }" \
|
|
"/t { $p2 unix bind addr=@/a///bar, }" \
|
|
"@{HOME}=/a/
|
|
/t { $p2 unix bind addr=@@{HOME}/bar, }" \
|
|
"@{HOME}=/a/
|
|
/t { $p2 unix bind addr=@//@{HOME}bar, }" \
|
|
"@{HOME}=/a/
|
|
/t { $p2 unix bind addr=@/@{HOME}/bar, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' unix rules peer addr conditional" \
|
|
"/t { $p1 unix peer=(addr=@/a/bar), }" \
|
|
"/t { $p2 unix peer=(addr=@/a//bar), }" \
|
|
"/t { $p2 unix peer=(addr=@//a/bar), }" \
|
|
"/t { $p2 unix peer=(addr=@/a///bar), }" \
|
|
"@{HOME}=/a/
|
|
/t { $p2 unix peer=(addr=@@{HOME}/bar), }" \
|
|
"@{HOME}=/a/
|
|
/t { $p2 unix peer=(addr=@//@{HOME}bar), }" \
|
|
"@{HOME}=/a/
|
|
/t { $p2 unix peer=(addr=@/@{HOME}/bar), }"
|
|
|
|
# verify slash filtering for mount rules
|
|
verify_binary_equality "'$p1'x'$p2' mount rules slash filtering" \
|
|
"/t { $p1 mount /dev/foo -> /mnt/bar, }" \
|
|
"/t { $p2 mount ///dev/foo -> /mnt/bar, }" \
|
|
"/t { $p2 mount /dev/foo -> /mnt//bar, }" \
|
|
"/t { $p2 mount /dev///foo -> ////mnt/bar, }" \
|
|
"@{MNT}=/mnt/
|
|
/t { $p2 mount /dev///foo -> @{MNT}/bar, }" \
|
|
"@{FOO}=/foo
|
|
/t { $p2 mount /dev//@{FOO} -> /mnt/bar, }"
|
|
|
|
# verify slash filtering for link rules
|
|
verify_binary_equality "'$p1'x'$p2' link rules slash filtering" \
|
|
"/t { $p1 link /dev/foo -> /mnt/bar, }" \
|
|
"/t { $p2 link ///dev/foo -> /mnt/bar, }" \
|
|
"/t { $p2 link /dev/foo -> /mnt//bar, }" \
|
|
"/t { $p2 link /dev///foo -> ////mnt/bar, }" \
|
|
"@{BAR}=/mnt/
|
|
/t { $p2 link /dev///foo -> @{BAR}/bar, }" \
|
|
"@{FOO}=/dev/
|
|
/t { $p2 link @{FOO}//foo -> /mnt/bar, }" \
|
|
"@{FOO}=/dev/
|
|
@{BAR}=/mnt/
|
|
/t { $p2 link @{FOO}/foo -> @{BAR}/bar, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' attachment slash filtering" \
|
|
"/t /bin/foo { }" \
|
|
"/t /bin//foo { }" \
|
|
"@{BAR}=/bin/
|
|
/t @{BAR}/foo { }" \
|
|
"@{FOO}=/foo
|
|
/t /bin/@{FOO} { }" \
|
|
"@{BAR}=/bin/
|
|
@{FOO}=/foo
|
|
/t @{BAR}/@{FOO} { }"
|
|
|
|
# verify comment at end of variable assignment is not treated as a value
|
|
verify_binary_equality "comment at end of set var" \
|
|
"/t { /bin/ r, }" \
|
|
"@{BAR}=/bin/ #a tail comment
|
|
/t { @{BAR} r, }"
|
|
|
|
verify_binary_equality "value like comment at end of set var" \
|
|
"/t { /{bin/,#value} r, }" \
|
|
"@{BAR}=bin/ \#value
|
|
/t { /@{BAR} r, }"
|
|
|
|
|
|
# This can potentially fail as ideally it requires a better dfa comparison
|
|
# routine as it can generates hormomorphic dfas. The enumeration of the
|
|
# dfas dumped will be different, even if the binary is the same
|
|
# Note: this test in the future will require -O filter-deny and
|
|
# -O minimize and -O remove-unreachable.
|
|
verify_binary_equality "'$p1'x'$p2' mount specific deny doesn't affect non-overlapping" \
|
|
"/t { $p1 mount options=bind /e/ -> /**, }" \
|
|
"/t { $p2 audit deny mount /s/** -> /**,
|
|
mount options=bind /e/ -> /**, }"
|
|
|
|
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
|
|
then
|
|
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
|
exit $((fails + errors))
|
|
fi
|
|
|
|
|
|
## priority override equivalence tests
|
|
## compare single rule, to multi-rule profile where one rule overrides
|
|
## the other rule via priority.
|
|
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, multiple values/rules" \
|
|
"/t { dbus (send, receive) path=/com/foo, }" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo, $p2 dbus (send, receive) path=/com/foo, }" \
|
|
"@{FOO}=foo
|
|
/t { $p1 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/foo, }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, ensure rule de-duping occurs" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, dbus (send, receive) path=/com/bar, }" \
|
|
"@{FOO}=bar foo bar foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=bar foo bar foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/@{FOO}, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with all perms" \
|
|
"/t { $p1 dbus, }" \
|
|
"/t { $p2 dbus bus=session, $p2 dbus, }" \
|
|
"/t { $p2 dbus (send, receive, bind, eavesdrop), $p2 dbus, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with bind" \
|
|
"/t { $p1 dbus bind, }" \
|
|
"/t { $p2 dbus bind bus=session, $p2 dbus bind, }" \
|
|
"/t { $p2 dbus bind bus=system name=com.foo, $p2 dbus bind, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with send and a bus conditional" \
|
|
"/t { $p1 dbus send bus=system, }" \
|
|
"/t { $p2 dbus send bus=system path=/com/foo interface=com.foo member=bar, dbus send bus=system, }" \
|
|
"/t { $p2 dbus send bus=system peer=(label=/usr/bin/foo), $p2 dbus send bus=system, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with an audit modifier" \
|
|
"/t { $p1 audit dbus eavesdrop, }" \
|
|
"/t { $p2 audit dbus eavesdrop bus=session, $p2 audit dbus eavesdrop, }"
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization with a deny modifier" \
|
|
"/t { $p1 deny dbus send bus=system peer=(name=com.foo), }" \
|
|
"/t { $p2 deny dbus send bus=system peer=(name=com.foo label=/usr/bin/foo), $p2 deny dbus send bus=system peer=(name=com.foo), }" \
|
|
|
|
verify_binary_equality "'$p1'x'$p2' dbus minimization found in dbus abstractions" \
|
|
"/t { $p1 dbus send bus=session, }" \
|
|
"/t { $p2 dbus send
|
|
bus=session
|
|
path=/org/freedesktop/DBus
|
|
interface=org.freedesktop.DBus
|
|
member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName}
|
|
peer=(name=org.freedesktop.DBus),
|
|
$p2 dbus send bus=session, }"
|
|
|
|
# verify slash filtering for dbus paths.
|
|
verify_binary_equality "'$p1'x'$p2' dbus slash filtering for paths" \
|
|
"/t { $p1 dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com///foo, dbus (send, receive) path=///com/bar, }" \
|
|
"/t { $p2 dbus (send, receive) path=/com//{foo,bar}, }" \
|
|
"/t { $p2 dbus (send, receive) path={//com/foo,/com//bar}, }" \
|
|
"@{FOO}=/foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/bar, }" \
|
|
"@{FOO}=/foo /bar
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=/bar //foo
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=//{bar,foo}
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
|
"@{FOO}=/foo
|
|
@{BAR}=bar
|
|
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com//@{BAR}, }"
|
|
|
|
|
|
|
|
#### end of wrapper fn
|
|
}
|
|
|
|
|
|
printf "Equality Tests:\n"
|
|
|
|
#rules that don't support priority
|
|
|
|
# verify rlimit data conversions
|
|
verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
|
"/t { set rlimit rttime <= 12 weeks, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7)) days, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7 * 24)) hours, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60)) minutes, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60)) seconds, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000)) ms, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)) us, }" \
|
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)), }"
|
|
|
|
verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
|
"/t { set rlimit cpu <= 42 weeks, }" \
|
|
"/t { set rlimit cpu <= $((42 * 7)) days, }" \
|
|
"/t { set rlimit cpu <= $((42 * 7 * 24)) hours, }" \
|
|
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60)) minutes, }" \
|
|
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)) seconds, }" \
|
|
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)), }"
|
|
|
|
verify_binary_equality "set rlimit memlock <= 2GB" \
|
|
"/t { set rlimit memlock <= 2GB, }" \
|
|
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
|
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
|
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }"
|
|
|
|
run_port_range=$(kernel_features network_v8/af_inet)
|
|
if [ "$run_port_range" != "true" ]; then
|
|
echo -e "\nSkipping network af_inet tests. $run_port_range\n"
|
|
else
|
|
# network port range
|
|
# select features file that contains netv8 af_inet
|
|
features_file="features.af_inet"
|
|
verify_binary_equality "network port range" \
|
|
"/t { network port=3456-3460, }" \
|
|
"/t { network port=3456, \
|
|
network port=3457, \
|
|
network port=3458, \
|
|
network port=3459, \
|
|
network port=3460, }"
|
|
|
|
verify_binary_equality "network peer port range" \
|
|
"/t { network peer=(port=3456-3460), }" \
|
|
"/t { network peer=(port=3456), \
|
|
network peer=(port=3457), \
|
|
network peer=(port=3458), \
|
|
network peer=(port=3459), \
|
|
network peer=(port=3460), }"
|
|
|
|
verify_binary_inequality "network port range allows more than single port" \
|
|
"/t { network port=3456-3460, }" \
|
|
"/t { network port=3456, }"
|
|
|
|
verify_binary_inequality "network peer port range allows more than single port" \
|
|
"/t { network peer=(port=3456-3460), }" \
|
|
"/t { network peer=(port=3456), }"
|
|
# return to default
|
|
features_file=$default_features_file
|
|
fi
|
|
|
|
# verify combinations of different priority levels
|
|
# for single rule comparisons, rules should keep same expected result
|
|
# even when the priorities are different.
|
|
# different priorities within a profile comparison resulting in
|
|
# different permission could affected expected results
|
|
|
|
|
|
priorities="none 0 1 -1"
|
|
|
|
for pri1 in $priorities ; do
|
|
if [ "$pri1" = "none" ] ; then
|
|
priority1=""
|
|
else
|
|
priority1="priority=$pri1"
|
|
fi
|
|
for pri2 in $priorities ; do
|
|
if [ "$pri2" = "none" ] ; then
|
|
priority2=""
|
|
else
|
|
priority2="priority=$pri2"
|
|
fi
|
|
|
|
verify_set "$priority1" "$priority2"
|
|
done
|
|
done
|
|
|
|
[ -z "${verbose}" ] && printf "\n"
|
|
printf "PASS\n"
|
|
exit 0
|