Tests abstract UNIX domain sockets with various combinations of implied permissions, explicit permissions, and conditionals. It also tests with bad permissions and conditionals.
Signed-off-by: Tyler Hicks <[email protected]> --- tests/regression/apparmor/unix_socket.sh | 176 ++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 59 deletions(-) diff --git a/tests/regression/apparmor/unix_socket.sh b/tests/regression/apparmor/unix_socket.sh index 0b36b4f..7c23464 100755 --- a/tests/regression/apparmor/unix_socket.sh +++ b/tests/regression/apparmor/unix_socket.sh @@ -31,7 +31,9 @@ requires_features policy/versions/v6 client=$bin/unix_socket_client sockpath_pathname=${tmpdir}/unix_socket.sock +bad_sockpath_pathname="${sockpath_pathname}XXX" sockpath_abstract="@apparmor_unix_socket" +bad_sockpath_abstract="${sockpath_abstract}XXX" message=4a0c83d87aaa7afa2baab5df3ee4df630f0046d5bfb7a3080c550b721f401b3b\ 8a738e1435a3b77aa6482a70fb51c44f20007221b85541b0184de66344d46a4c @@ -51,32 +53,117 @@ testsocktype() { local testdesc=$1 # description (eg, "AF_UNIX abstract socket (dgram)") local sockpath=$2 # fs path or "@NAME" for an abstract sock - local socktype=$3 # stream, dgram, or seqpacket + local bad_sockpath=$3 + local socktype=$4 # stream, dgram, or seqpacket + local bad_socktype=$5 local args="$sockpath $socktype $message $client" local i=0 + local okservers + local badservers + local okclients + local badclients - # assume, by default, that the sock addr is of the pathname type - local okservers=("$sockpath:w") - local badservers=("" "$sockpath:r") - local okclients=("$sockpath:rw") - local badclients=("" "$sockpath:r" "$sockpath:w") - - if [ "$(have_features policy/versions/v7)" == "true" ] ; then - # v7 requires 'unix create' to call socket() - # v7 requires 'unix getopt' to call getsockopt() - # v7 requires 'unix setopt' to call setsockopt() - # v7 requires 'rw' for the server - okservers=("$sockpath:rw unix:(create,getopt,setopt)") - badservers=("" \ - "$sockpath:r unix:(create,getopt,setopt)" \ - "$sockpath:w unix:(create,getopt,setopt)" \ - "unix:(create,getopt,setopt)" \ - "$sockpath:rw unix:(getopt,setopt)" \ - "$sockpath:rw unix:(create,setopt)" \ - "$sockpath:rw unix:(create,getopt)" \ - ) - okclients=("${okservers[@]}") - badclients=("${badservers[@]}") + if isabstract $sockpath; then + local ls_access # local server accesses + local ps_access # peer server accesses + local s_access # combined server accesses + + local lc_access # local client accesses + local pc_access # peer client accesses + local c_access # combined client accesses + + local access # used for iterating accesses + + if [ "$socktype" == "dgram" ]; then + # Connectionless + # Server doesn't listen() or accept() + ls_access="create,bind,getopt,setopt" + ps_access="read,write" + + # Client calls bind() + lc_access="${client_create}bind,getopt,setopt" + pc_access="connect,write,read" + else # stream or seqpacket + # Connection based + # Server calls listen() and accept() + ls_access="create,bind,listen,getopt,setopt" + ps_access="accept,read,write" + + # Client doesn't call bind() + lc_access="${client_create}getopt,setopt" + pc_access="connect,write,read" + fi + + s_access="${ls_access},${ps_access}" + c_access="${lc_access},${pc_access}" + + okservers=("unix:ALL" \ + "unix:($s_access)" \ + "unix:addr=$sockpath" \ + "unix:type=$socktype" \ + "unix:peer=(label=unconfined)" \ + "unix:($s_access):addr=$sockpath" \ + "unix:($ls_access):addr=$sockpath unix:($ps_access):addr=$sockpath:peer=(label=unconfined)" \ + "unix:($ls_access):type=$socktype:addr=$sockpath unix:($ps_access):type=$socktype:addr=$sockpath:peer=(label=unconfined)" \ + "unix:type=$socktype:addr=$sockpath:peer=(label=unconfined)" \ + ) + # Start with no accessess, then remove each access one-by-one + # from the list of server accesses, and then test bad + # conditional values + badservers=("") + for access in ${s_access/,/ }; do + badservers+=("unix:(${s_access//$access/})") + done + badservers+=("unix:addr=$bad_sockpath" \ + "unix:type=$bad_socktype" \ + "unix:peer=(label=XXX)" \ + ) + + okclients=("unix:ALL" \ + "unix:($c_access)" \ + "unix:addr=$sockpath" \ + "unix:type=$socktype" \ + "unix:peer=(label=$test)" \ + "unix:($c_access):addr=$sockpath" \ + "unix:($lc_access):addr=$sockpath unix:($pc_access):addr=$sockpath:peer=(label=$test)" \ + "unix:($lc_access):type=$socktype:addr=$sockpath unix:($pc_access):type=$socktype:addr=$sockpath:peer=(label=$test)" \ + "unix:type=$socktype:addr=$sockpath:peer=(label=$test)" \ + ) + # Start with no accessess, then remove each access one-by-one + # from the list of client accesses, and then test bad + # conditional values + badclients=("") + for access in ${c_access/,/ }; do + badclients+=("unix:(${c_access//$access/})") + done + badclients+=("unix:addr=$bad_sockpath" \ + "unix:type=$bad_socktype" \ + "unix:peer=(label=XXX)" \ + ) + else # pathname-based UNIX domain socket + if [ "$(have_features policy/versions/v7)" == "true" ] ; then + # v7 requires 'unix create' to call socket() + # v7 requires 'unix getopt' to call getsockopt() + # v7 requires 'unix setopt' to call setsockopt() + # v7 requires 'rw' for the server + okservers=("$sockpath:rw unix:(create,getopt,setopt)") + badservers=("" \ + "$sockpath:r unix:(create,getopt,setopt)" \ + "$sockpath:w unix:(create,getopt,setopt)" \ + "unix:(create,getopt,setopt)" \ + "$sockpath:rw unix:(getopt,setopt)" \ + "$sockpath:rw unix:(create,setopt)" \ + "$sockpath:rw unix:(create,getopt)" \ + ) + okclients=("${okservers[@]}") + badclients=("${badservers[@]}") + else + # v6 only requires 'w' for the server + okservers=("$sockpath:w") + badservers=("" "$sockpath:r") + okclients=("$sockpath:rw") + badclients=("" "$sockpath:r" "$sockpath:w") + fi fi removesocket $sockpath @@ -86,15 +173,6 @@ testsocktype() runchecktest "$testdesc; unconfined" pass $args removesocket $sockpath - # TODO: Make additional changes to test abstract sockets w/ confinement - # - # * Create variables to hold genprofile arguments for socket accesses - # and initialize them according to socket address type - # * Remove the following conditional - if isabstract $sockpath; then - return - fi - for ((i=0; i<${#okservers[@]}; i++)); do # PASS - server w/ access to the file @@ -132,32 +210,12 @@ testsocktype() testsockpath() { - local sockpath="$1" # $sockpath_pathname or $sockpath_abstract - local testdesc="AF_UNIX " - local socktype= - - if [ "$sockpath" == "$sockpath_pathname" ]; then - testdesc+="pathname socket" - elif [ "$sockpath" == "$sockpath_abstract" ]; then - testdesc+="abstract socket" - else - fatalerror "Unknown sockpath addr type: $sockpath" - fi - - for socktype in stream dgram seqpacket; do - testsocktype "$testdesc ($socktype)" "$sockpath" "$socktype" - done + testsocktype "AF_UNIX $1 (stream)" "$2" "$3" stream dgram + testsocktype "AF_UNIX $1 (dgram)" "$2" "$3" dgram seqpacket + testsocktype "AF_UNIX $1 (seqpacket)" "$2" "$3" seqpacket stream } -testsockpath "$sockpath_pathname" -testsockpath "$sockpath_abstract" -# TODO: testsockpath "$sockpath_unnamed" -# -# * Adjust unix_socket.c and unix_socket_client.c when the socket path is -# "UNNAMED" -# - Don't bind() the socket -# - Don't set SO_CLOEXEC so that the fd can be passed over exec() -# * Decide how to generate appropriate access rules (if any are needed) -# * Define sockpath_unnamed as "UNNAMED" -# * Update testsockpath() to handle sockpath_unnamed -# * Create isunnamed() and update removesocket() to call it +testsockpath "pathname socket" "$sockpath_pathname" "$bad_sockpath_pathname" +if [ "$(have_features network/af_unix)" == "true" ] ; then + testsockpath "abstract socket" "$sockpath_abstract" "$bad_sockpath_abstract" +fi -- 2.1.0 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
