mirror of
https://git.FreeBSD.org/src.git
synced 2026-06-02 11:24:32 +00:00
MAC/do: Add consistency tests
Test that: 1. Concurrent changes to different parameters on the same jail are independent/atomic. 2. Inheritance works. 3. Relaxing only parent jail rules does not leak to a subjail thanks to sequential consistency. 4. Sysctl knobs and jail parameters stay consistent. Some of these tests may be extended in the future with several layers of jails (there is only a single subjail currently). Reviewed by: bapt MFC after: 1 month Sponsored by: The FreeBSD Foundation Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/38
This commit is contained in:
@@ -2,7 +2,7 @@ PACKAGE= tests
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/sys/mac/do
|
||||
|
||||
ATF_TESTS_SH+= valid_configs invalid_configs
|
||||
ATF_TESTS_SH+= valid_configs invalid_configs consistency
|
||||
|
||||
${PACKAGE}FILES+= common.sh
|
||||
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
# Copyright (c) 2026 The FreeBSD Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# This software was developed by Olivier Certner <olce@FreeBSD.org> at
|
||||
# Kumacom SARL under sponsorship from the FreeBSD Foundation.
|
||||
|
||||
SJ_JID_FILE=sj.jid
|
||||
|
||||
atf_test_case concurrent_rules_exec_paths_changes
|
||||
concurrent_rules_exec_paths_changes_head()
|
||||
{
|
||||
atf_set descr "Consistency of rules and exec paths changes on same jail"
|
||||
}
|
||||
concurrent_rules_exec_paths_changes_body()
|
||||
{
|
||||
local rules exec_paths rules_es exec_paths_es
|
||||
|
||||
for I in $(jot - 1 1000); do
|
||||
sysctl_set_and_check_rules "uid=$I>uid=1001"
|
||||
done &
|
||||
rules=$!
|
||||
|
||||
for I in $(jot - 1 1000); do
|
||||
sysctl_set_and_check_exec_paths /nowhere/nonexistent$I
|
||||
done &
|
||||
exec_paths=$!
|
||||
|
||||
wait $rules
|
||||
rules_es=$?
|
||||
|
||||
wait $exec_paths
|
||||
exec_paths_es=$?
|
||||
|
||||
# atf_check called in the asynchronous AND-OR lists above causes exit of the
|
||||
# subshells and also a write to the ATF result file. These writes are
|
||||
# concurrent and may cause the result file to be malformed. Consequently,
|
||||
# it is important that, once execution becomes sequential again, atf_fail() is
|
||||
# called again (and not just exit()).
|
||||
if [ $rules_es -ne 0 ] || [ $exec_paths_es -ne 0 ]; then
|
||||
atf_fail "Rules exit status: $rules_es, \
|
||||
exec paths exit status: $exec_paths_es"
|
||||
fi
|
||||
}
|
||||
|
||||
atf_test_case inheritance cleanup
|
||||
inheritance_head()
|
||||
{
|
||||
atf_set descr "Simple inheritance test (values propagated to child jail)"
|
||||
}
|
||||
inheritance_body()
|
||||
{
|
||||
local sj rules exec_paths
|
||||
|
||||
# For the sake of not running the test under Kyua
|
||||
mac_do_ensure_disabled
|
||||
|
||||
sj=$(launch_subjail)
|
||||
echo $sj > "${SJ_JID_FILE}"
|
||||
|
||||
jail -m jid=$sj ${ROOT_JAIL_PARAM}=inherit
|
||||
JEXEC="jexec $sj"
|
||||
mac_do_check_disabled
|
||||
JEXEC=
|
||||
|
||||
rules="uid=1001>uid=0"
|
||||
sysctl_set_and_check_rules $rules
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_rules $rules
|
||||
JEXEC=
|
||||
|
||||
rules="gid=1001>uid=0"
|
||||
sysctl_set_and_check_rules $rules
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_rules $rules
|
||||
JEXEC=
|
||||
|
||||
# Not really necessary, just to keep mac_do(4) disabled
|
||||
sysctl_set_and_check_rules ""
|
||||
|
||||
exec_paths="/nowhere/nonexistent"
|
||||
sysctl_set_and_check_exec_paths $exec_paths
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_exec_paths $exec_paths
|
||||
JEXEC=
|
||||
|
||||
exec_paths="$MDO"
|
||||
sysctl_set_and_check_exec_paths $exec_paths
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_exec_paths $exec_paths
|
||||
JEXEC=
|
||||
}
|
||||
inheritance_cleanup()
|
||||
{
|
||||
# We clean up our subjail manually just for the sake of launching this test
|
||||
# with atf-sh. Kyua is informed that these tests should run in a jail, and
|
||||
# kills it automatically after the test, which kills all subjails. It is
|
||||
# annoying that atf-sh does not offer a more practical way to pass
|
||||
# information from the body to the cleanup part than a file.
|
||||
jail -r $(cat "${SJ_JID_FILE}")
|
||||
rm -f "${SJ_JID_FILE}"
|
||||
}
|
||||
|
||||
atf_test_case inheritance_relax_parent_jail cleanup
|
||||
inheritance_relax_parent_jail_head()
|
||||
{
|
||||
atf_set descr \
|
||||
"Test sequential consistency in a \"relax parent rules\" scenario"
|
||||
}
|
||||
inheritance_relax_parent_jail_body()
|
||||
{
|
||||
local sj rules exec_paths subproc
|
||||
|
||||
sj=$(launch_subjail)
|
||||
echo $sj > "${SJ_JID_FILE}"
|
||||
|
||||
jail -m jid=$sj ${ROOT_JAIL_PARAM}=inherit
|
||||
rules="uid=1001>uid=0"
|
||||
sysctl_set_and_check_rules $rules
|
||||
# Additional inheritance sanity check
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_rules $rules
|
||||
JEXEC=
|
||||
exec_paths="$MDO"
|
||||
sysctl_set_and_check_exec_paths $exec_paths
|
||||
# Additional inheritance sanity check
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_exec_paths $exec_paths
|
||||
JEXEC=
|
||||
|
||||
# Launch a process that tries to become 'root' from user 1002, and verify
|
||||
# that this always fails.
|
||||
{ for I in $(jot - 1 1000); do
|
||||
jexec $sj "$MDO" -u 1002 -g 1002 -G 1002 "$MDO" -i true 2>/dev/null &&
|
||||
exit 1
|
||||
done; true; } &
|
||||
subproc=$!
|
||||
|
||||
# Decouple the subjail from the parent jail, copying its parameters
|
||||
jail -m jid=$sj ${ROOT_JAIL_PARAM}=new
|
||||
# Allow user 1002 to become 'root' on the parent jail
|
||||
sysctl_set_and_check_rules "$rules;uid=1002>uid=0"
|
||||
JEXEC="jexec $sj"
|
||||
# Additional sanity check (that rules of the subjail are now independent)
|
||||
[ "$(sysctl_rules)" == $rules ] || atf_fail "Rules not copied"
|
||||
[ "$(sysctl_exec_paths)" == $exec_paths ] ||
|
||||
atf_fail "Exec paths not copied"
|
||||
JEXEC=
|
||||
|
||||
wait $subproc || atf_fail "A transition wrongly succeeded in the subjail!"
|
||||
}
|
||||
inheritance_relax_parent_jail_cleanup()
|
||||
{
|
||||
# See inheritance_cleanup() for explanations
|
||||
jail -r $(cat "${SJ_JID_FILE}")
|
||||
rm -f "${SJ_JID_FILE}"
|
||||
}
|
||||
|
||||
atf_test_case same_knob_and_jail_parameter cleanup
|
||||
same_knob_and_jail_parameter_head()
|
||||
{
|
||||
atf_set descr \
|
||||
"Corresponding sysctl knobs and jail parameters have same value"
|
||||
}
|
||||
same_knob_and_jail_parameter_body()
|
||||
{
|
||||
local sj rules exec_paths subproc
|
||||
|
||||
sj=$(launch_subjail)
|
||||
echo $sj > "${SJ_JID_FILE}"
|
||||
|
||||
# Set sysctl knobs, observe parameters
|
||||
rules="uid=19999>uid=21700"
|
||||
exec_paths="/improbable/path/he"
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_set_and_check_rules $rules
|
||||
sysctl_set_and_check_exec_paths $exec_paths
|
||||
JEXEC=
|
||||
atf_check -o inline:"$rules\n" jls -j $sj ${RULES_JAIL_PARAM}
|
||||
atf_check -o inline:"${exec_paths}\n" jls -j $sj ${EXEC_PATHS_JAIL_PARAM}
|
||||
|
||||
# Set parameters, observe knobs
|
||||
rules="uid=128000>uid=-1"
|
||||
exec_paths="/hello/i_ve/changed"
|
||||
jail -m jid=$sj ${RULES_JAIL_PARAM}=$rules \
|
||||
${EXEC_PATHS_JAIL_PARAM}=${exec_paths}
|
||||
JEXEC="jexec $sj"
|
||||
sysctl_check_rules $rules
|
||||
sysctl_check_exec_paths $exec_paths
|
||||
JEXEC=
|
||||
}
|
||||
same_knob_and_jail_parameter_cleanup()
|
||||
{
|
||||
# See inheritance_cleanup() for explanations
|
||||
jail -r $(cat "${SJ_JID_FILE}")
|
||||
rm -f "${SJ_JID_FILE}"
|
||||
}
|
||||
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
. $(atf_get_srcdir)/common.sh
|
||||
atf_require_prog jot
|
||||
# Needs an absolute path for mdo(1), to set it in exec_paths
|
||||
atf_require_prog "$MDO"
|
||||
|
||||
atf_add_test_case concurrent_rules_exec_paths_changes
|
||||
atf_add_test_case inheritance
|
||||
atf_add_test_case inheritance_relax_parent_jail
|
||||
atf_add_test_case same_knob_and_jail_parameter
|
||||
}
|
||||
Reference in New Issue
Block a user