Commit 42cf93cd authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: Fix bridge netfilter related in xfrm_lookup

The bridge-netfilter code attaches a fake dst_entry with dst->ops == NULL
to purely bridged packets. When these packets are SNATed and a policy
lookup is done, xfrm_lookup crashes because it tries to dereference
dst->ops.

Change xfrm_lookup not to dereference dst->ops before checking for the
DST_NOXFRM flag and set this flag in the fake dst_entry.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a80614d1
...@@ -90,6 +90,7 @@ static struct rtable __fake_rtable = { ...@@ -90,6 +90,7 @@ static struct rtable __fake_rtable = {
.dev = &__fake_net_device, .dev = &__fake_net_device,
.path = &__fake_rtable.u.dst, .path = &__fake_rtable.u.dst,
.metrics = {[RTAX_MTU - 1] = 1500}, .metrics = {[RTAX_MTU - 1] = 1500},
.flags = DST_NOXFRM,
} }
}, },
.rt_flags = 0, .rt_flags = 0,
......
...@@ -782,7 +782,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, ...@@ -782,7 +782,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
int nx = 0; int nx = 0;
int err; int err;
u32 genid; u32 genid;
u16 family = dst_orig->ops->family; u16 family;
u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
u32 sk_sid = security_sk_sid(sk, fl, dir); u32 sk_sid = security_sk_sid(sk, fl, dir);
restart: restart:
...@@ -796,13 +796,14 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, ...@@ -796,13 +796,14 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
return 0; return 0;
policy = flow_cache_lookup(fl, sk_sid, family, dir, policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family,
xfrm_policy_lookup); dir, xfrm_policy_lookup);
} }
if (!policy) if (!policy)
return 0; return 0;
family = dst_orig->ops->family;
policy->curlft.use_time = (unsigned long)xtime.tv_sec; policy->curlft.use_time = (unsigned long)xtime.tv_sec;
switch (policy->action) { switch (policy->action) {
......
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