mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
tests/int: use runc features in seccomp flags test
This test (initially added by commit58ea21daefand later amended in commit26dc55ef1a) currently has two major deficiencies: 1. All possible flag combinations, and their respective numeric values, have to be explicitly listed. Currently we support 3 flags, so there is only 2^3 - 1 = 7 combinations, but adding more flags will become increasingly difficult (for example, 5 flags will result in 31 combinations). 2. The test requires kernel 4.17 (for SECCOMP_FILTER_FLAG_SPEC_ALLOW), and not doing any tests when running on an older kernel. This, too, will make it more difficult to add extra flags in the future. Both issues can be solved by using runc features which now prints all known and supported runc flags. We still have to hardcode the numeric values of all flags, but most of the other work is coded now. In particular: * The test only uses supported flags, meaning it can be used with older kernels, removing the limitation (2) above. * The test calculates the powerset (all possible combinations) of flags and their numeric values. This makes it easier to add more flags, removing the limitation (1) above. * The test will fail (in flags_value) if any new flags will be added to runc but the test itself is not amended. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
@@ -66,11 +66,32 @@ function teardown() {
|
||||
[[ "$output" == *"Network is down"* ]]
|
||||
}
|
||||
|
||||
@test "runc run [seccomp] (SECCOMP_FILTER_FLAG_*)" {
|
||||
# Linux 4.14: SECCOMP_FILTER_FLAG_LOG
|
||||
# Linux 4.17: SECCOMP_FILTER_FLAG_SPEC_ALLOW
|
||||
requires_kernel 4.17
|
||||
# Prints the numeric value of provided seccomp flags combination.
|
||||
# The parameter is flags string, as supplied in OCI spec, for example
|
||||
# '"SECCOMP_FILTER_FLAG_TSYNC","SECCOMP_FILTER_FLAG_LOG"'.
|
||||
function flags_value() {
|
||||
# Numeric values of seccomp flags.
|
||||
declare -A values=(
|
||||
['"SECCOMP_FILTER_FLAG_TSYNC"']=0 # Supported but ignored by runc, thus 0.
|
||||
['"SECCOMP_FILTER_FLAG_LOG"']=2
|
||||
['"SECCOMP_FILTER_FLAG_SPEC_ALLOW"']=4
|
||||
# XXX: add new values above this line.
|
||||
)
|
||||
# Split the flags.
|
||||
IFS=',' read -ra flags <<<"$1"
|
||||
|
||||
local flag v sum=0
|
||||
for flag in "${flags[@]}"; do
|
||||
# This will produce "values[$flag]: unbound variable"
|
||||
# error for a new flag yet unknown to the test.
|
||||
v=${values[$flag]}
|
||||
((sum += v)) || true
|
||||
done
|
||||
|
||||
echo $sum
|
||||
}
|
||||
|
||||
@test "runc run [seccomp] (SECCOMP_FILTER_FLAG_*)" {
|
||||
update_config ' .process.args = ["/bin/sh", "-c", "mkdir /dev/shm/foo"]
|
||||
| .process.noNewPrivileges = false
|
||||
| .linux.seccomp = {
|
||||
@@ -79,18 +100,35 @@ function teardown() {
|
||||
"syscalls":[{"names":["mkdir", "mkdirat"], "action":"SCMP_ACT_ERRNO"}]
|
||||
}'
|
||||
|
||||
declare -A FLAGS=(
|
||||
['REMOVE']=4 # No setting, use built-in default.
|
||||
['EMPTY']=0 # Empty set of flags.
|
||||
['"SECCOMP_FILTER_FLAG_LOG"']=2
|
||||
['"SECCOMP_FILTER_FLAG_SPEC_ALLOW"']=4
|
||||
['"SECCOMP_FILTER_FLAG_TSYNC"']=0 # tsync flag is ignored.
|
||||
['"SECCOMP_FILTER_FLAG_LOG","SECCOMP_FILTER_FLAG_SPEC_ALLOW"']=6
|
||||
['"SECCOMP_FILTER_FLAG_LOG","SECCOMP_FILTER_FLAG_TSYNC"']=2
|
||||
['"SECCOMP_FILTER_FLAG_SPEC_ALLOW","SECCOMP_FILTER_FLAG_TSYNC"']=4
|
||||
['"SECCOMP_FILTER_FLAG_LOG","SECCOMP_FILTER_FLAG_SPEC_ALLOW","SECCOMP_FILTER_FLAG_TSYNC"']=6
|
||||
# Get the list of flags supported by runc/seccomp/kernel,
|
||||
# or "null" if no flags are supported or runc is too old.
|
||||
mapfile -t flags < <(__runc features | jq -c '.linux.seccomp.supportedFlags' |
|
||||
tr -d '[]\n' | tr ',' '\n')
|
||||
|
||||
# This is a set of all possible flag combinations to test.
|
||||
declare -A TEST_CASES=(
|
||||
['EMPTY']=0 # Special value: empty set of flags.
|
||||
['REMOVE']=0 # Special value: no flags set.
|
||||
)
|
||||
for key in "${!FLAGS[@]}"; do
|
||||
|
||||
# If supported, runc should set SPEC_ALLOW if no flags are set.
|
||||
if [[ " ${flags[*]} " == *' "SECCOMP_FILTER_FLAG_SPEC_ALLOW" '* ]]; then
|
||||
TEST_CASES['REMOVE']=$(flags_value '"SECCOMP_FILTER_FLAG_SPEC_ALLOW"')
|
||||
fi
|
||||
|
||||
# Add all possible combinations of seccomp flags
|
||||
# and their expected numeric values to TEST_CASES.
|
||||
if [ "${flags[0]}" != "null" ]; then
|
||||
# Use shell {a,}{b,}{c,} to generate the powerset.
|
||||
for fc in $(eval echo "$(printf "{'%s,',}" "${flags[@]}")"); do
|
||||
# Remove the last comma.
|
||||
fc="${fc/%,/}"
|
||||
TEST_CASES[$fc]=$(flags_value "$fc")
|
||||
done
|
||||
fi
|
||||
|
||||
# Finally, run the tests.
|
||||
for key in "${!TEST_CASES[@]}"; do
|
||||
case "$key" in
|
||||
'REMOVE')
|
||||
update_config ' del(.linux.seccomp.flags)'
|
||||
@@ -108,7 +146,7 @@ function teardown() {
|
||||
[[ "$output" == *"mkdir:"*"/dev/shm/foo"*"Operation not permitted"* ]]
|
||||
|
||||
# Check the numeric flags value, as printed in the debug log, is as expected.
|
||||
exp="\"seccomp filter flags: ${FLAGS[$key]}\""
|
||||
exp="\"seccomp filter flags: ${TEST_CASES[$key]}\""
|
||||
echo "flags $key, expecting $exp"
|
||||
[[ "$output" == *"$exp"* ]]
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user