[XFRM] IPV6: Restrict bundle reusing
For outbound transformation, bundle is checked whether it is suitable for current flow to be reused or not. In such IPv6 case as below, transformation may apply incorrect bundle for the flow instead of creating another bundle: - The policy selector has destination prefix length < 128 (Two or more addresses can be matched it) - Its bundle holds dst entry of default route whose prefix length < 128 (Previous traffic was used such route as next hop) - The policy and the bundle were used a transport mode state and this time flow address is not matched the bundled state. This issue is found by Mobile IPv6 usage to protect mobility signaling by IPsec, but it is not a Mobile IPv6 specific. This patch adds strict check to xfrm_bundle_ok() for each state mode and address when prefix length is less than 128. Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
9afaca0579
commit
e53820de0f
@@ -1167,7 +1167,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
|
||||
|
||||
static int stale_bundle(struct dst_entry *dst)
|
||||
{
|
||||
return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC);
|
||||
return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
|
||||
}
|
||||
|
||||
void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
|
||||
@@ -1282,7 +1282,7 @@ EXPORT_SYMBOL(xfrm_init_pmtu);
|
||||
* still valid.
|
||||
*/
|
||||
|
||||
int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
|
||||
int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict)
|
||||
{
|
||||
struct dst_entry *dst = &first->u.dst;
|
||||
struct xfrm_dst *last;
|
||||
@@ -1304,6 +1304,10 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
|
||||
if (dst->xfrm->km.state != XFRM_STATE_VALID)
|
||||
return 0;
|
||||
|
||||
if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL &&
|
||||
!xfrm_state_addr_flow_check(dst->xfrm, fl, family))
|
||||
return 0;
|
||||
|
||||
mtu = dst_mtu(dst->child);
|
||||
if (xdst->child_mtu_cached != mtu) {
|
||||
last = xdst;
|
||||
|
Reference in New Issue
Block a user