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 | config NET_IPVTI | 304 | config NET_IPVTI |
| 305 | tristate "Virtual (secure) IP: tunneling" | 305 | tristate "Virtual (secure) IP: tunneling" |
| 306 | depends on IPV6 || IPV6=n | ||
| 306 | select INET_TUNNEL | 307 | select INET_TUNNEL |
| 307 | select NET_IP_TUNNEL | 308 | select NET_IP_TUNNEL |
| 308 | select XFRM | 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 | int mtu; | 187 | int mtu; |
| 188 | 188 | ||
| 189 | if (!dst) { | 189 | if (!dst) { |
| 190 | struct rtable *rt; | 190 | switch (skb->protocol) { |
| 191 | 191 | case htons(ETH_P_IP): { | |
| 192 | fl->u.ip4.flowi4_oif = dev->ifindex; | 192 | struct rtable *rt; |
| 193 | fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; | 193 | |
| 194 | rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); | 194 | fl->u.ip4.flowi4_oif = dev->ifindex; |
| 195 | if (IS_ERR(rt)) { | 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 | dev->stats.tx_carrier_errors++; | 220 | dev->stats.tx_carrier_errors++; |
| 197 | goto tx_error_icmp; | 221 | goto tx_error_icmp; |
| 198 | } | 222 | } |
| 199 | dst = &rt->dst; | ||
| 200 | skb_dst_set(skb, dst); | ||
| 201 | } | 223 | } |
| 202 | 224 | ||
| 203 | dst_hold(dst); | 225 | dst_hold(dst); |
| @@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb) · 310 unmodified lines | |||
| 311 | 311 | ||
| 312 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 312 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| 313 | rcu_read_unlock(); | 313 | rcu_read_unlock(); |
| 314 | return 0; | 314 | goto discard; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | ipv6h = ipv6_hdr(skb); | 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 | int mtu; | 450 | int mtu; |
| 451 | 451 | ||
| 452 | if (!dst) { | 452 | if (!dst) { |
| 453 | fl->u.ip6.flowi6_oif = dev->ifindex; | 453 | switch (skb->protocol) { |
| 454 | fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; | 454 | case htons(ETH_P_IP): { |
| 455 | dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); | 455 | struct rtable *rt; |
| 456 | if (dst->error) { | 456 | |
| 457 | dst_release(dst); | 457 | fl->u.ip4.flowi4_oif = dev->ifindex; |
| 458 | dst = NULL; | 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 | goto tx_err_link_failure; | 478 | goto tx_err_link_failure; |
| 460 | } | 479 | } |
| 461 | skb_dst_set(skb, dst); | ||
| 462 | } | 480 | } |
| 463 | 481 | ||
| 464 | dst_hold(dst); | 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 | hlist_for_each_entry_rcu(x6spi, | 79 | hlist_for_each_entry_rcu(x6spi, |
| 80 | &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], | 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 | if (xfrm6_addr_equal(&x6spi->addr, saddr)) | 82 | if (xfrm6_addr_equal(&x6spi->addr, saddr)) |
| 83 | return x6spi; | 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 | int err; | 78 | int err; |
| 79 | unsigned long flags; | 79 | unsigned long flags; |
| 80 | struct xfrm_state *x; | 80 | struct xfrm_state *x; |
| 81 | struct sk_buff *skb2, *nskb; | ||
| 82 | struct softnet_data *sd; | 81 | struct softnet_data *sd; |
| 82 | struct sk_buff *skb2, *nskb, *pskb = NULL; | ||
| 83 | netdev_features_t esp_features = features; | 83 | netdev_features_t esp_features = features; |
| 84 | struct xfrm_offload *xo = xfrm_offload(skb); | 84 | struct xfrm_offload *xo = xfrm_offload(skb); |
| 85 | struct sec_path *sp; | 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 | } else { | 168 | } else { |
| 169 | if (skb == skb2) | 169 | if (skb == skb2) |
| 170 | skb = nskb; | 170 | skb = nskb; |
| 171 | 171 | else | |
| 172 | if (!skb) | 172 | pskb->next = nskb; |
| 173 | return NULL; | ||
| 174 | 173 | ||
| 175 | continue; | 174 | continue; |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | skb_push(skb2, skb2->data - skb_mac_header(skb2)); | 177 | skb_push(skb2, skb2->data - skb_mac_header(skb2)); |
| 178 | pskb = skb2; | ||
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | return skb; | 181 | return skb; |
| @@ -383,6 +383,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void · 201 unmodified lines | |||
| 383 | return xfrm_dev_feat_change(dev); | 383 | return xfrm_dev_feat_change(dev); |
| 384 | 384 | ||
| 385 | case NETDEV_DOWN: | 385 | case NETDEV_DOWN: |
| 386 | case NETDEV_UNREGISTER: | ||
| 386 | return xfrm_dev_down(dev); | 387 | return xfrm_dev_down(dev); |
| 387 | } | 388 | } |
| 388 | return NOTIFY_DONE; | 389 | return NOTIFY_DONE; |
| @@ -434,7 +434,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy); · 433 unmodified lines | |||
| 434 | 434 | ||
| 435 | static void xfrm_policy_kill(struct xfrm_policy *policy) | 435 | static void xfrm_policy_kill(struct xfrm_policy *policy) |
| 436 | { | 436 | { |
| 437 | write_lock_bh(&policy->lock); | ||
| 437 | policy->walk.dead = 1; | 438 | policy->walk.dead = 1; |
| 439 | write_unlock_bh(&policy->lock); | ||
| 438 | 440 | ||
| 439 | atomic_inc(&policy->genid); | 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 | return 0; | 110 | return 0; |
| 111 | 111 | ||
| 112 | uctx = nla_data(rt); | 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 | return -EINVAL; | 115 | return -EINVAL; |
| 115 | 116 | ||
| 116 | return 0; | 117 | return 0; |
| @@ -2273,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, · 2156 unmodified lines | |||
| 2273 | xfrm_mark_get(attrs, &mark); | 2274 | xfrm_mark_get(attrs, &mark); |
| 2274 | 2275 | ||
| 2275 | err = verify_newpolicy_info(&ua->policy); | 2276 | err = verify_newpolicy_info(&ua->policy); |
| 2277 | if (err) | ||
| 2278 | goto free_state; | ||
| 2279 | err = verify_sec_ctx_len(attrs); | ||
| 2276 | if (err) | 2280 | if (err) |
| 2277 | goto free_state; | 2281 | goto free_state; |
| 2278 | 2282 | ||