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 atf_set require.progs jail 33} 34 35basic_body() 36{ 37 # Create the jail 38 atf_check -s exit:0 -o ignore jail -c name=basejail persist ip4.addr=192.0.1.1 39 # Create a second jail to test `jls -n` in the process for breakage when 40 # handling some of the non-trivial parameter types. 41 atf_check -s exit:0 -o ignore jail -c name=basejail2 persist ip4.addr=192.0.1.2 42 # Check output of jls 43 atf_check -s exit:0 -o ignore jls 44 atf_check -s exit:0 -o ignore jls -v 45 atf_check -s exit:0 -o ignore jls -n 46 # Stop jail 47 atf_check -s exit:0 -o ignore jail -r basejail 48 jail -c name=basejail persist ip4.addr=192.0.1.1 49 # Stop jail by jid 50 atf_check -s exit:0 -o ignore jail -r `jls -j basejail jid` 51 # Recreate 52 atf_check -s exit:0 -o ignore jail -cm name=basejail persist ip4.addr=192.0.1.1 53 # Restart 54 atf_check -s exit:0 -o ignore jail -rc name=basejail persist ip4.addr=192.0.1.1 55} 56 57basic_cleanup() 58{ 59 jail -r basejail basejail2 60} 61 62atf_test_case "list" "cleanup" 63list_head() 64{ 65 atf_set descr 'Specify some jail parameters as lists' 66 atf_set require.user root 67 atf_set require.progs jail 68} 69 70list_body() 71{ 72 if [ "$(sysctl -qn kern.features.vimage)" -ne 1 ]; then 73 atf_skip "cannot create VNET jails" 74 fi 75 atf_check -o save:epair ifconfig epair create 76 77 epair=$(cat epair) 78 atf_check jail -c name=basejail vnet persist vnet.interface=${epair},${epair%a}b 79 80 atf_check -o ignore jexec basejail ifconfig ${epair} 81 atf_check -o ignore jexec basejail ifconfig ${epair%a}b 82} 83 84list_cleanup() 85{ 86 jail -r basejail 87 if [ -f epair ]; then 88 ifconfig $(cat epair) destroy 89 fi 90} 91 92atf_test_case "nested" "cleanup" 93nested_head() 94{ 95 atf_set descr 'Hierarchical jails test' 96 atf_set require.user root 97 atf_set require.progs jail 98} 99 100nested_body() 101{ 102 # Create the first jail 103 jail -c name=basejail persist ip4.addr=192.0.1.1 children.max=1 104 atf_check -s exit:0 -o empty \ 105 jexec basejail \ 106 jail -c name=nestedjail persist ip4.addr=192.0.1.1 107 108 atf_check -s exit:1 -o empty -e inline:"jail: prison limit exceeded\n"\ 109 jexec basejail \ 110 jail -c name=secondnestedjail persist ip4.addr=192.0.1.1 111 # Check output of jls 112 atf_check -s exit:0 -o ignore \ 113 jexec basejail jls 114 atf_check -s exit:0 -o ignore \ 115 jexec basejail jls -v 116 atf_check -s exit:0 -o ignore \ 117 jexec basejail jls -n 118 # Create jail with no child - children.max should be 0 by default 119 jail -c name=basejail_nochild persist ip4.addr=192.0.1.1 120 atf_check -s exit:1 -o empty \ 121 -e inline:"jail: jail_set: Operation not permitted\n" \ 122 jexec basejail_nochild \ 123 jail -c name=nestedjail persist ip4.addr=192.0.1.1 124} 125 126nested_cleanup() 127{ 128 jail -r nestedjail 129 jail -r basejail 130 jail -r basejail_nochild 131} 132 133atf_test_case "commands" "cleanup" 134commands_head() 135{ 136 atf_set descr 'Commands jail test' 137 atf_set require.user root 138 atf_set require.progs jail 139} 140 141commands_body() 142{ 143 cp "$(atf_get_srcdir)/commands.jail.conf" jail.conf 144 echo "path = \"$PWD\";" >> jail.conf 145 146 # exec.prestart (START) and exec.poststart (env) 147 atf_check -o save:stdout -e empty \ 148 jail -f jail.conf -qc basejail 149 150 # exec.prestart output is missing 151 atf_check grep -qE '^START$' stdout 152 # JID was not set in the exec.poststart env 153 atf_check grep -qE '^JID=[0-9]+' stdout 154 # JNAME was not set in the exec.poststart env 155 atf_check grep -qE '^JNAME=basejail$' stdout 156 # JPATH was not set in the exec.poststart env 157 atf_check grep -qE "^JPATH=$PWD$" stdout 158 159 # exec.prestop by jailname 160 atf_check -s exit:0 -o inline:"STOP\n" \ 161 jail -f jail.conf -qr basejail 162 # exec.prestop by jid 163 jail -f jail.conf -qc basejail 164 atf_check -s exit:0 -o inline:"STOP\n" \ 165 jail -f jail.conf -qr `jls -j basejail jid` 166} 167 168commands_cleanup() 169{ 170 if jls -j basejail > /dev/null 2>&1; then 171 jail -r basejail 172 fi 173} 174 175atf_test_case "jid_name_set" "cleanup" 176jid_name_set_head() 177{ 178 atf_set descr 'Test that one can set both the jid and name in a config file' 179 atf_set require.user root 180 atf_set require.progs jail 181} 182 183find_unused_jid() 184{ 185 : ${JAIL_MAX=999999} 186 187 # We'll start at a higher jid number and roll through the space until 188 # we find one that isn't taken. We start high to avoid racing parallel 189 # activity for the 'next available', though ideally we don't have a lot 190 # of parallel jail activity like that. 191 jid=5309 192 while jls -cj "$jid"; do 193 if [ "$jid" -eq "$JAIL_MAX" ]; then 194 atf_skip "System has too many jail, cannot find free slot" 195 fi 196 197 : $(( jid += 1 )) 198 done 199 200 echo "$jid" | tee -a jails.lst 201} 202 203clean_jails() 204{ 205 if [ ! -s jails.lst ]; then 206 return 0 207 fi 208 209 while read jail; do 210 if jls -c -j "$jail"; then 211 jail -r "$jail" 212 fi 213 done < jails.lst 214} 215 216jid_name_set_body() 217{ 218 local jid=$(find_unused_jid) 219 220 echo "basejail" >> jails.lst 221 echo "$jid { name = basejail; persist; }" > jail.conf 222 atf_check -o match:"$jid: created" jail -f jail.conf -c "$jid" 223 # Confirm that we didn't override the explicitly-set name with the jid 224 # as the name. 225 atf_check -o match:"basejail" jls -j "$jid" name 226 atf_check -o match:"$jid: removed" jail -f jail.conf -r "$jid" 227 228 echo "$jid { host.hostname = \"\${name}\"; persist; }" > jail.conf 229 atf_check -o match:"$jid: created" jail -f jail.conf -c "$jid" 230 # Confirm that ${name} expanded and expanded correctly to the 231 # jid-implied name. 232 atf_check -o match:"$jid" jls -j "$jid" host.hostname 233 atf_check -o match:"$jid: removed" jail -f jail.conf -r "$jid" 234 235 echo "basejail { jid = $jid; persist; }" > jail.conf 236 atf_check -o match:"basejail: created" jail -f jail.conf -c basejail 237 # Confirm that our jid assigment in the definition worked out and we 238 # did in-fact create the jail there. 239 atf_check -o match:"$jid" jls -j "basejail" jid 240 atf_check -o match:"basejail: removed" jail -f jail.conf -r basejail 241} 242 243jid_name_set_cleanup() 244{ 245 clean_jails 246} 247 248atf_test_case "param_consistency" "cleanup" 249param_consistency_head() 250{ 251 atf_set descr 'Test for consistency in jid/name params being set implicitly' 252 atf_set require.user root 253 atf_set require.progs jail 254} 255 256param_consistency_body() 257{ 258 local iface jid 259 260 echo "basejail" >> jails.lst 261 262 # Most basic test: exec.poststart running a command without a jail 263 # config. This would previously crash as we only had the jid and name 264 # as populated at creation time. 265 atf_check jail -c path=/ exec.poststart="true" command=/usr/bin/true 266 267 iface=$(ifconfig lo create) 268 atf_check test -n "$iface" 269 echo "$iface" >> interfaces.lst 270 271 # Now do it again but exercising IP_VNET_INTERFACE, which is an 272 # implied command that wants to use the jid or name. This would crash 273 # as neither KP_JID or KP_NAME are populated when a jail is created, 274 # just as above- just at a different spot. 275 atf_check jail -c \ 276 path=/ vnet=new vnet.interface="$iface" command=/usr/bin/true 277 278 # Test that a jail that we only know by name will have its jid resolved 279 # and added to its param set. 280 echo "basejail {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 281 282 atf_check -o ignore jail -f jail.conf -c basejail 283 atf_check -o match:"STOP" jail -f jail.conf -r basejail 284 285 # Do the same sequence as above, but use a jail with a jid-ish name. 286 jid=$(find_unused_jid) 287 echo "$jid {path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 288 289 atf_check -o ignore jail -f jail.conf -c "$jid" 290 atf_check -o match:"STOP" jail -f jail.conf -r "$jid" 291 292 # Ditto, but now we set a name for that jid-jail. 293 echo "$jid {name = basejail; path = /; exec.prestop = 'echo STOP'; persist; }" > jail.conf 294 295 atf_check -o ignore jail -f jail.conf -c "$jid" 296 atf_check -o match:"STOP" jail -f jail.conf -r "$jid" 297 298 # Confirm that we have a valid jid available in exec.poststop. It's 299 # probably debatable whether we should or not. 300 echo "basejail {path = /; exec.poststop = 'echo JID=\$JID'; persist; }" > jail.conf 301 atf_check -o ignore jail -f jail.conf -c basejail 302 jid=$(jls -j basejail jid) 303 304 atf_check -o match:"JID=$jid" jail -f jail.conf -r basejail 305 306} 307 308param_consistency_cleanup() 309{ 310 clean_jails 311 312 if [ -f "interfaces.lst" ]; then 313 while read iface; do 314 ifconfig "$iface" destroy 315 done < interfaces.lst 316 fi 317} 318 319atf_test_case "setaudit" 320setaudit_head() 321{ 322 atf_set descr 'Test that setaudit works in a jail when configured with allow.setaudit' 323 atf_set require.user root 324 atf_set require.progs setaudit jail 325} 326 327setaudit_body() 328{ 329 # Try to modify the audit mask within a jail without 330 # allow.setaudit configured. 331 atf_check -s not-exit:0 -o empty -e not-empty jail -c name=setaudit_jail \ 332 command=setaudit -m fr ls / 333 # The command should succeed if allow.setaudit is configured. 334 atf_check -s exit:0 -o ignore -e empty jail -c name=setaudit_jail \ 335 allow.setaudit command=setaudit -m fr ls / 336} 337 338atf_init_test_cases() 339{ 340 atf_add_test_case "basic" 341 atf_add_test_case "list" 342 atf_add_test_case "nested" 343 atf_add_test_case "commands" 344 atf_add_test_case "jid_name_set" 345 atf_add_test_case "param_consistency" 346 atf_add_test_case "setaudit" 347} 348