# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
TESTNAME="bpftool_map"
BPF_FILE="security_bpf_map.bpf.o"
BPF_ITER_FILE="bpf_iter_map_elem.bpf.o"
PROTECTED_MAP_NAME="prot_map"
NOT_PROTECTED_MAP_NAME="not_prot_map"
BPF_FS_TMP_PARENT="/tmp"
BPF_FS_PARENT=$(awk '$3 == "bpf" {print $2; exit}' /proc/mounts)
BPF_FS_PARENT=${BPF_FS_PARENT:-$BPF_FS_TMP_PARENT} # bpftool will mount bpf file system under BPF_DIR if it is not mounted # under BPF_FS_PARENT.
BPF_DIR="$BPF_FS_PARENT/test_$TESTNAME"
SCRIPT_DIR=$(dirname $(realpath "$0"))
BPF_FILE_PATH="$SCRIPT_DIR/$BPF_FILE"
BPF_ITER_FILE_PATH="$SCRIPT_DIR/$BPF_ITER_FILE"
BPFTOOL_PATH="bpftool" # Assume the script is located under tools/testing/selftests/bpf/
KDIR_ROOT_DIR=$(realpath "$SCRIPT_DIR"/../../../../)
_cleanup()
{
set +eu
# If BPF_DIR is a mount point this will not remove the mount point itself.
[ -d "$BPF_DIR" ] && rm -rf "$BPF_DIR" 2> /dev/null
# Unmount if BPF filesystem was temporarily created. if [ "$BPF_FS_PARENT" = "$BPF_FS_TMP_PARENT" ]; then # A loop and recursive unmount are required as bpftool might # create multiple mounts. For example, a bind mount of the directory # to itself. The bind mount is created to change mount propagation # flags on an actual mount point.
max_attempts=3
attempt=0 while mountpoint -q "$BPF_DIR" && [ $attempt -lt $max_attempts ]; do
umount -R "$BPF_DIR" 2>/dev/null
attempt=$((attempt+1)) done
# The directory still exists. Remove it now.
[ -d "$BPF_DIR" ] && rm -rf "$BPF_DIR" 2>/dev/null fi
}
cleanup()
{ if [ "$?" = 0 ]; then echo"selftests: $TESTNAME [PASS]" else echo"selftests: $TESTNAME [FAILED]" fi
_cleanup
}
check_root_privileges() { if [ $(id -u) -ne 0 ]; then echo"Need root privileges"
exit $ksft_skip fi
}
# Function to verify bpftool path. # Parameters: # $1: bpftool path
verify_bpftool_path() {
local bpftool_path="$1" if ! "$bpftool_path" version > /dev/null 2>&1; then echo"Could not run test without bpftool"
exit $ksft_skip fi
}
# Function to verify BTF support. # The test requires BTF support for fmod_ret programs.
verify_btf_support() { if [ ! -f /sys/kernel/btf/vmlinux ]; then echo"Could not run test without BTF support"
exit $ksft_skip fi
}
# Function to initialize map entries with keys [0..2] and values set to 0. # Parameters: # $1: Map name # $2: bpftool path
initialize_map_entries() {
local map_name="$1"
local bpftool_path="$2"
for key in 0 1 2; do "$bpftool_path" map update name "$map_name" key $key 0 0 0 value 0 0 0 $key done
}
# Test read access to the map. # Parameters: # $1: Name command (name/pinned) # $2: Map name # $3: bpftool path # $4: key
access_for_read() {
local name_cmd="$1"
local map_name="$2"
local bpftool_path="$3"
local key="$4"
# Test read access to the map. if ! "$bpftool_path" map lookup "$name_cmd""$map_name" key $key 1>/dev/null; then echo" Read access to $key in $map_name failed"
exit 1 fi
# Test read access to map's BTF data. if ! "$bpftool_path" btf dump map "$name_cmd""$map_name" 1>/dev/null; then echo" Read access to $map_name for BTF data failed"
exit 1 fi
}
# Test write access to the map. # Parameters: # $1: Name command (name/pinned) # $2: Map name # $3: bpftool path # $4: key # $5: Whether write should succeed (true/false)
access_for_write() {
local name_cmd="$1"
local map_name="$2"
local bpftool_path="$3"
local key="$4"
local write_should_succeed="$5"
local value="1 1 1 1"
if"$bpftool_path" map update "$name_cmd""$map_name" key $key value \
$value 2>/dev/null; then if [ "$write_should_succeed" = "false" ]; then echo" Write access to $key in $map_name succeeded but should have failed"
exit 1 fi else if [ "$write_should_succeed" = "true" ]; then echo" Write access to $key in $map_name failed but should have succeeded"
exit 1 fi fi
}
# Test entry deletion for the map. # Parameters: # $1: Name command (name/pinned) # $2: Map name # $3: bpftool path # $4: key # $5: Whether write should succeed (true/false)
access_for_deletion() {
local name_cmd="$1"
local map_name="$2"
local bpftool_path="$3"
local key="$4"
local write_should_succeed="$5"
local value="1 1 1 1"
# Test deletion by key for the map. # Before deleting, check the key exists. if ! "$bpftool_path" map lookup "$name_cmd""$map_name" key $key 1>/dev/null; then echo" Key $key does not exist in $map_name"
exit 1 fi
# Delete by key. if"$bpftool_path" map delete"$name_cmd""$map_name" key $key 2>/dev/null; then if [ "$write_should_succeed" = "false" ]; then echo" Deletion for $key in $map_name succeeded but should have failed"
exit 1 fi else if [ "$write_should_succeed" = "true" ]; then echo" Deletion for $key in $map_name failed but should have succeeded"
exit 1 fi fi
# After deleting, check the entry existence according to the expected status. if"$bpftool_path" map lookup "$name_cmd""$map_name" key $key 1>/dev/null; then if [ "$write_should_succeed" = "true" ]; then echo" Key $key for $map_name was not deleted but should have been deleted"
exit 1 fi else if [ "$write_should_succeed" = "false" ]; then echo"Key $key for $map_name was deleted but should have not been deleted"
exit 1 fi fi
# Test creation of map's deleted entry, if deletion was successful. # Otherwise, the entry exists. if"$bpftool_path" map update "$name_cmd""$map_name" key $key value \
$value 2>/dev/null; then if [ "$write_should_succeed" = "false" ]; then echo" Write access to $key in $map_name succeeded after deletion attempt but should have failed"
exit 1 fi else if [ "$write_should_succeed" = "true" ]; then echo" Write access to $key in $map_name failed after deletion attempt but should have succeeded"
exit 1 fi fi
}
# Test map elements iterator. # Parameters: # $1: Name command (name/pinned) # $2: Map name # $3: bpftool path # $4: BPF_DIR # $5: bpf iterator object file path
iterate_map_elem() {
local name_cmd="$1"
local map_name="$2"
local bpftool_path="$3"
local bpf_dir="$4"
local bpf_file="$5"
local pin_path="$bpf_dir/map_iterator"
"$bpftool_path" iter pin "$bpf_file""$pin_path" map "$name_cmd""$map_name" if [ ! -f "$pin_path" ]; then echo" Failed to pin iterator to $pin_path"
exit 1 fi
# Function to test map access with configurable write expectations # Parameters: # $1: Name command (name/pinned) # $2: Map name # $3: bpftool path # $4: key for rw # $5: key to delete # $6: Whether write should succeed (true/false) # $7: BPF_DIR # $8: bpf iterator object file path
access_map() {
local name_cmd="$1"
local map_name="$2"
local bpftool_path="$3"
local key_for_rw="$4"
local key_to_del="$5"
local write_should_succeed="$6"
local bpf_dir="$7"
local bpf_iter_file_path="$8"
# Function to test map access with configurable write expectations # Parameters: # $1: Map name # $2: bpftool path # $3: BPF_DIR # $4: Whether write should succeed (true/false) # $5: bpf iterator object file path
test_map_access() {
local map_name="$1"
local bpftool_path="$2"
local bpf_dir="$3"
local pin_path="$bpf_dir/${map_name}_pinned"
local write_should_succeed="$4"
local bpf_iter_file_path="$5"
# Test access to the map by name.
access_map "name""$map_name""$bpftool_path""0 0 0 0""1 0 0 0" \ "$write_should_succeed""$bpf_dir""$bpf_iter_file_path"
# Pin the map to the BPF filesystem "$bpftool_path" map pin name "$map_name""$pin_path" if [ ! -e "$pin_path" ]; then echo" Failed to pin $map_name"
exit 1 fi
# Test access to the pinned map.
access_map "pinned""$pin_path""$bpftool_path""0 0 0 0""2 0 0 0" \ "$write_should_succeed""$bpf_dir""$bpf_iter_file_path"
}
# Function to test map creation and map-of-maps # Parameters: # $1: bpftool path # $2: BPF_DIR
test_map_creation_and_map_of_maps() {
local bpftool_path="$1"
local bpf_dir="$2"
local outer_map_name="outer_map_tt"
local inner_map_name="inner_map_tt"
"$bpftool_path" map create "$bpf_dir/$inner_map_name" type array key 4 \
value 4 entries 4 name "$inner_map_name" if [ ! -f "$bpf_dir/$inner_map_name" ]; then echo" Failed to create inner map file at $bpf_dir/$outer_map_name"
return 1 fi
"$bpftool_path" map create "$bpf_dir/$outer_map_name" type hash_of_maps \
key 4 value 4 entries 2 name "$outer_map_name" inner_map name "$inner_map_name" if [ ! -f "$bpf_dir/$outer_map_name" ]; then echo" Failed to create outer map file at $bpf_dir/$outer_map_name"
return 1 fi
# Add entries to the outer map by name and by pinned path. "$bpftool_path" map update pinned "$bpf_dir/$outer_map_name" key 0 0 0 0 \
value pinned "$bpf_dir/$inner_map_name" "$bpftool_path" map update name "$outer_map_name" key 1 0 0 0 value \
name "$inner_map_name"
# The outer map should be full by now. # The following map update command is expected to fail. if"$bpftool_path" map update name "$outer_map_name" key 2 0 0 0 value name \ "$inner_map_name" 2>/dev/null; then echo" Update for $outer_map_name succeeded but should have failed"
exit 1 fi
}
# Function to test map access with the btf list command # Parameters: # $1: bpftool path
test_map_access_with_btf_list() {
local bpftool_path="$1"
# The btf list command iterates over maps for # loaded BPF programs. if ! "$bpftool_path" btf list 1>/dev/null; then echo" Failed to access btf data"
exit 1 fi
}
set -eu
trap cleanup_skip EXIT
check_root_privileges
verify_bpftool_path "$BPFTOOL_PATH"
verify_btf_support
trap cleanup EXIT
# Load and attach the BPF programs to control maps access. "$BPFTOOL_PATH" prog loadall "$BPF_FILE_PATH""$BPF_DIR" autoattach
# Activate the map protection mechanism. Protection status is controlled # by a value stored in the prot_status_map at index 0. "$BPFTOOL_PATH" map update name prot_status_map key 0 0 0 0 value 1 0 0 0
# Test protected map (write should fail).
test_map_access "$PROTECTED_MAP_NAME""$BPFTOOL_PATH""$BPF_DIR""false" \ "$BPF_ITER_FILE_PATH"
# Test not protected map (write should succeed).
test_map_access "$NOT_PROTECTED_MAP_NAME""$BPFTOOL_PATH""$BPF_DIR""true" \ "$BPF_ITER_FILE_PATH"
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.