cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xfrm_policy.sh (14759B)


      1#!/bin/bash
      2# SPDX-License-Identifier: GPL-2.0
      3#
      4# Check xfrm policy resolution.  Topology:
      5#
      6# 1.2   1.1   3.1  3.10    2.1   2.2
      7# eth1  eth1 veth0 veth0 eth1   eth1
      8# ns1 ---- ns3 ----- ns4 ---- ns2
      9#
     10# ns3 and ns4 are connected via ipsec tunnel.
     11# pings from ns1 to ns2 (and vice versa) are supposed to work like this:
     12# ns1: ping 10.0.2.2: passes via ipsec tunnel.
     13# ns2: ping 10.0.1.2: passes via ipsec tunnel.
     14
     15# ns1: ping 10.0.1.253: passes via ipsec tunnel (direct policy)
     16# ns2: ping 10.0.2.253: passes via ipsec tunnel (direct policy)
     17#
     18# ns1: ping 10.0.2.254: does NOT pass via ipsec tunnel (exception)
     19# ns2: ping 10.0.1.254: does NOT pass via ipsec tunnel (exception)
     20
     21# Kselftest framework requirement - SKIP code is 4.
     22ksft_skip=4
     23ret=0
     24policy_checks_ok=1
     25
     26KEY_SHA=0xdeadbeef1234567890abcdefabcdefabcdefabcd
     27KEY_AES=0x0123456789abcdef0123456789012345
     28SPI1=0x1
     29SPI2=0x2
     30
     31do_esp_policy() {
     32    local ns=$1
     33    local me=$2
     34    local remote=$3
     35    local lnet=$4
     36    local rnet=$5
     37
     38    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
     39    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow
     40    # to fwd decrypted packets after esp processing:
     41    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow
     42}
     43
     44do_esp() {
     45    local ns=$1
     46    local me=$2
     47    local remote=$3
     48    local lnet=$4
     49    local rnet=$5
     50    local spi_out=$6
     51    local spi_in=$7
     52
     53    ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in  enc aes $KEY_AES  auth sha1 $KEY_SHA  mode tunnel sel src $rnet dst $lnet
     54    ip -net $ns xfrm state add src $me  dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
     55
     56    do_esp_policy $ns $me $remote $lnet $rnet
     57}
     58
     59# add policies with different netmasks, to make sure kernel carries
     60# the policies contained within new netmask over when search tree is
     61# re-built.
     62# peer netns that are supposed to be encapsulated via esp have addresses
     63# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively.
     64#
     65# Adding a policy for '10.0.1.0/23' will make it necessary to
     66# alter the prefix of 10.0.1.0 subnet.
     67# In case new prefix overlaps with existing node, the node and all
     68# policies it carries need to be merged with the existing one(s).
     69#
     70# Do that here.
     71do_overlap()
     72{
     73    local ns=$1
     74
     75    # adds new nodes to tree (neither network exists yet in policy database).
     76    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
     77
     78    # adds a new node in the 10.0.0.0/24 tree (dst node exists).
     79    ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
     80
     81    # adds a 10.2.0.0/23 node, but for different dst.
     82    ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block
     83
     84    # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd.
     85    # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23.
     86    # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node
     87    # also has to be merged too, including source-sorted subtrees.
     88    # old:
     89    # 10.0.0.0/24 (node 1 in dst tree of the bin)
     90    #    10.1.0.0/24 (node in src tree of dst node 1)
     91    #    10.2.0.0/24 (node in src tree of dst node 1)
     92    # 10.0.1.0/24 (node 2 in dst tree of the bin)
     93    #    10.0.2.0/24 (node in src tree of dst node 2)
     94    #    10.2.0.0/24 (node in src tree of dst node 2)
     95    #
     96    # The next 'policy add' adds dst '10.0.0.0/23', which means
     97    # that dst node 1 and dst node 2 have to be merged including
     98    # the sub-tree.  As no duplicates are allowed, policies in
     99    # the two '10.0.2.0/24' are also merged.
    100    #
    101    # after the 'add', internal search tree should look like this:
    102    # 10.0.0.0/23 (node in dst tree of bin)
    103    #     10.0.2.0/24 (node in src tree of dst node)
    104    #     10.1.0.0/24 (node in src tree of dst node)
    105    #     10.2.0.0/24 (node in src tree of dst node)
    106    #
    107    # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
    108    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
    109
    110    # similar to above: add policies (with partially random address), with shrinking prefixes.
    111    for p in 29 28 27;do
    112      for k in $(seq 1 32); do
    113       ip -net $ns xfrm policy add src 10.253.1.$((RANDOM%255))/$p dst 10.254.1.$((RANDOM%255))/$p dir fwd priority $((200+k)) action block 2>/dev/null
    114      done
    115    done
    116}
    117
    118do_esp_policy_get_check() {
    119    local ns=$1
    120    local lnet=$2
    121    local rnet=$3
    122
    123    ip -net $ns xfrm policy get src $lnet dst $rnet dir out > /dev/null
    124    if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then
    125        policy_checks_ok=0
    126        echo "FAIL: ip -net $ns xfrm policy get src $lnet dst $rnet dir out"
    127        ret=1
    128    fi
    129
    130    ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd > /dev/null
    131    if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then
    132        policy_checks_ok=0
    133        echo "FAIL: ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd"
    134        ret=1
    135    fi
    136}
    137
    138do_exception() {
    139    local ns=$1
    140    local me=$2
    141    local remote=$3
    142    local encryptip=$4
    143    local plain=$5
    144
    145    # network $plain passes without tunnel
    146    ip -net $ns xfrm policy add dst $plain dir out priority 10 action allow
    147
    148    # direct policy for $encryptip, use tunnel, higher prio takes precedence
    149    ip -net $ns xfrm policy add dst $encryptip dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow
    150}
    151
    152# policies that are not supposed to match any packets generated in this test.
    153do_dummies4() {
    154    local ns=$1
    155
    156    for i in $(seq 10 16);do
    157      # dummy policy with wildcard src/dst.
    158      echo netns exec $ns ip xfrm policy add src 0.0.0.0/0 dst 10.$i.99.0/30 dir out action block
    159      echo netns exec $ns ip xfrm policy add src 10.$i.99.0/30 dst 0.0.0.0/0 dir out action block
    160      for j in $(seq 32 64);do
    161        echo netns exec $ns ip xfrm policy add src 10.$i.1.0/30 dst 10.$i.$j.0/30 dir out action block
    162        # silly, as it encompasses the one above too, but its allowed:
    163        echo netns exec $ns ip xfrm policy add src 10.$i.1.0/29 dst 10.$i.$j.0/29 dir out action block
    164        # and yet again, even more broad one.
    165        echo netns exec $ns ip xfrm policy add src 10.$i.1.0/24 dst 10.$i.$j.0/24 dir out action block
    166        echo netns exec $ns ip xfrm policy add src 10.$i.$j.0/24 dst 10.$i.1.0/24 dir fwd action block
    167      done
    168    done | ip -batch /dev/stdin
    169}
    170
    171do_dummies6() {
    172    local ns=$1
    173
    174    for i in $(seq 10 16);do
    175      for j in $(seq 32 64);do
    176       echo netns exec $ns ip xfrm policy add src dead:$i::/64 dst dead:$i:$j::/64 dir out action block
    177       echo netns exec $ns ip xfrm policy add src dead:$i:$j::/64 dst dead:$i::/24 dir fwd action block
    178      done
    179    done | ip -batch /dev/stdin
    180}
    181
    182check_ipt_policy_count()
    183{
    184	ns=$1
    185
    186	ip netns exec $ns iptables-save -c |grep policy | ( read c rest
    187		ip netns exec $ns iptables -Z
    188		if [ x"$c" = x'[0:0]' ]; then
    189			exit 0
    190		elif [ x"$c" = x ]; then
    191			echo "ERROR: No counters"
    192			ret=1
    193			exit 111
    194		else
    195			exit 1
    196		fi
    197	)
    198}
    199
    200check_xfrm() {
    201	# 0: iptables -m policy rule count == 0
    202	# 1: iptables -m policy rule count != 0
    203	rval=$1
    204	ip=$2
    205	local lret=0
    206
    207	ip netns exec ns1 ping -q -c 1 10.0.2.$ip > /dev/null
    208
    209	check_ipt_policy_count ns3
    210	if [ $? -ne $rval ] ; then
    211		lret=1
    212	fi
    213	check_ipt_policy_count ns4
    214	if [ $? -ne $rval ] ; then
    215		lret=1
    216	fi
    217
    218	ip netns exec ns2 ping -q -c 1 10.0.1.$ip > /dev/null
    219
    220	check_ipt_policy_count ns3
    221	if [ $? -ne $rval ] ; then
    222		lret=1
    223	fi
    224	check_ipt_policy_count ns4
    225	if [ $? -ne $rval ] ; then
    226		lret=1
    227	fi
    228
    229	return $lret
    230}
    231
    232check_exceptions()
    233{
    234	logpostfix="$1"
    235	local lret=0
    236
    237	# ping to .254 should be excluded from the tunnel (exception is in place).
    238	check_xfrm 0 254
    239	if [ $? -ne 0 ]; then
    240		echo "FAIL: expected ping to .254 to fail ($logpostfix)"
    241		lret=1
    242	else
    243		echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)"
    244	fi
    245
    246	# ping to .253 should use use ipsec due to direct policy exception.
    247	check_xfrm 1 253
    248	if [ $? -ne 0 ]; then
    249		echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)"
    250		lret=1
    251	else
    252		echo "PASS: direct policy matches ($logpostfix)"
    253	fi
    254
    255	# ping to .2 should use ipsec.
    256	check_xfrm 1 2
    257	if [ $? -ne 0 ]; then
    258		echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)"
    259		lret=1
    260	else
    261		echo "PASS: policy matches ($logpostfix)"
    262	fi
    263
    264	return $lret
    265}
    266
    267check_hthresh_repeat()
    268{
    269	local log=$1
    270	i=0
    271
    272	for i in $(seq 1 10);do
    273		ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::0014:0000:0001 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break
    274		ip -net ns1 xfrm policy set hthresh6 0 28 || break
    275
    276		ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::01 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break
    277		ip -net ns1 xfrm policy set hthresh6 0 28 || break
    278	done
    279
    280	if [ $i -ne 10 ] ;then
    281		echo "FAIL: $log" 1>&2
    282		ret=1
    283		return 1
    284	fi
    285
    286	echo "PASS: $log"
    287	return 0
    288}
    289
    290# insert non-overlapping policies in a random order and check that
    291# all of them can be fetched using the traffic selectors.
    292check_random_order()
    293{
    294	local ns=$1
    295	local log=$2
    296
    297	for i in $(seq 100); do
    298		ip -net $ns xfrm policy flush
    299		for j in $(seq 0 16 255 | sort -R); do
    300			ip -net $ns xfrm policy add dst $j.0.0.0/24 dir out priority 10 action allow
    301		done
    302		for j in $(seq 0 16 255); do
    303			if ! ip -net $ns xfrm policy get dst $j.0.0.0/24 dir out > /dev/null; then
    304				echo "FAIL: $log" 1>&2
    305				return 1
    306			fi
    307		done
    308	done
    309
    310	for i in $(seq 100); do
    311		ip -net $ns xfrm policy flush
    312		for j in $(seq 0 16 255 | sort -R); do
    313			local addr=$(printf "e000:0000:%02x00::/56" $j)
    314			ip -net $ns xfrm policy add dst $addr dir out priority 10 action allow
    315		done
    316		for j in $(seq 0 16 255); do
    317			local addr=$(printf "e000:0000:%02x00::/56" $j)
    318			if ! ip -net $ns xfrm policy get dst $addr dir out > /dev/null; then
    319				echo "FAIL: $log" 1>&2
    320				return 1
    321			fi
    322		done
    323	done
    324
    325	ip -net $ns xfrm policy flush
    326
    327	echo "PASS: $log"
    328	return 0
    329}
    330
    331#check for needed privileges
    332if [ "$(id -u)" -ne 0 ];then
    333	echo "SKIP: Need root privileges"
    334	exit $ksft_skip
    335fi
    336
    337ip -Version 2>/dev/null >/dev/null
    338if [ $? -ne 0 ];then
    339	echo "SKIP: Could not run test without the ip tool"
    340	exit $ksft_skip
    341fi
    342
    343# needed to check if policy lookup got valid ipsec result
    344iptables --version 2>/dev/null >/dev/null
    345if [ $? -ne 0 ];then
    346	echo "SKIP: Could not run test without iptables tool"
    347	exit $ksft_skip
    348fi
    349
    350for i in 1 2 3 4; do
    351    ip netns add ns$i
    352    ip -net ns$i link set lo up
    353done
    354
    355DEV=veth0
    356ip link add $DEV netns ns1 type veth peer name eth1 netns ns3
    357ip link add $DEV netns ns2 type veth peer name eth1 netns ns4
    358
    359ip link add $DEV netns ns3 type veth peer name veth0 netns ns4
    360
    361DEV=veth0
    362for i in 1 2; do
    363    ip -net ns$i link set $DEV up
    364    ip -net ns$i addr add 10.0.$i.2/24 dev $DEV
    365    ip -net ns$i addr add dead:$i::2/64 dev $DEV
    366
    367    ip -net ns$i addr add 10.0.$i.253 dev $DEV
    368    ip -net ns$i addr add 10.0.$i.254 dev $DEV
    369    ip -net ns$i addr add dead:$i::fd dev $DEV
    370    ip -net ns$i addr add dead:$i::fe dev $DEV
    371done
    372
    373for i in 3 4; do
    374ip -net ns$i link set eth1 up
    375ip -net ns$i link set veth0 up
    376done
    377
    378ip -net ns1 route add default via 10.0.1.1
    379ip -net ns2 route add default via 10.0.2.1
    380
    381ip -net ns3 addr add 10.0.1.1/24 dev eth1
    382ip -net ns3 addr add 10.0.3.1/24 dev veth0
    383ip -net ns3 addr add 2001:1::1/64 dev eth1
    384ip -net ns3 addr add 2001:3::1/64 dev veth0
    385
    386ip -net ns3 route add default via 10.0.3.10
    387
    388ip -net ns4 addr add 10.0.2.1/24 dev eth1
    389ip -net ns4 addr add 10.0.3.10/24 dev veth0
    390ip -net ns4 addr add 2001:2::1/64 dev eth1
    391ip -net ns4 addr add 2001:3::10/64 dev veth0
    392ip -net ns4 route add default via 10.0.3.1
    393
    394for j in 4 6; do
    395	for i in 3 4;do
    396		ip netns exec ns$i sysctl net.ipv$j.conf.eth1.forwarding=1 > /dev/null
    397		ip netns exec ns$i sysctl net.ipv$j.conf.veth0.forwarding=1 > /dev/null
    398	done
    399done
    400
    401# abuse iptables rule counter to check if ping matches a policy
    402ip netns exec ns3 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec
    403ip netns exec ns4 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec
    404if [ $? -ne 0 ];then
    405	echo "SKIP: Could not insert iptables rule"
    406	for i in 1 2 3 4;do ip netns del ns$i;done
    407	exit $ksft_skip
    408fi
    409
    410#          localip  remoteip  localnet    remotenet
    411do_esp ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
    412do_esp ns3 dead:3::1 dead:3::10 dead:1::/64 dead:2::/64 $SPI1 $SPI2
    413do_esp ns4 10.0.3.10 10.0.3.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
    414do_esp ns4 dead:3::10 dead:3::1 dead:2::/64 dead:1::/64 $SPI2 $SPI1
    415
    416do_dummies4 ns3
    417do_dummies6 ns4
    418
    419do_esp_policy_get_check ns3 10.0.1.0/24 10.0.2.0/24
    420do_esp_policy_get_check ns4 10.0.2.0/24 10.0.1.0/24
    421do_esp_policy_get_check ns3 dead:1::/64 dead:2::/64
    422do_esp_policy_get_check ns4 dead:2::/64 dead:1::/64
    423
    424# ping to .254 should use ipsec, exception is not installed.
    425check_xfrm 1 254
    426if [ $? -ne 0 ]; then
    427	echo "FAIL: expected ping to .254 to use ipsec tunnel"
    428	ret=1
    429else
    430	echo "PASS: policy before exception matches"
    431fi
    432
    433# installs exceptions
    434#                localip  remoteip   encryptdst  plaindst
    435do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
    436do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28
    437
    438do_exception ns3 dead:3::1 dead:3::10 dead:2::fd  dead:2:f0::/96
    439do_exception ns4 dead:3::10 dead:3::1 dead:1::fd  dead:1:f0::/96
    440
    441check_exceptions "exceptions"
    442if [ $? -ne 0 ]; then
    443	ret=1
    444fi
    445
    446# insert block policies with adjacent/overlapping netmasks
    447do_overlap ns3
    448
    449check_exceptions "exceptions and block policies"
    450if [ $? -ne 0 ]; then
    451	ret=1
    452fi
    453
    454for n in ns3 ns4;do
    455	ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125
    456	sleep $((RANDOM%5))
    457done
    458
    459check_exceptions "exceptions and block policies after hresh changes"
    460
    461# full flush of policy db, check everything gets freed incl. internal meta data
    462ip -net ns3 xfrm policy flush
    463
    464do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24
    465do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
    466
    467# move inexact policies to hash table
    468ip -net ns3 xfrm policy set hthresh4 16 16
    469
    470sleep $((RANDOM%5))
    471check_exceptions "exceptions and block policies after hthresh change in ns3"
    472
    473# restore original hthresh settings -- move policies back to tables
    474for n in ns3 ns4;do
    475	ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
    476	sleep $((RANDOM%5))
    477done
    478check_exceptions "exceptions and block policies after htresh change to normal"
    479
    480check_hthresh_repeat "policies with repeated htresh change"
    481
    482check_random_order ns3 "policies inserted in random order"
    483
    484for i in 1 2 3 4;do ip netns del ns$i;done
    485
    486exit $ret