Skip to content

Commit f92ee61

Browse files
committed
xfrm: Generate blackhole routes only from route lookup functions
Currently we genarate a blackhole route route whenever we have matching policies but can not resolve the states. Here we assume that dst_output() is called to kill the balckholed packets. Unfortunately this assumption is not true in all cases, so it is possible that these packets leave the system unwanted. We fix this by generating blackhole routes only from the route lookup functions, here we can guarantee a call to dst_output() afterwards. Fixes: 2774c13 ("xfrm: Handle blackhole route creation via afinfo.") Reported-by: Konstantinos Kolelis <k.kolelis@sirrix.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
1 parent 95cd6f4 commit f92ee61

File tree

4 files changed

+36
-7
lines changed

4 files changed

+36
-7
lines changed

include/net/dst.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,16 @@ static inline struct dst_entry *xfrm_lookup(struct net *net,
490490
int flags)
491491
{
492492
return dst_orig;
493-
}
493+
}
494+
495+
static inline struct dst_entry *xfrm_lookup_route(struct net *net,
496+
struct dst_entry *dst_orig,
497+
const struct flowi *fl,
498+
struct sock *sk,
499+
int flags)
500+
{
501+
return dst_orig;
502+
}
494503

495504
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
496505
{
@@ -502,6 +511,10 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
502511
const struct flowi *fl, struct sock *sk,
503512
int flags);
504513

514+
struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
515+
const struct flowi *fl, struct sock *sk,
516+
int flags);
517+
505518
/* skb attached with this dst needs transformation if dst->xfrm is valid */
506519
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
507520
{

net/ipv4/route.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,9 +2265,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
22652265
return rt;
22662266

22672267
if (flp4->flowi4_proto)
2268-
rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
2269-
flowi4_to_flowi(flp4),
2270-
sk, 0);
2268+
rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst,
2269+
flowi4_to_flowi(flp4),
2270+
sk, 0);
22712271

22722272
return rt;
22732273
}

net/ipv6/ip6_output.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
10091009
if (final_dst)
10101010
fl6->daddr = *final_dst;
10111011

1012-
return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
1012+
return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
10131013
}
10141014
EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
10151015

@@ -1041,7 +1041,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
10411041
if (final_dst)
10421042
fl6->daddr = *final_dst;
10431043

1044-
return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
1044+
return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
10451045
}
10461046
EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
10471047

net/xfrm/xfrm_policy.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2138,7 +2138,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
21382138
xfrm_pols_put(pols, drop_pols);
21392139
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
21402140

2141-
return make_blackhole(net, family, dst_orig);
2141+
return ERR_PTR(-EREMOTE);
21422142
}
21432143

21442144
err = -EAGAIN;
@@ -2195,6 +2195,22 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
21952195
}
21962196
EXPORT_SYMBOL(xfrm_lookup);
21972197

2198+
/* Callers of xfrm_lookup_route() must ensure a call to dst_output().
2199+
* Otherwise we may send out blackholed packets.
2200+
*/
2201+
struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
2202+
const struct flowi *fl,
2203+
struct sock *sk, int flags)
2204+
{
2205+
struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, flags);
2206+
2207+
if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
2208+
return make_blackhole(net, dst_orig->ops->family, dst_orig);
2209+
2210+
return dst;
2211+
}
2212+
EXPORT_SYMBOL(xfrm_lookup_route);
2213+
21982214
static inline int
21992215
xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
22002216
{

0 commit comments

Comments
 (0)