mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
ipv6: pass proto by value to ipv6_push_nfrag_opts() and ipv6_push_frag_opts()
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>
This commit is contained in:
parent
e022155343
commit
1bc46dd209
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1074,9 +1074,9 @@ int ipv6_parse_hopopts(struct sk_buff *skb)
|
|||
* 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1265,7 +1265,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
|
|||
|
||||
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));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user