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 -c -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 # Confirm that we didn't override the explicitly-set name with the jid 215 # as the name. 216 atf_check -o match:"basejail" jls -j "$jid" name 217 atf_check -o match:"$jid: removed" jail -f jail.conf -r "$jid" 218 219 echo "$jid { host.hostname = \"\${name}\"; persist; }" > jail.conf 220 atf_check -o match:"$jid: created" jail -f jail.conf -c "$jid" 221 # Confirm that ${name} expanded and expanded correctly to the 222 # jid-implied name. 223 atf_check -o match:"$jid" jls -j "$jid" host.hostname 224 atf_check -o match:"$jid: removed" jail -f jail.conf -r "$jid" 225 226 echo "basejail { jid = $jid; persist; }" > jail.conf 227 atf_check -o match:"basejail: created" jail -f jail.conf -c basejail 228 # Confirm that our jid assigment in the definition worked out and we 229 # did in-fact create the jail there. 230 atf_check -o match:"$jid" jls -j "basejail" jid 231 atf_check -o match:"basejail: removed" jail -f jail.conf -r basejail 232} 233 234jid_name_set_cleanup() 235{ 236 clean_jails 237} 238 239atf_test_case "param_consistency" "cleanup" 240param_consistency_head() 241{ 242 atf_set descr 'Test for consistency in jid/name params being set implicitly' 243 atf_set require.user root 244} 245 246param_consistency_body() 247{ 248 local iface jid 249 250 echo "basejail" >> jails.lst 251 252 # Most basic test: exec.poststart running a command without a jail 253 # config. This would previously crash as we only had the jid and name 254 # as populated at creation time. 255 atf_check jail -c path=/ exec.poststart="true" command=/usr/bin/true 256 257 iface=$(ifconfig lo create) 258 atf_check test -n "$iface" 259 echo "$iface" >> interfaces.lst 260 261 # Now do it again but exercising IP_VNET_INTERFACE, which is an 262 # implied command that wants to use the jid or name. This would crash 263 # as neither KP_JID or KP_NAME are populated when a jail is created, 264 # just as above- just at a different spot. 265 atf_check jail -c \ 266 path=/ vnet=new vnet.interface="$iface" command=/usr/bin/true 267 268 # Test that a jail that we only know by name will have its jid resolved 269 # and added to its param set. 270 echo "basejail {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 271 272 atf_check -o ignore jail -f jail.conf -c basejail 273 atf_check -o match:"STOP" jail -f jail.conf -r basejail 274 275 # Do the same sequence as above, but use a jail with a jid-ish name. 276 jid=$(find_unused_jid) 277 echo "$jid {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 278 279 atf_check -o ignore jail -f jail.conf -c "$jid" 280 atf_check -o match:"STOP" jail -f jail.conf -r "$jid" 281 282 # Ditto, but now we set a name for that jid-jail. 283 echo "$jid {name = basejail; path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 284 285 atf_check -o ignore jail -f jail.conf -c "$jid" 286 atf_check -o match:"STOP" jail -f jail.conf -r "$jid" 287 288 # Confirm that we have a valid jid available in exec.poststop. It's 289 # probably debatable whether we should or not. 290 echo "basejail {path = /; exec.poststop = 'echo JID=\$JID'; persist; }" > jail.conf 291 atf_check -o ignore jail -f jail.conf -c basejail 292 jid=$(jls -j basejail jid) 293 294 atf_check -o match:"JID=$jid" jail -f jail.conf -r basejail 295 296} 297 298param_consistency_cleanup() 299{ 300 clean_jails 301 302 if [ -f "interfaces.lst" ]; then 303 while read iface; do 304 ifconfig "$iface" destroy 305 done < interfaces.lst 306 fi 307} 308 309atf_test_case "setaudit" 310setaudit_head() 311{ 312 atf_set descr 'Test that setaudit works in a jail when configured with allow.setaudit' 313 atf_set require.user root 314 atf_set require.progs setaudit 315} 316 317setaudit_body() 318{ 319 # Try to modify the audit mask within a jail without 320 # allow.setaudit configured. 321 atf_check -s not-exit:0 -o empty -e not-empty jail -c name=setaudit_jail \ 322 command=setaudit -m fr ls / 323 # The command should succeed if allow.setaudit is configured. 324 atf_check -s exit:0 -o ignore -e empty jail -c name=setaudit_jail \ 325 allow.setaudit command=setaudit -m fr ls / 326} 327 328atf_init_test_cases() 329{ 330 atf_add_test_case "basic" 331 atf_add_test_case "list" 332 atf_add_test_case "nested" 333 atf_add_test_case "commands" 334 atf_add_test_case "jid_name_set" 335 atf_add_test_case "param_consistency" 336 atf_add_test_case "setaudit" 337} 338