1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2019 Michael Zhilin 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26 27atf_test_case "basic" "cleanup" 28basic_head() 29{ 30 atf_set descr 'Basic jail test' 31 atf_set require.user root 32} 33 34basic_body() 35{ 36 # Create the jail 37 atf_check -s exit:0 -o ignore jail -c name=basejail persist ip4.addr=192.0.1.1 38 # Check output of jls 39 atf_check -s exit:0 -o ignore jls 40 atf_check -s exit:0 -o ignore jls -v 41 atf_check -s exit:0 -o ignore jls -n 42 # Stop jail 43 atf_check -s exit:0 -o ignore jail -r basejail 44 jail -c name=basejail persist ip4.addr=192.0.1.1 45 # Stop jail by jid 46 atf_check -s exit:0 -o ignore jail -r `jls -j basejail jid` 47 # Recreate 48 atf_check -s exit:0 -o ignore jail -cm name=basejail persist ip4.addr=192.0.1.1 49 # Restart 50 atf_check -s exit:0 -o ignore jail -rc name=basejail persist ip4.addr=192.0.1.1 51} 52 53basic_cleanup() 54{ 55 jail -r basejail 56} 57 58atf_test_case "list" "cleanup" 59list_head() 60{ 61 atf_set descr 'Specify some jail parameters as lists' 62 atf_set require.user root 63} 64 65list_body() 66{ 67 if [ "$(sysctl -qn kern.features.vimage)" -ne 1 ]; then 68 atf_skip "cannot create VNET jails" 69 fi 70 atf_check -o save:epair ifconfig epair create 71 72 epair=$(cat epair) 73 atf_check jail -c name=basejail vnet persist vnet.interface=${epair},${epair%a}b 74 75 atf_check -o ignore jexec basejail ifconfig ${epair} 76 atf_check -o ignore jexec basejail ifconfig ${epair%a}b 77} 78 79list_cleanup() 80{ 81 jail -r basejail 82 if [ -f epair ]; then 83 ifconfig $(cat epair) destroy 84 fi 85} 86 87atf_test_case "nested" "cleanup" 88nested_head() 89{ 90 atf_set descr 'Hierarchical jails test' 91 atf_set require.user root 92} 93 94nested_body() 95{ 96 # Create the first jail 97 jail -c name=basejail persist ip4.addr=192.0.1.1 children.max=1 98 atf_check -s exit:0 -o empty \ 99 jexec basejail \ 100 jail -c name=nestedjail persist ip4.addr=192.0.1.1 101 102 atf_check -s exit:1 -o empty -e inline:"jail: prison limit exceeded\n"\ 103 jexec basejail \ 104 jail -c name=secondnestedjail persist ip4.addr=192.0.1.1 105 # Check output of jls 106 atf_check -s exit:0 -o ignore \ 107 jexec basejail jls 108 atf_check -s exit:0 -o ignore \ 109 jexec basejail jls -v 110 atf_check -s exit:0 -o ignore \ 111 jexec basejail jls -n 112 # Create jail with no child - children.max should be 0 by default 113 jail -c name=basejail_nochild persist ip4.addr=192.0.1.1 114 atf_check -s exit:1 -o empty \ 115 -e inline:"jail: jail_set: Operation not permitted\n" \ 116 jexec basejail_nochild \ 117 jail -c name=nestedjail persist ip4.addr=192.0.1.1 118} 119 120nested_cleanup() 121{ 122 jail -r nestedjail 123 jail -r basejail 124 jail -r basejail_nochild 125} 126 127atf_test_case "commands" "cleanup" 128commands_head() 129{ 130 atf_set descr 'Commands jail test' 131 atf_set require.user root 132} 133 134commands_body() 135{ 136 cp "$(atf_get_srcdir)/commands.jail.conf" jail.conf 137 echo "path = \"$PWD\";" >> jail.conf 138 139 # exec.prestart (START) and exec.poststart (env) 140 atf_check -o save:stdout -e empty \ 141 jail -f jail.conf -qc basejail 142 143 # exec.prestart output is missing 144 atf_check grep -qE '^START$' stdout 145 # JID was not set in the exec.poststart env 146 atf_check grep -qE '^JID=[0-9]+' stdout 147 # JNAME was not set in the exec.poststart env 148 atf_check grep -qE '^JNAME=basejail$' stdout 149 # JPATH was not set in the exec.poststart env 150 atf_check grep -qE "^JPATH=$PWD$" stdout 151 152 # exec.prestop by jailname 153 atf_check -s exit:0 -o inline:"STOP\n" \ 154 jail -f jail.conf -qr basejail 155 # exec.prestop by jid 156 jail -f jail.conf -qc basejail 157 atf_check -s exit:0 -o inline:"STOP\n" \ 158 jail -f jail.conf -qr `jls -j basejail jid` 159} 160 161commands_cleanup() 162{ 163 if jls -j basejail > /dev/null 2>&1; then 164 jail -r basejail 165 fi 166} 167 168atf_test_case "jid_name_set" "cleanup" 169jid_name_set_head() 170{ 171 atf_set descr 'Test that one can set both the jid and name in a config file' 172 atf_set require.user root 173} 174 175find_unused_jid() 176{ 177 : ${JAIL_MAX=999999} 178 179 # We'll start at a higher jid number and roll through the space until 180 # we find one that isn't taken. We start high to avoid racing parallel 181 # activity for the 'next available', though ideally we don't have a lot 182 # of parallel jail activity like that. 183 jid=5309 184 while jls -cj "$jid"; do 185 if [ "$jid" -eq "$JAIL_MAX" ]; then 186 atf_skip "System has too many jail, cannot find free slot" 187 fi 188 189 jid=$((jid + 1)) 190 done 191 192 echo "$jid" | tee -a jails.lst 193} 194clean_jails() 195{ 196 if [ ! -s jails.lst ]; then 197 return 0 198 fi 199 200 while read jail; do 201 if jls -e -j "$jail"; then 202 jail -r "$jail" 203 fi 204 done < jails.lst 205} 206 207jid_name_set_body() 208{ 209 local jid=$(find_unused_jid) 210 211 echo "basejail" >> jails.lst 212 echo "$jid { name = basejail; persist; }" > jail.conf 213 atf_check -o match:"$jid: created" jail -f jail.conf -c "$jid" 214 atf_check -o match:"$jid: removed" jail -f jail.conf -r "$jid" 215 216 echo "basejail { jid = $jid; persist; }" > jail.conf 217 atf_check -o match:"basejail: created" jail -f jail.conf -c basejail 218 atf_check -o match:"basejail: removed" jail -f jail.conf -r basejail 219} 220 221jid_name_set_cleanup() 222{ 223 clean_jails 224} 225 226atf_test_case "param_consistency" "cleanup" 227param_consistency_head() 228{ 229 atf_set descr 'Test for consistency in jid/name params being set implicitly' 230 atf_set require.user root 231} 232 233param_consistency_body() 234{ 235 local iface jid 236 237 echo "basejail" >> jails.lst 238 239 # Most basic test: exec.poststart running a command without a jail 240 # config. This would previously crash as we only had the jid and name 241 # as populated at creation time. 242 atf_check jail -c path=/ exec.poststart="true" command=/usr/bin/true 243 244 iface=$(ifconfig lo create) 245 atf_check test -n "$iface" 246 echo "$iface" >> interfaces.lst 247 248 # Now do it again but exercising IP_VNET_INTERFACE, which is an 249 # implied command that wants to use the jid or name. This would crash 250 # as neither KP_JID or KP_NAME are populated when a jail is created, 251 # just as above- just at a different spot. 252 atf_check jail -c \ 253 path=/ vnet=new vnet.interface="$iface" command=/usr/bin/true 254 255 # Test that a jail that we only know by name will have its jid resolved 256 # and added to its param set. 257 echo "basejail {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 258 259 atf_check -o ignore jail -f jail.conf -c basejail 260 atf_check -o match:"STOP" jail -f jail.conf -r basejail 261 262 # Do the same sequence as above, but use a jail with a jid-ish name. 263 jid=$(find_unused_jid) 264 echo "$jid {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 265 266 atf_check -o ignore jail -f jail.conf -c "$jid" 267 atf_check -o match:"STOP" jail -f jail.conf -r "$jid" 268 269 # Ditto, but now we set a name for that jid-jail. 270 echo "$jid {name = basejail; path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 271 272 atf_check -o ignore jail -f jail.conf -c "$jid" 273 atf_check -o match:"STOP" jail -f jail.conf -r "$jid" 274 275 # Confirm that we have a valid jid available in exec.poststop. It's 276 # probably debatable whether we should or not. 277 echo "basejail {path = /; exec.poststop = 'echo JID=\$JID'; persist; }" > jail.conf 278 atf_check -o ignore jail -f jail.conf -c basejail 279 jid=$(jls -j basejail jid) 280 281 atf_check -o match:"JID=$jid" jail -f jail.conf -r basejail 282 283} 284 285param_consistency_cleanup() 286{ 287 clean_jails 288 289 if [ -f "interfaces.lst" ]; then 290 while read iface; do 291 ifconfig "$iface" destroy 292 done < interfaces.lst 293 fi 294} 295 296atf_init_test_cases() 297{ 298 atf_add_test_case "basic" 299 atf_add_test_case "list" 300 atf_add_test_case "nested" 301 atf_add_test_case "commands" 302 atf_add_test_case "jid_name_set" 303 atf_add_test_case "param_consistency" 304} 305