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. ====================
Unified · Split
| @@ -303,6 +303,7 @@ config SYN_COOKIES · 302 unmodified lines | ||
| 303 | 303 | |
| 304 | 304 | config NET_IPVTI |
| 305 | 305 | tristate "Virtual (secure) IP: tunneling" |
| 306 | + depends on IPV6 || IPV6=n | |
| 306 | 307 | select INET_TUNNEL |
| 307 | 308 | select NET_IP_TUNNEL |
| 308 | 309 | select XFRM |
| @@ -187,17 +187,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, · 186 unmodified lines | ||
| 187 | 187 | int mtu; |
| 188 | 188 | |
| 189 | 189 | 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: | |
| 196 | 220 | dev->stats.tx_carrier_errors++; |
| 197 | 221 | goto tx_error_icmp; |
| 198 | 222 | } |
| 199 | − dst = &rt->dst; | |
| 200 | − skb_dst_set(skb, dst); | |
| 201 | 223 | } |
| 202 | 224 | |
| 203 | 225 | dst_hold(dst); |
| @@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb) · 310 unmodified lines | ||
| 311 | 311 | |
| 312 | 312 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| 313 | 313 | rcu_read_unlock(); |
| 314 | − return 0; | |
| 314 | + goto discard; | |
| 315 | 315 | } |
| 316 | 316 | |
| 317 | 317 | ipv6h = ipv6_hdr(skb); |
| @@ -450,15 +450,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) · 132 unmodified lines | ||
| 450 | 450 | int mtu; |
| 451 | 451 | |
| 452 | 452 | 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: | |
| 459 | 478 | goto tx_err_link_failure; |
| 460 | 479 | } |
| 461 | − skb_dst_set(skb, dst); | |
| 462 | 480 | } |
| 463 | 481 | |
| 464 | 482 | dst_hold(dst); |
| @@ -78,7 +78,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const · 77 unmodified lines | ||
| 78 | 78 | |
| 79 | 79 | hlist_for_each_entry_rcu(x6spi, |
| 80 | 80 | &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], |
| 81 | − list_byaddr) { | |
| 81 | + list_byaddr, lockdep_is_held(&xfrm6_tunnel_spi_lock)) { | |
| 82 | 82 | if (xfrm6_addr_equal(&x6spi->addr, saddr)) |
| 83 | 83 | return x6spi; |
| 84 | 84 | } |
| @@ -78,8 +78,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur · 77 unmodified lines | ||
| 78 | 78 | int err; |
| 79 | 79 | unsigned long flags; |
| 80 | 80 | struct xfrm_state *x; |
| 81 | − struct sk_buff *skb2, *nskb; | |
| 82 | 81 | struct softnet_data *sd; |
| 82 | + struct sk_buff *skb2, *nskb, *pskb = NULL; | |
| 83 | 83 | netdev_features_t esp_features = features; |
| 84 | 84 | struct xfrm_offload *xo = xfrm_offload(skb); |
| 85 | 85 | struct sec_path *sp; |
| @@ -168,14 +168,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur · 82 unmodified lines | ||
| 168 | 168 | } else { |
| 169 | 169 | if (skb == skb2) |
| 170 | 170 | skb = nskb; |
| 171 | − | |
| 172 | − if (!skb) | |
| 173 | − return NULL; | |
| 171 | + else | |
| 172 | + pskb->next = nskb; | |
| 174 | 173 | |
| 175 | 174 | continue; |
| 176 | 175 | } |
| 177 | 176 | |
| 178 | 177 | skb_push(skb2, skb2->data - skb_mac_header(skb2)); |
| 178 | + pskb = skb2; | |
| 179 | 179 | } |
| 180 | 180 | |
| 181 | 181 | return skb; |
| @@ -383,6 +383,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void · 201 unmodified lines | ||
| 383 | 383 | return xfrm_dev_feat_change(dev); |
| 384 | 384 | |
| 385 | 385 | case NETDEV_DOWN: |
| 386 | + case NETDEV_UNREGISTER: | |
| 386 | 387 | return xfrm_dev_down(dev); |
| 387 | 388 | } |
| 388 | 389 | return NOTIFY_DONE; |
| @@ -434,7 +434,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy); · 433 unmodified lines | ||
| 434 | 434 | |
| 435 | 435 | static void xfrm_policy_kill(struct xfrm_policy *policy) |
| 436 | 436 | { |
| 437 | + write_lock_bh(&policy->lock); | |
| 437 | 438 | policy->walk.dead = 1; |
| 439 | + write_unlock_bh(&policy->lock); | |
| 438 | 440 | |
| 439 | 441 | atomic_inc(&policy->genid); |
| 440 | 442 | |
| @@ -110,7 +110,8 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs) · 109 unmodified lines | ||
| 110 | 110 | return 0; |
| 111 | 111 | |
| 112 | 112 | 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)) | |
| 114 | 115 | return -EINVAL; |
| 115 | 116 | |
| 116 | 117 | return 0; |
| @@ -2273,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, · 2156 unmodified lines | ||
| 2273 | 2274 | xfrm_mark_get(attrs, &mark); |
| 2274 | 2275 | |
| 2275 | 2276 | err = verify_newpolicy_info(&ua->policy); |
| 2277 | + if (err) | |
| 2278 | + goto free_state; | |
| 2279 | + err = verify_sec_ctx_len(attrs); | |
| 2276 | 2280 | if (err) |
| 2277 | 2281 | goto free_state; |
| 2278 | 2282 | |