]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipv6: pass proto by value to ipv6_push_nfrag_opts() and ipv6_push_frag_opts()
authorEric Dumazet <edumazet@google.com>
Fri, 30 Jan 2026 21:02:56 +0000 (21:02 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 3 Feb 2026 01:49:28 +0000 (17:49 -0800)
With CONFIG_STACKPROTECTOR_STRONG=y, it is better to avoid passing
a pointer to an automatic variable.

Change these exported functions to return 'u8 proto'
instead of void.

- ipv6_push_nfrag_opts()
- ipv6_push_frag_opts()

For instance, replace
ipv6_push_frag_opts(skb, opt, &proto);
with:
proto = ipv6_push_frag_opts(skb, opt, proto);

Note that even after this change, ip6_xmit() has to use a stack canary
because of @first_hop variable.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260130210303.3888261-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/ipv6.h
net/ipv6/exthdrs.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c

index cf2203ff2bfd2b42381aba196578cd2668796c8b..a35f0a8114c093c65d3706f53b945cb426bd212b 100644 (file)
@@ -1151,11 +1151,11 @@ int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
  *     Extension header (options) processing
  */
 
-void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
-                         u8 *proto, struct in6_addr **daddr_p,
-                         struct in6_addr *saddr);
-void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
-                        u8 *proto);
+u8 ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
+                       u8 proto, struct in6_addr **daddr_p,
+                       struct in6_addr *saddr);
+u8 ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
+                      u8 proto);
 
 int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp,
                     __be16 *frag_offp);
index cd318ff0dcd8784c3e3841d61d682f2c4a523e61..209fdf1b1aa9b9111f9131a75a6e18e7f9a153fe 100644 (file)
@@ -1074,9 +1074,9 @@ fail_and_free:
  *     for headers.
  */
 
-static void ipv6_push_rthdr0(struct sk_buff *skb, u8 *proto,
-                            struct ipv6_rt_hdr *opt,
-                            struct in6_addr **addr_p, struct in6_addr *saddr)
+static u8 ipv6_push_rthdr0(struct sk_buff *skb, u8 proto,
+                          struct ipv6_rt_hdr *opt,
+                          struct in6_addr **addr_p, struct in6_addr *saddr)
 {
        struct rt0_hdr *phdr, *ihdr;
        int hops;
@@ -1095,13 +1095,13 @@ static void ipv6_push_rthdr0(struct sk_buff *skb, u8 *proto,
        phdr->addr[hops - 1] = **addr_p;
        *addr_p = ihdr->addr;
 
-       phdr->rt_hdr.nexthdr = *proto;
-       *proto = NEXTHDR_ROUTING;
+       phdr->rt_hdr.nexthdr = proto;
+       return NEXTHDR_ROUTING;
 }
 
-static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
-                            struct ipv6_rt_hdr *opt,
-                            struct in6_addr **addr_p, struct in6_addr *saddr)
+static u8 ipv6_push_rthdr4(struct sk_buff *skb, u8 proto,
+                          struct ipv6_rt_hdr *opt,
+                          struct in6_addr **addr_p, struct in6_addr *saddr)
 {
        struct ipv6_sr_hdr *sr_phdr, *sr_ihdr;
        int plen, hops;
@@ -1144,58 +1144,61 @@ static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
        }
 #endif
 
-       sr_phdr->nexthdr = *proto;
-       *proto = NEXTHDR_ROUTING;
+       sr_phdr->nexthdr = proto;
+       return NEXTHDR_ROUTING;
 }
 
