Commit 35c715c3 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2021-01-21

1) Fix a rare panic on SMP systems when packet reordering
   happens between anti replay check and update.
   From Shmulik Ladkani.

2) Fix disable_xfrm sysctl when used on xfrm interfaces.
   From Eyal Birger.

3) Fix a race in PF_KEY when the availability of crypto
   algorithms is set. From Cong Wang.

4) Fix a return value override in the xfrm policy selftests.
   From Po-Hsu Lin.

5) Fix an integer wraparound in xfrm_policy_addr_delta.
   From Visa Hankala.

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec:
  xfrm: Fix wraparound in xfrm_policy_addr_delta()
  selftests: xfrm: fix test return value override issue in xfrm_policy.sh
  af_key: relax availability checks for skb size calculation
  xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
  xfrm: Fix oops in xfrm_replay_advance_bmp
====================

Link: https://lore.kernel.org/r/20210121121558.621339-1-steffen.klassert@secunet.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 1c45ba93 da64ae2d
...@@ -2902,7 +2902,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t) ...@@ -2902,7 +2902,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t)
break; break;
if (!aalg->pfkey_supported) if (!aalg->pfkey_supported)
continue; continue;
if (aalg_tmpl_set(t, aalg) && aalg->available) if (aalg_tmpl_set(t, aalg))
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
return sz + sizeof(struct sadb_prop); return sz + sizeof(struct sadb_prop);
...@@ -2920,7 +2920,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) ...@@ -2920,7 +2920,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
if (!ealg->pfkey_supported) if (!ealg->pfkey_supported)
continue; continue;
if (!(ealg_tmpl_set(t, ealg) && ealg->available)) if (!(ealg_tmpl_set(t, ealg)))
continue; continue;
for (k = 1; ; k++) { for (k = 1; ; k++) {
...@@ -2931,7 +2931,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) ...@@ -2931,7 +2931,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
if (!aalg->pfkey_supported) if (!aalg->pfkey_supported)
continue; continue;
if (aalg_tmpl_set(t, aalg) && aalg->available) if (aalg_tmpl_set(t, aalg))
sz += sizeof(struct sadb_comb); sz += sizeof(struct sadb_comb);
} }
} }
......
...@@ -660,7 +660,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -660,7 +660,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
/* only the first xfrm gets the encap type */ /* only the first xfrm gets the encap type */
encap_type = 0; encap_type = 0;
if (async && x->repl->recheck(x, skb, seq)) { if (x->repl->recheck(x, skb, seq)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
goto drop_unlock; goto drop_unlock;
} }
......
...@@ -793,15 +793,22 @@ static int xfrm_policy_addr_delta(const xfrm_address_t *a, ...@@ -793,15 +793,22 @@ static int xfrm_policy_addr_delta(const xfrm_address_t *a,
const xfrm_address_t *b, const xfrm_address_t *b,
u8 prefixlen, u16 family) u8 prefixlen, u16 family)
{ {
u32 ma, mb, mask;
unsigned int pdw, pbi; unsigned int pdw, pbi;
int delta = 0; int delta = 0;
switch (family) { switch (family) {
case AF_INET: case AF_INET:
if (sizeof(long) == 4 && prefixlen == 0) if (prefixlen == 0)
return ntohl(a->a4) - ntohl(b->a4); return 0;
return (ntohl(a->a4) & ((~0UL << (32 - prefixlen)))) - mask = ~0U << (32 - prefixlen);
(ntohl(b->a4) & ((~0UL << (32 - prefixlen)))); ma = ntohl(a->a4) & mask;
mb = ntohl(b->a4) & mask;
if (ma < mb)
delta = -1;
else if (ma > mb)
delta = 1;
break;
case AF_INET6: case AF_INET6:
pdw = prefixlen >> 5; pdw = prefixlen >> 5;
pbi = prefixlen & 0x1f; pbi = prefixlen & 0x1f;
...@@ -812,10 +819,13 @@ static int xfrm_policy_addr_delta(const xfrm_address_t *a, ...@@ -812,10 +819,13 @@ static int xfrm_policy_addr_delta(const xfrm_address_t *a,
return delta; return delta;
} }
if (pbi) { if (pbi) {
u32 mask = ~0u << (32 - pbi); mask = ~0U << (32 - pbi);
ma = ntohl(a->a6[pdw]) & mask;
delta = (ntohl(a->a6[pdw]) & mask) - mb = ntohl(b->a6[pdw]) & mask;
(ntohl(b->a6[pdw]) & mask); if (ma < mb)
delta = -1;
else if (ma > mb)
delta = 1;
} }
break; break;
default: default:
...@@ -3078,8 +3088,8 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net, ...@@ -3078,8 +3088,8 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net,
xflo.flags = flags; xflo.flags = flags;
/* To accelerate a bit... */ /* To accelerate a bit... */
if ((dst_orig->flags & DST_NOXFRM) || if (!if_id && ((dst_orig->flags & DST_NOXFRM) ||
!net->xfrm.policy_count[XFRM_POLICY_OUT]) !net->xfrm.policy_count[XFRM_POLICY_OUT]))
goto nopol; goto nopol;
xdst = xfrm_bundle_lookup(net, fl, family, dir, &xflo, if_id); xdst = xfrm_bundle_lookup(net, fl, family, dir, &xflo, if_id);
......
...@@ -202,7 +202,7 @@ check_xfrm() { ...@@ -202,7 +202,7 @@ check_xfrm() {
# 1: iptables -m policy rule count != 0 # 1: iptables -m policy rule count != 0
rval=$1 rval=$1
ip=$2 ip=$2
lret=0 local lret=0
ip netns exec ns1 ping -q -c 1 10.0.2.$ip > /dev/null ip netns exec ns1 ping -q -c 1 10.0.2.$ip > /dev/null
...@@ -287,6 +287,47 @@ check_hthresh_repeat() ...@@ -287,6 +287,47 @@ check_hthresh_repeat()
return 0 return 0
} }
# insert non-overlapping policies in a random order and check that
# all of them can be fetched using the traffic selectors.
check_random_order()
{
local ns=$1
local log=$2
for i in $(seq 100); do
ip -net $ns xfrm policy flush
for j in $(seq 0 16 255 | sort -R); do
ip -net $ns xfrm policy add dst $j.0.0.0/24 dir out priority 10 action allow
done
for j in $(seq 0 16 255); do
if ! ip -net $ns xfrm policy get dst $j.0.0.0/24 dir out > /dev/null; then
echo "FAIL: $log" 1>&2
return 1
fi
done
done
for i in $(seq 100); do
ip -net $ns xfrm policy flush
for j in $(seq 0 16 255 | sort -R); do
local addr=$(printf "e000:0000:%02x00::/56" $j)
ip -net $ns xfrm policy add dst $addr dir out priority 10 action allow
done
for j in $(seq 0 16 255); do
local addr=$(printf "e000:0000:%02x00::/56" $j)
if ! ip -net $ns xfrm policy get dst $addr dir out > /dev/null; then
echo "FAIL: $log" 1>&2
return 1
fi
done
done
ip -net $ns xfrm policy flush
echo "PASS: $log"
return 0
}
#check for needed privileges #check for needed privileges
if [ "$(id -u)" -ne 0 ];then if [ "$(id -u)" -ne 0 ];then
echo "SKIP: Need root privileges" echo "SKIP: Need root privileges"
...@@ -438,6 +479,8 @@ check_exceptions "exceptions and block policies after htresh change to normal" ...@@ -438,6 +479,8 @@ check_exceptions "exceptions and block policies after htresh change to normal"
check_hthresh_repeat "policies with repeated htresh change" check_hthresh_repeat "policies with repeated htresh change"
check_random_order ns3 "policies inserted in random order"
for i in 1 2 3 4;do ip netns del ns$i;done for i in 1 2 3 4;do ip netns del ns$i;done
exit $ret exit $ret
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment