diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-27 13:53:43 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-27 13:53:43 -0700 |
| commit | 1b78070aaef63512688aebfbc82365ef9d6660f1 (patch) | |
| tree | 691c0aeaa3d92278ceeb6ace56bc8cd56a7f2ae8 /net/ipv6 | |
| parent | 3ba13f5e7180c034b0a1ef7e052fb780856b134e (diff) | |
| parent | 4a9d62a8774f130a5b8de26ca9f415e6050a9d51 (diff) | |
| download | linux-master.tar.gz linux-master.zip | |
Pull networking fixes from Jakub Kicinski:
"Including fixes from Bluetooth, IPSec and Netfilter.
Current release - fix to a fix:
- netfilter: ipset: remove need to allocate memory on delete operations
Current release - regressions:
- macb: drop CONFIG_OF #if block, fix build
Previous releases - always broken:
- stream of fixes for SCTP continues
- inet: frags: strip GSO state from fragments before reassembly
- virtio-net: ensure that TCP packets don't overflow gso_segs
- tcp-ao: fix use-after-free of current_key on reconnect to another
peer
- page_pool: remove zone/policy GFP flags when allocating XArray
entries
- Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN
- tls: device: fix out-of-bounds write in tls_append_frag()
- eth: bnxt:
- ring the doorbell when SW USO exits early, avoid packets stuck
in Tx
- gate TPH enablement behind BNXT_SUPPORTS_QUEUE_API check, avoid
users of older NICs seeing non-actionable warning messages
- eth: qede: fix NULL pointer dereference in TPA fragment processing"
* tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (216 commits)
inet: frags: strip GSO state from fragments before reassembly
net/sched: sch_htb: limit htb_classify inner-class filter hops
selftests/net: packetdrill: add tcp_urg_ptr_retransmit
tcp: fix corruption of urgent data on multi-segment retransmit
usb: atm: usbatm: fix invalid ci_range initialization
net: fec: only stop PTP if it was initialized
slip: remove slip_hangup() to fix use-after-free in slip_receive_buf()
net: bridge: mcast: fix use-after-free of a master VLAN's multicast context
net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup
net: dsa: mxl862xx: enable assisted learning on CPU port
net: stmmac: restore NET_IP_ALIGN in the RX DMA offset
net: stmmac: drop gso_enabled_types and rely on netdev features
net: stmmac: selftests: Don't test flow control for small rx fifos
net: stmmac: selftests: Account for the UC filter list for filtering tests
net: stmmac: dwxgmac: Account for the primary MAC address for UC filtering
net: stmmac: dwmac4: Account for the primary MAC address for UC filtering
net: stmmac: dwmac1000: Account for the primary MAC address for UC filtering
net: stmmac: selftests: Check multiple MMC counters
selftests: net: Fix slow configurations in big_tcp_tunnels.sh
selftests: net: Lower threshold with csum offload off in big_tcp_tunnels.sh
...
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/ah6.c | 29 | ||||
| -rw-r--r-- | net/ipv6/exthdrs.c | 26 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 3 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_ah.c | 27 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_frag.c | 41 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_hbh.c | 40 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_mh.c | 3 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_rt.c | 6 | ||||
| -rw-r--r-- | net/ipv6/netfilter/nf_tproxy_ipv6.c | 2 | ||||
| -rw-r--r-- | net/ipv6/route.c | 6 | ||||
| -rw-r--r-- | net/ipv6/seg6_local.c | 16 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_input.c | 2 |
13 files changed, 70 insertions, 133 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 76f7a2de9108..c96f7e0d0a48 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -232,26 +232,28 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des * Rearrange the destination address in @iph and the addresses in @rthdr * so that they appear in the order they will at the final destination. * See Appendix A2 of RFC 2402 for details. + * + * Return: 0 on success, -EINVAL if segments_left exceeds the number of + * addresses described by hdrlen. */ -static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) +static int ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) { - int segments, segments_left; + unsigned int segments, segments_left; struct in6_addr *addrs; struct in6_addr final_addr; segments_left = rthdr->segments_left; if (segments_left == 0) - return; - rthdr->segments_left = 0; + return 0; - /* The value of rthdr->hdrlen has been verified either by the system - * call if it is locally generated, or by ipv6_rthdr_rcv() for incoming - * packets. So we can assume that it is even and that segments is - * greater than or equal to segments_left. - * - * For the same reason we can assume that this option is of type 0. + /* Raw locally generated packets can reach AH6 without the invariant + * required by the rt0-style address rearrangement below. */ segments = rthdr->hdrlen >> 1; + if (segments_left > segments) + return -EINVAL; + + rthdr->segments_left = 0; addrs = ((struct rt0_hdr *)rthdr)->addr; final_addr = addrs[segments - 1]; @@ -261,6 +263,8 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) addrs[0] = iph->daddr; iph->daddr = final_addr; + + return 0; } static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) @@ -273,6 +277,7 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) } exthdr = { .iph = iph }; char *end = exthdr.raw + len; int nexthdr = iph->nexthdr; + int err; exthdr.iph++; @@ -292,7 +297,9 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) break; case NEXTHDR_ROUTING: - ipv6_rearrange_rthdr(iph, exthdr.rth); + err = ipv6_rearrange_rthdr(iph, exthdr.rth); + if (err) + return err; break; default: diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 9c677eb1d1a6..51941ad656a3 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -368,23 +368,16 @@ static void seg6_update_csum(struct sk_buff *skb) (__be32 *)addr); } -static int ipv6_srh_rcv(struct sk_buff *skb) +static int ipv6_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev) { struct inet6_skb_parm *opt = IP6CB(skb); struct net *net = dev_net(skb->dev); struct ipv6_sr_hdr *hdr; - struct inet6_dev *idev; struct in6_addr *addr; int accept_seg6; hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); - idev = __in6_dev_get(skb->dev); - if (!idev) { - kfree_skb(skb); - return -1; - } - accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), READ_ONCE(idev->cnf.seg6_enabled)); @@ -485,12 +478,11 @@ looped_back: return -1; } -static int ipv6_rpl_srh_rcv(struct sk_buff *skb) +static int ipv6_rpl_srh_rcv(struct sk_buff *skb, struct inet6_dev *idev) { struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr; struct inet6_skb_parm *opt = IP6CB(skb); struct net *net = dev_net(skb->dev); - struct inet6_dev *idev; struct ipv6hdr *oldhdr; unsigned int chdr_len; unsigned char *buf; @@ -499,8 +491,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb) u64 n = 0; u32 r; - idev = __in6_dev_get(skb->dev); - accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled), READ_ONCE(idev->cnf.rpl_seg_enabled)); if (!accept_rpl_seg) { @@ -689,10 +679,14 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) switch (hdr->type) { case IPV6_SRCRT_TYPE_4: /* segment routing */ - return ipv6_srh_rcv(skb); + if (!idev) + goto disabled; + return ipv6_srh_rcv(skb, idev); case IPV6_SRCRT_TYPE_3: /* rpl segment routing */ - return ipv6_rpl_srh_rcv(skb); + if (!idev) + goto disabled; + return ipv6_rpl_srh_rcv(skb, idev); default: break; } @@ -837,6 +831,10 @@ unknown_rh: icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb_network_header(skb)); return -1; + +disabled: + kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED); + return -1; } static const struct inet6_protocol rthdr_protocol = { diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 604a58838901..3f2ed9b77deb 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1162,10 +1162,10 @@ static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt, msg->im6_src = ipv6_hdr(pkt)->saddr; msg->im6_dst = ipv6_hdr(pkt)->daddr; - skb_dst_set(skb, dst_clone(skb_dst(pkt))); skb->ip_summed = CHECKSUM_UNNECESSARY; } + skb_dst_drop(skb); mrt6msg_netlink_event(mrt, skb); /* Deliver to user space multicast routing algorithms */ @@ -1246,6 +1246,7 @@ static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, skb->skb_iif = dev->ifindex; } + skb_dst_drop(skb); skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb); spin_unlock_bh(&mfc_unres_lock); diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index 1258783ed876..dab7dbc6a675 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -24,13 +24,7 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); static inline bool spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) { - bool r; - - pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", - invert ? '!' : ' ', min, spi, max); - r = (spi >= min && spi <= max) ^ invert; - pr_debug(" result %s\n", r ? "PASS" : "FAILED"); - return r; + return (spi >= min && spi <= max) ^ invert; } static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par) @@ -62,23 +56,6 @@ static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par) return false; } - pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); - pr_debug("RES %04X ", ah->reserved); - pr_debug("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi)); - - pr_debug("IPv6 AH spi %02X ", - spi_match(ahinfo->spis[0], ahinfo->spis[1], - ntohl(ah->spi), - !!(ahinfo->invflags & IP6T_AH_INV_SPI))); - pr_debug("len %02X %04X %02X ", - ahinfo->hdrlen, hdrlen, - (!ahinfo->hdrlen || - (ahinfo->hdrlen == hdrlen) ^ - !!(ahinfo->invflags & IP6T_AH_INV_LEN))); - pr_debug("res %02X %04X %02X\n", - ahinfo->hdrres, ah->reserved, - !(ahinfo->hdrres && ah->reserved)); - return spi_match(ahinfo->spis[0], ahinfo->spis[1], ntohl(ah->spi), !!(ahinfo->invflags & IP6T_AH_INV_SPI)) && @@ -93,7 +70,7 @@ static int ah_mt6_check(const struct xt_mtchk_param *par) const struct ip6t_ah *ahinfo = par->matchinfo; if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { - pr_debug("unknown flags %X\n", ahinfo->invflags); + pr_info_ratelimited("unknown flags %X\n", ahinfo->invflags); return -EINVAL; } return 0; diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 3aad6439386b..f5f3cfb8704c 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -23,12 +23,7 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); static inline bool id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) { - bool r; - pr_debug("id_match:%c 0x%x <= 0x%x <= 0x%x\n", invert ? '!' : ' ', - min, id, max); - r = (id >= min && id <= max) ^ invert; - pr_debug(" result %s\n", r ? "PASS" : "FAILED"); - return r; + return (id >= min && id <= max) ^ invert; } static bool @@ -53,38 +48,6 @@ frag_mt6(const struct sk_buff *skb, struct xt_action_param *par) return false; } - pr_debug("INFO %04X ", fh->frag_off); - pr_debug("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); - pr_debug("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); - pr_debug("MF %04X ", fh->frag_off & htons(IP6_MF)); - pr_debug("ID %u %08X\n", ntohl(fh->identification), - ntohl(fh->identification)); - - pr_debug("IPv6 FRAG id %02X ", - id_match(fraginfo->ids[0], fraginfo->ids[1], - ntohl(fh->identification), - !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))); - pr_debug("res %02X %02X%04X %02X ", - fraginfo->flags & IP6T_FRAG_RES, fh->reserved, - ntohs(fh->frag_off) & 0x6, - !((fraginfo->flags & IP6T_FRAG_RES) && - (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); - pr_debug("first %02X %02X %02X ", - fraginfo->flags & IP6T_FRAG_FST, - ntohs(fh->frag_off) & ~0x7, - !((fraginfo->flags & IP6T_FRAG_FST) && - (ntohs(fh->frag_off) & ~0x7))); - pr_debug("mf %02X %02X %02X ", - fraginfo->flags & IP6T_FRAG_MF, - ntohs(fh->frag_off) & IP6_MF, - !((fraginfo->flags & IP6T_FRAG_MF) && - !((ntohs(fh->frag_off) & IP6_MF)))); - pr_debug("last %02X %02X %02X\n", - fraginfo->flags & IP6T_FRAG_NMF, - ntohs(fh->frag_off) & IP6_MF, - !((fraginfo->flags & IP6T_FRAG_NMF) && - (ntohs(fh->frag_off) & IP6_MF))); - return id_match(fraginfo->ids[0], fraginfo->ids[1], ntohl(fh->identification), !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)) && @@ -103,7 +66,7 @@ static int frag_mt6_check(const struct xt_mtchk_param *par) const struct ip6t_frag *fraginfo = par->matchinfo; if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { - pr_debug("unknown flags %X\n", fraginfo->invflags); + pr_info_ratelimited("unknown flags %X\n", fraginfo->invflags); return -EINVAL; } return 0; diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 6d1a5d2026a6..6008dcff8488 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -79,14 +79,6 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par) return false; } - pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); - - pr_debug("len %02X %04X %02X ", - optinfo->hdrlen, hdrlen, - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); - ret = (!(optinfo->flags & IP6T_OPTS_LEN) || ((optinfo->hdrlen == hdrlen) ^ !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); @@ -96,8 +88,6 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par) if (!(optinfo->flags & IP6T_OPTS_OPTS)) { return ret; } else { - pr_debug("Strict "); - pr_debug("#%d ", optinfo->optsnr); for (temp = 0; temp < optinfo->optsnr; temp++) { /* type field exists ? */ if (hdrlen < 1) @@ -108,13 +98,9 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par) break; /* Type check */ - if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { - pr_debug("Tbad %02X %02X\n", *tp, - (optinfo->opts[temp] & 0xFF00) >> 8); + if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) return false; - } else { - pr_debug("Tok "); - } + /* Length check */ if (*tp) { u16 spec_len; @@ -129,26 +115,18 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par) break; spec_len = optinfo->opts[temp] & 0x00FF; - if (spec_len != 0x00FF && spec_len != *lp) { - pr_debug("Lbad %02X %04X\n", *lp, - spec_len); + if (spec_len != 0x00FF && spec_len != *lp) return false; - } - pr_debug("Lok "); + optlen = *lp + 2; } else { - pr_debug("Pad1\n"); optlen = 1; } - /* Step to the next */ - pr_debug("len%04X\n", optlen); - if ((ptr > skb->len - optlen || hdrlen < optlen) && - temp < optinfo->optsnr - 1) { - pr_debug("new pointer is too large!\n"); + temp < optinfo->optsnr - 1) break; - } + ptr += optlen; hdrlen -= optlen; } @@ -166,16 +144,16 @@ static int hbh_mt6_check(const struct xt_mtchk_param *par) const struct ip6t_opts *optsinfo = par->matchinfo; if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { - pr_debug("unknown flags %X\n", optsinfo->invflags); + pr_info_ratelimited("unknown flags %X\n", optsinfo->invflags); return -EINVAL; } if (optsinfo->optsnr > IP6T_OPTS_OPTSNR) { - pr_debug("too many supported opts specified\n"); + pr_info_ratelimited("too many supported opts specified\n"); return -EINVAL; } if (optsinfo->flags & IP6T_OPTS_NSTRICT) { - pr_debug("Not strict - not implemented"); + pr_info_ratelimited("Not strict - not implemented\n"); return -EINVAL; } diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c index fd492b69acbc..ba6dcc7791a0 100644 --- a/net/ipv6/netfilter/ip6t_mh.c +++ b/net/ipv6/netfilter/ip6t_mh.c @@ -42,14 +42,11 @@ static bool mh_mt6(const struct sk_buff *skb, struct xt_action_param *par) if (mh == NULL) { /* We've been asked to examine this packet, and we can't. Hence, no choice but to drop. */ - pr_debug("Dropping evil MH tinygram.\n"); par->hotdrop = true; return false; } if (mh->ip6mh_proto != IPPROTO_NONE) { - pr_debug("Dropping invalid MH Payload Proto: %u\n", - mh->ip6mh_proto); par->hotdrop = true; return false; } diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 278b52752f36..8051425213dd 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -155,18 +155,18 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) const struct ip6t_rt *rtinfo = par->matchinfo; if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { - pr_debug("unknown flags %X\n", rtinfo->invflags); + pr_info_ratelimited("unknown flags %X\n", rtinfo->invflags); return -EINVAL; } if (rtinfo->addrnr > IP6T_RT_HOPS) { - pr_debug("too many addresses specified\n"); + pr_info_ratelimited("too many addresses specified\n"); return -EINVAL; } if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && (!(rtinfo->flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP))) { - pr_debug("`--rt-type 0' required before `--rt-0-*'"); + pr_info_ratelimited("`--rt-type 0' required before `--rt-0-*'\n"); return -EINVAL; } diff --git a/net/ipv6/netfilter/nf_tproxy_ipv6.c b/net/ipv6/netfilter/nf_tproxy_ipv6.c index b2f59ed9d7cc..12ec36a6be2e 100644 --- a/net/ipv6/netfilter/nf_tproxy_ipv6.c +++ b/net/ipv6/netfilter/nf_tproxy_ipv6.c @@ -136,7 +136,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, } break; default: - WARN_ON(1); + DEBUG_NET_WARN_ON_ONCE(1); sk = NULL; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 16dfac54a259..6a40c5074543 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3261,7 +3261,7 @@ void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) static unsigned int ip6_default_advmss(const struct dst_entry *dst) { - unsigned int mtu = dst6_mtu(dst); + unsigned int mtu = ip6_dst_mtu_configured(dst); struct net *net; mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); @@ -4852,7 +4852,7 @@ static void rt6_upper_bound_set(struct fib6_info *rt, int *weight, int total) { int upper_bound = -1; - if (!rt6_is_dead(rt)) { + if (total && !rt6_is_dead(rt)) { *weight += rt->fib6_nh->fib_nh_weight; upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31, total) - 1; @@ -6046,7 +6046,7 @@ static int rt6_nh_dump_exceptions(struct fib6_nh *nh, void *arg) return 0; for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) { - hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { + hlist_for_each_entry_rcu(rt6_ex, &bucket->chain, hlist) { if (w->skip) { w->skip--; continue; diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c index 2b41e4c0dddd..7b5212220185 100644 --- a/net/ipv6/seg6_local.c +++ b/net/ipv6/seg6_local.c @@ -256,6 +256,22 @@ static bool decap_and_validate(struct sk_buff *skb, int proto) if (iptunnel_pull_offloads(skb)) return false; + if (proto == IPPROTO_IPIP) { + int iif = IP6CB(skb)->iif; + + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + IPCB(skb)->iif = iif; + } else if (proto == IPPROTO_IPV6) { + bool l3slave = ipv6_l3mdev_skb(IP6CB(skb)->flags); + int iif = IP6CB(skb)->iif; + + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + IP6CB(skb)->iif = iif; + IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); + if (l3slave) + IP6CB(skb)->flags |= IP6SKB_L3SLAVE; + } + return true; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9e9155b1b3aa..df9c29eb5c1f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1487,7 +1487,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * tcp_ca_openreq_child(newsk, dst); tcp_sync_mss(newsk, dst6_mtu(dst)); - newtp->advmss = tcp_mss_clamp(tcp_sk(sk), dst_metric_advmss(dst)); + newtp->advmss = tcp_mss_clamp(tcp_sk(sk), tcp_dst_advmss(dst)); tcp_initialize_rcv_mss(newsk); diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 89d0443b5307..07edef258984 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -247,7 +247,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, goto drop; } - if (1 + sp->len == XFRM_MAX_DEPTH) { + if (sp->len >= XFRM_MAX_DEPTH) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); goto drop; } |
