mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
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>
This commit is contained in:
parent
b6e2db0ed9
commit
a14d931790
1 changed files with 16 additions and 16 deletions
|
|
@ -90,23 +90,24 @@ EXPORT_SYMBOL_GPL(raw_v6_match);
|
|||
* 0 - deliver
|
||||
* 1 - block
|
||||
*/
|
||||
static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
|
||||
static int icmpv6_filter(const struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct icmp6hdr _hdr;
|
||||
const struct icmp6hdr *hdr;
|
||||
const __u32 *data;
|
||||
unsigned int type;
|
||||
|
||||
/* We require only the four bytes of the ICMPv6 header, not any
|
||||
* additional bytes of message body in "struct icmp6hdr".
|
||||
*/
|
||||
hdr = skb_header_pointer(skb, skb_transport_offset(skb),
|
||||
ICMPV6_HDRLEN, &_hdr);
|
||||
if (hdr) {
|
||||
const __u32 *data = &raw6_sk(sk)->filter.data[0];
|
||||
unsigned int type = hdr->icmp6_type;
|
||||
if (!pskb_may_pull(skb, ICMPV6_HDRLEN))
|
||||
return 1;
|
||||
|
||||
return (data[type >> 5] & (1U << (type & 31))) != 0;
|
||||
}
|
||||
return 1;
|
||||
hdr = (struct icmp6hdr *)skb->data;
|
||||
type = hdr->icmp6_type;
|
||||
|
||||
data = &raw6_sk(sk)->filter.data[0];
|
||||
|
||||
return (data[type >> 5] & (1U << (type & 31))) != 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6_MIP6)
|
||||
|
|
@ -141,15 +142,13 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
|
|||
static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
const struct in6_addr *saddr;
|
||||
const struct in6_addr *daddr;
|
||||
const struct ipv6hdr *ip6h;
|
||||
struct hlist_head *hlist;
|
||||
struct sock *sk;
|
||||
bool delivered = false;
|
||||
struct sock *sk;
|
||||
__u8 hash;
|
||||
|
||||
saddr = &ipv6_hdr(skb)->saddr;
|
||||
daddr = saddr + 1;
|
||||
ip6h = ipv6_hdr(skb);
|
||||
|
||||
hash = raw_hashfunc(net, nexthdr);
|
||||
hlist = &raw_v6_hashinfo.ht[hash];
|
||||
|
|
@ -157,7 +156,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
|
|||
sk_for_each_rcu(sk, hlist) {
|
||||
int filtered;
|
||||
|
||||
if (!raw_v6_match(net, sk, nexthdr, daddr, saddr,
|
||||
if (!raw_v6_match(net, sk, nexthdr, &ip6h->daddr, &ip6h->saddr,
|
||||
inet6_iif(skb), inet6_sdif(skb)))
|
||||
continue;
|
||||
|
||||
|
|
@ -171,6 +170,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
|
|||
switch (nexthdr) {
|
||||
case IPPROTO_ICMPV6:
|
||||
filtered = icmpv6_filter(sk, skb);
|
||||
ip6h = ipv6_hdr(skb);
|
||||
break;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6_MIP6)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue