Skip to content

Commit e00dd94

Browse files
committed
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2020-03-27 1) Handle NETDEV_UNREGISTER for xfrm device to handle asynchronous unregister events cleanly. From Raed Salem. 2) Fix vti6 tunnel inter address family TX through bpf_redirect(). From Nicolas Dichtel. 3) Fix lenght check in verify_sec_ctx_len() to avoid a slab-out-of-bounds. From Xin Long. 4) Add a missing verify_sec_ctx_len check in xfrm_add_acquire to avoid a possible out-of-bounds to access. From Xin Long. 5) Use built-in RCU list checking of hlist_for_each_entry_rcu to silence false lockdep warning in __xfrm6_tunnel_spi_lookup when CONFIG_PROVE_RCU_LIST is enabled. From Madhuparna Bhowmik. 6) Fix a panic on esp offload when crypto is done asynchronously. From Xin Long. 7) Fix a skb memory leak in an error path of vti6_rcv. From Torsten Hilbrich. 8) Fix a race that can lead to a doulbe free in xfrm_policy_timer. From Xin Long. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8262e6f + 4c59406 commit e00dd94

File tree

7 files changed

+70
-22
lines changed

7 files changed

+70
-22
lines changed

net/ipv4/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ config SYN_COOKIES
303303

304304
config NET_IPVTI
305305
tristate "Virtual (secure) IP: tunneling"
306+
depends on IPV6 || IPV6=n
306307
select INET_TUNNEL
307308
select NET_IP_TUNNEL
308309
select XFRM

net/ipv4/ip_vti.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,17 +187,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
187187
int mtu;
188188

189189
if (!dst) {
190-
struct rtable *rt;
191-
192-
fl->u.ip4.flowi4_oif = dev->ifindex;
193-
fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
194-
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
195-
if (IS_ERR(rt)) {
190+
switch (skb->protocol) {
191+
case htons(ETH_P_IP): {
192+
struct rtable *rt;
193+
194+
fl->u.ip4.flowi4_oif = dev->ifindex;
195+
fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
196+
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
197+
if (IS_ERR(rt)) {
198+
dev->stats.tx_carrier_errors++;
199+
goto tx_error_icmp;
200+
}
201+
dst = &rt->dst;
202+
skb_dst_set(skb, dst);
203+
break;
204+
}
205+
#if IS_ENABLED(CONFIG_IPV6)
206+
case htons(ETH_P_IPV6):
207+
fl->u.ip6.flowi6_oif = dev->ifindex;
208+
fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
209+
dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
210+
if (dst->error) {
211+
dst_release(dst);
212+
dst = NULL;
213+
dev->stats.tx_carrier_errors++;
214+
goto tx_error_icmp;
215+
}
216+
skb_dst_set(skb, dst);
217+
break;
218+
#endif
219+
default:
196220
dev->stats.tx_carrier_errors++;
197221
goto tx_error_icmp;
198222
}
199-
dst = &rt->dst;
200-
skb_dst_set(skb, dst);
201223
}
202224

203225
dst_hold(dst);

net/ipv6/ip6_vti.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb)
311311

312312
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
313313
rcu_read_unlock();
314-
return 0;
314+
goto discard;
315315
}
316316

317317
ipv6h = ipv6_hdr(skb);
@@ -450,15 +450,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
450450
int mtu;
451451

452452
if (!dst) {
453-
fl->u.ip6.flowi6_oif = dev->ifindex;
454-
fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
455-
dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
456-
if (dst->error) {
457-
dst_release(dst);
458-
dst = NULL;
453+
switch (skb->protocol) {
454+
case htons(ETH_P_IP): {
455+
struct rtable *rt;
456+
457+
fl->u.ip4.flowi4_oif = dev->ifindex;
458+
fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
459+
rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
460+
if (IS_ERR(rt))
461+
goto tx_err_link_failure;
462+
dst = &rt->dst;
463+
skb_dst_set(skb, dst);
464+
break;
465+
}
466+
case htons(ETH_P_IPV6):
467+
fl->u.ip6.flowi6_oif = dev->ifindex;
468+
fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
469+
dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
470+
if (dst->error) {
471+
dst_release(dst);
472+
dst = NULL;
473+
goto tx_err_link_failure;
474+
}
475+
skb_dst_set(skb, dst);
476+
break;
477+
default:
459478
goto tx_err_link_failure;
460479
}
461-
skb_dst_set(skb, dst);
462480
}
463481

464482
dst_hold(dst);

net/ipv6/xfrm6_tunnel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const
7878

7979
hlist_for_each_entry_rcu(x6spi,
8080
&xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
81-
list_byaddr) {
81+
list_byaddr, lockdep_is_held(&xfrm6_tunnel_spi_lock)) {
8282
if (xfrm6_addr_equal(&x6spi->addr, saddr))
8383
return x6spi;
8484
}

net/xfrm/xfrm_device.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
7878
int err;
7979
unsigned long flags;
8080
struct xfrm_state *x;
81-
struct sk_buff *skb2, *nskb;
8281
struct softnet_data *sd;
82+
struct sk_buff *skb2, *nskb, *pskb = NULL;
8383
netdev_features_t esp_features = features;
8484
struct xfrm_offload *xo = xfrm_offload(skb);
8585
struct sec_path *sp;
@@ -168,14 +168,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
168168
} else {
169169
if (skb == skb2)
170170
skb = nskb;
171-
172-
if (!skb)
173-
return NULL;
171+
else
172+
pskb->next = nskb;
174173

175174
continue;
176175
}
177176

178177
skb_push(skb2, skb2->data - skb_mac_header(skb2));
178+
pskb = skb2;
179179
}
180180

181181
return skb;
@@ -383,6 +383,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
383383
return xfrm_dev_feat_change(dev);
384384

385385
case NETDEV_DOWN:
386+
case NETDEV_UNREGISTER:
386387
return xfrm_dev_down(dev);
387388
}
388389
return NOTIFY_DONE;

net/xfrm/xfrm_policy.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy);
434434

435435
static void xfrm_policy_kill(struct xfrm_policy *policy)
436436
{
437+
write_lock_bh(&policy->lock);
437438
policy->walk.dead = 1;
439+
write_unlock_bh(&policy->lock);
438440

439441
atomic_inc(&policy->genid);
440442

net/xfrm/xfrm_user.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
110110
return 0;
111111

112112
uctx = nla_data(rt);
113-
if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
113+
if (uctx->len > nla_len(rt) ||
114+
uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
114115
return -EINVAL;
115116

116117
return 0;
@@ -2273,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
22732274
xfrm_mark_get(attrs, &mark);
22742275

22752276
err = verify_newpolicy_info(&ua->policy);
2277+
if (err)
2278+
goto free_state;
2279+
err = verify_sec_ctx_len(attrs);
22762280
if (err)
22772281
goto free_state;
22782282

0 commit comments

Comments
 (0)