Skip to content

Commit b8c203b

Browse files
committed
xfrm: Generate queueing routes only from route lookup functions
Currently we genarate a queueing route if we have matching policies but can not resolve the states and the sysctl xfrm_larval_drop is disabled. Here we assume that dst_output() is called to kill the queued 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 queueing routes only from the route lookup functions, here we can guarantee a call to dst_output() afterwards. Fixes: a0073fe ("xfrm: Add a state resolution packet queue") Reported-by: Konstantinos Kolelis <k.kolelis@sirrix.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
1 parent f92ee61 commit b8c203b

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

include/net/dst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ void dst_init(void);
480480
/* Flags for xfrm_lookup flags argument. */
481481
enum {
482482
XFRM_LOOKUP_ICMP = 1 << 0,
483+
XFRM_LOOKUP_QUEUE = 1 << 1,
483484
};
484485

485486
struct flowi;

net/xfrm/xfrm_policy.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
#define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ))
4040
#define XFRM_MAX_QUEUE_LEN 100
4141

42+
struct xfrm_flo {
43+
struct dst_entry *dst_orig;
44+
u8 flags;
45+
};
46+
4247
static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock);
4348
static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO]
4449
__read_mostly;
@@ -1877,23 +1882,27 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)
18771882
}
18781883

18791884
static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
1880-
struct dst_entry *dst,
1885+
struct xfrm_flo *xflo,
18811886
const struct flowi *fl,
18821887
int num_xfrms,
18831888
u16 family)
18841889
{
18851890
int err;
18861891
struct net_device *dev;
1892+
struct dst_entry *dst;
18871893
struct dst_entry *dst1;
18881894
struct xfrm_dst *xdst;
18891895

18901896
xdst = xfrm_alloc_dst(net, family);
18911897
if (IS_ERR(xdst))
18921898
return xdst;
18931899

1894-
if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0)
1900+
if (!(xflo->flags & XFRM_LOOKUP_QUEUE) ||
1901+
net->xfrm.sysctl_larval_drop ||
1902+
num_xfrms <= 0)
18951903
return xdst;
18961904

1905+
dst = xflo->dst_orig;
18971906
dst1 = &xdst->u.dst;
18981907
dst_hold(dst);
18991908
xdst->route = dst;
@@ -1935,7 +1944,7 @@ static struct flow_cache_object *
19351944
xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
19361945
struct flow_cache_object *oldflo, void *ctx)
19371946
{
1938-
struct dst_entry *dst_orig = (struct dst_entry *)ctx;
1947+
struct xfrm_flo *xflo = (struct xfrm_flo *)ctx;
19391948
struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
19401949
struct xfrm_dst *xdst, *new_xdst;
19411950
int num_pols = 0, num_xfrms = 0, i, err, pol_dead;
@@ -1976,7 +1985,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
19761985
goto make_dummy_bundle;
19771986
}
19781987

1979-
new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig);
1988+
new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family,
1989+
xflo->dst_orig);
19801990
if (IS_ERR(new_xdst)) {
19811991
err = PTR_ERR(new_xdst);
19821992
if (err != -EAGAIN)
@@ -2010,7 +2020,7 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
20102020
/* We found policies, but there's no bundles to instantiate:
20112021
* either because the policy blocks, has no transformations or
20122022
* we could not build template (no xfrm_states).*/
2013-
xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family);
2023+
xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family);
20142024
if (IS_ERR(xdst)) {
20152025
xfrm_pols_put(pols, num_pols);
20162026
return ERR_CAST(xdst);
@@ -2104,13 +2114,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
21042114
}
21052115

21062116
if (xdst == NULL) {
2117+
struct xfrm_flo xflo;
2118+
2119+
xflo.dst_orig = dst_orig;
2120+
xflo.flags = flags;
2121+
21072122
/* To accelerate a bit... */
21082123
if ((dst_orig->flags & DST_NOXFRM) ||
21092124
!net->xfrm.policy_count[XFRM_POLICY_OUT])
21102125
goto nopol;
21112126

21122127
flo = flow_cache_lookup(net, fl, family, dir,
2113-
xfrm_bundle_lookup, dst_orig);
2128+
xfrm_bundle_lookup, &xflo);
21142129
if (flo == NULL)
21152130
goto nopol;
21162131
if (IS_ERR(flo)) {
@@ -2202,7 +2217,8 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
22022217
const struct flowi *fl,
22032218
struct sock *sk, int flags)
22042219
{
2205-
struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, flags);
2220+
struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk,
2221+
flags | XFRM_LOOKUP_QUEUE);
22062222

22072223
if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
22082224
return make_blackhole(net, dst_orig->ops->family, dst_orig);
@@ -2476,7 +2492,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
24762492

24772493
skb_dst_force(skb);
24782494

2479-
dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0);
2495+
dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE);
24802496
if (IS_ERR(dst)) {
24812497
res = 0;
24822498
dst = NULL;

0 commit comments

Comments
 (0)