-static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
-                           struct ipv6_rt_hdr *opt,
-                           struct in6_addr **addr_p, struct in6_addr *saddr)
+static u8 ipv6_push_rthdr(struct sk_buff *skb, u8 proto,
+                         struct ipv6_rt_hdr *opt,
+                         struct in6_addr **addr_p, struct in6_addr *saddr)
 {
        switch (opt->type) {
        case IPV6_SRCRT_TYPE_0:
        case IPV6_SRCRT_STRICT:
        case IPV6_SRCRT_TYPE_2:
-               ipv6_push_rthdr0(skb, proto, opt, addr_p, saddr);
+               proto = ipv6_push_rthdr0(skb, proto, opt, addr_p, saddr);
                break;
        case IPV6_SRCRT_TYPE_4:
-               ipv6_push_rthdr4(skb, proto, opt, addr_p, saddr);
+               proto = ipv6_push_rthdr4(skb, proto, opt, addr_p, saddr);
                break;
        default:
                break;
        }
+       return proto;
 }
 
-static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
+static u8 ipv6_push_exthdr(struct sk_buff *skb, u8 proto, u8 type, struct ipv6_opt_hdr *opt)
 {
        struct ipv6_opt_hdr *h = skb_push(skb, ipv6_optlen(opt));
 
        memcpy(h, opt, ipv6_optlen(opt));
-       h->nexthdr = *proto;
-       *proto = type;
+       h->nexthdr = proto;
+       return type;
 }
 
-void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
-                         u8 *proto,
-                         struct in6_addr **daddr, struct in6_addr *saddr)
+u8 ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
+                       u8 proto,
+                       struct in6_addr **daddr, struct in6_addr *saddr)
 {
        if (opt->srcrt) {
-               ipv6_push_rthdr(skb, proto, opt->srcrt, daddr, saddr);
+               proto = ipv6_push_rthdr(skb, proto, opt->srcrt, daddr, saddr);
                /*
                 * IPV6_RTHDRDSTOPTS is ignored
                 * unless IPV6_RTHDR is set (RFC3542).
                 */
                if (opt->dst0opt)
-                       ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
+                       proto = ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
        }
        if (opt->hopopt)
-               ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
+               proto = ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
+       return proto;
 }
 
-void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
+u8 ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 proto)
 {
        if (opt->dst1opt)
-               ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
+               proto = ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
+       return proto;
 }
 EXPORT_SYMBOL(ipv6_push_frag_opts);
 
index f904739e99b907a5704c32452ff585479e369727..e4bed95ae5bba173c2418d402cba46e946335219 100644 (file)
@@ -305,11 +305,12 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
                seg_len += opt->opt_nflen + opt->opt_flen;
 
                if (opt->opt_flen)
-                       ipv6_push_frag_opts(skb, opt, &proto);
+                       proto = ipv6_push_frag_opts(skb, opt, proto);
 
                if (opt->opt_nflen)
-                       ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop,
-                                            &fl6->saddr);
+                       proto = ipv6_push_nfrag_opts(skb, opt, proto,
+                                                    &first_hop,
+                                                    &fl6->saddr);
        }
 
        if (unlikely(seg_len > IPV6_MAXPLEN)) {
@@ -1940,11 +1941,13 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
        __skb_pull(skb, skb_network_header_len(skb));
 
        final_dst = &fl6->daddr;
-       if (opt && opt->opt_flen)
-               ipv6_push_frag_opts(skb, opt, &proto);
-       if (opt && opt->opt_nflen)
-               ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst, &fl6->saddr);
-
+       if (opt) {
+               if (opt->opt_flen)
+                       proto = ipv6_push_frag_opts(skb, opt, proto);
+               if (opt->opt_nflen)
+                       proto = ipv6_push_nfrag_opts(skb, opt, proto,
+                                                    &final_dst, &fl6->saddr);
+       }
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        hdr = ipv6_hdr(skb);
index f68f6f110a3e7ea70b9aca4ad1fcfb4d6fe15c38..6fca0868b5a237417eb4c013f713952e8922696d 100644 (file)
@@ -1265,7 +1265,7 @@ route_lookup:
 
        if (encap_limit >= 0) {
                init_tel_txopt(&opt, encap_limit);
-               ipv6_push_frag_opts(skb, &opt.ops, &proto);
+               proto = ipv6_push_frag_opts(skb, &opt.ops, proto);
        }
 
        skb_push(skb, sizeof(struct ipv6hdr));