Skip to content

Commit a14d931

Browse files
edumazetkuba-moo
authored andcommitted
ipv6: do not use skb_header_pointer() in icmpv6_filter()
Prefer pskb_may_pull() to avoid a stack canary in raw6_local_deliver(). Note: skb->head can change, hence we reload ip6h pointer in ipv6_raw_deliver() $ scripts/bloat-o-meter -t vmlinux.old vmlinux.new add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-86 (-86) Function old new delta raw6_local_deliver 780 694 -86 Total: Before=24889784, After=24889698, chg -0.00% Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260205211909.4115285-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent b6e2db0 commit a14d931

1 file changed

Lines changed: 16 additions & 16 deletions

File tree

net/ipv6/raw.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,23 +90,24 @@ EXPORT_SYMBOL_GPL(raw_v6_match);
9090
* 0 - deliver
9191
* 1 - block
9292
*/
93-
static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
93+
static int icmpv6_filter(const struct sock *sk, struct sk_buff *skb)
9494
{
95-
struct icmp6hdr _hdr;
9695
const struct icmp6hdr *hdr;
96+
const __u32 *data;
97+
unsigned int type;
9798

9899
/* We require only the four bytes of the ICMPv6 header, not any
99100
* additional bytes of message body in "struct icmp6hdr".
100101
*/
101-
hdr = skb_header_pointer(skb, skb_transport_offset(skb),
102-
ICMPV6_HDRLEN, &_hdr);
103-
if (hdr) {
104-
const __u32 *data = &raw6_sk(sk)->filter.data[0];
105-
unsigned int type = hdr->icmp6_type;
102+
if (!pskb_may_pull(skb, ICMPV6_HDRLEN))
103+
return 1;
106104

107-
return (data[type >> 5] & (1U << (type & 31))) != 0;
108-
}
109-
return 1;
105+
hdr = (struct icmp6hdr *)skb->data;
106+
type = hdr->icmp6_type;
107+
108+
data = &raw6_sk(sk)->filter.data[0];
109+
110+
return (data[type >> 5] & (1U << (type & 31))) != 0;
110111
}
111112

112113
#if IS_ENABLED(CONFIG_IPV6_MIP6)
@@ -141,23 +142,21 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
141142
static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
142143
{
143144
struct net *net = dev_net(skb->dev);
144-
const struct in6_addr *saddr;
145-
const struct in6_addr *daddr;
145+
const struct ipv6hdr *ip6h;
146146
struct hlist_head *hlist;
147-
struct sock *sk;
148147
bool delivered = false;
148+
struct sock *sk;
149149
__u8 hash;
150150

151-
saddr = &ipv6_hdr(skb)->saddr;
152-
daddr = saddr + 1;
151+
ip6h = ipv6_hdr(skb);
153152

154153
hash = raw_hashfunc(net, nexthdr);
155154
hlist = &raw_v6_hashinfo.ht[hash];
156155
rcu_read_lock();
157156
sk_for_each_rcu(sk, hlist) {
158157
int filtered;
159158

160-
if (!raw_v6_match(net, sk, nexthdr, daddr, saddr,
159+
if (!raw_v6_match(net, sk, nexthdr, &ip6h->daddr, &ip6h->saddr,
161160
inet6_iif(skb), inet6_sdif(skb)))
162161
continue;
163162

@@ -171,6 +170,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
171170
switch (nexthdr) {
172171
case IPPROTO_ICMPV6:
173172
filtered = icmpv6_filter(sk, skb);
173+
ip6h = ipv6_hdr(skb);
174174
break;
175175

176176
#if IS_ENABLED(CONFIG_IPV6_MIP6)

0 commit comments

Comments
 (0)