mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
3f649ab728
Using uninitialized_var() is dangerous as it papers over real bugs[1] (or can in the future), and suppresses unrelated compiler warnings (e.g. "unused variable"). If the compiler thinks it is uninitialized, either simply initialize the variable or make compiler changes. In preparation for removing[2] the[3] macro[4], remove all remaining needless uses with the following script: git grep '\buninitialized_var\b' | cut -d: -f1 | sort -u | \ xargs perl -pi -e \ 's/\buninitialized_var\(([^\)]+)\)/\1/g; s:\s*/\* (GCC be quiet|to make compiler happy) \*/$::g;' drivers/video/fbdev/riva/riva_hw.c was manually tweaked to avoid pathological white-space. No outstanding warnings were found building allmodconfig with GCC 9.3.0 for x86_64, i386, arm64, arm, powerpc, powerpc64le, s390x, mips, sparc64, alpha, and m68k. [1] https://lore.kernel.org/lkml/20200603174714.192027-1-glider@google.com/ [2] https://lore.kernel.org/lkml/CA+55aFw+Vbj0i=1TGqCR5vQkCzWJ0QxK6CernOU6eedsudAixw@mail.gmail.com/ [3] https://lore.kernel.org/lkml/CA+55aFwgbgqhbp1fkxvRKEpzyR5J8n1vKT1VZdz9knmPuXhOeg@mail.gmail.com/ [4] https://lore.kernel.org/lkml/CA+55aFz2500WfbKXAx8s67wrm9=yVJu65TpLgN_ybYNv0VEOKA@mail.gmail.com/ Reviewed-by: Leon Romanovsky <leonro@mellanox.com> # drivers/infiniband and mlx4/mlx5 Acked-by: Jason Gunthorpe <jgg@mellanox.com> # IB Acked-by: Kalle Valo <kvalo@codeaurora.org> # wireless drivers Reviewed-by: Chao Yu <yuchao0@huawei.com> # erofs Signed-off-by: Kees Cook <keescook@chromium.org>
153 lines
4.1 KiB
C
153 lines
4.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (C) 2007-2008 BalaBit IT Ltd.
|
|
* Author: Krisztian Kovacs
|
|
*/
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
#include <linux/module.h>
|
|
#include <linux/skbuff.h>
|
|
#include <net/tcp.h>
|
|
#include <net/udp.h>
|
|
#include <net/icmp.h>
|
|
#include <net/sock.h>
|
|
#include <net/inet_sock.h>
|
|
#include <net/netfilter/nf_socket.h>
|
|
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
|
#include <net/netfilter/nf_conntrack.h>
|
|
#endif
|
|
|
|
static int
|
|
extract_icmp4_fields(const struct sk_buff *skb, u8 *protocol,
|
|
__be32 *raddr, __be32 *laddr,
|
|
__be16 *rport, __be16 *lport)
|
|
{
|
|
unsigned int outside_hdrlen = ip_hdrlen(skb);
|
|
struct iphdr *inside_iph, _inside_iph;
|
|
struct icmphdr *icmph, _icmph;
|
|
__be16 *ports, _ports[2];
|
|
|
|
icmph = skb_header_pointer(skb, outside_hdrlen,
|
|
sizeof(_icmph), &_icmph);
|
|
if (icmph == NULL)
|
|
return 1;
|
|
|
|
if (!icmp_is_err(icmph->type))
|
|
return 1;
|
|
|
|
inside_iph = skb_header_pointer(skb, outside_hdrlen +
|
|
sizeof(struct icmphdr),
|
|
sizeof(_inside_iph), &_inside_iph);
|
|
if (inside_iph == NULL)
|
|
return 1;
|
|
|
|
if (inside_iph->protocol != IPPROTO_TCP &&
|
|
inside_iph->protocol != IPPROTO_UDP)
|
|
return 1;
|
|
|
|
ports = skb_header_pointer(skb, outside_hdrlen +
|
|
sizeof(struct icmphdr) +
|
|
(inside_iph->ihl << 2),
|
|
sizeof(_ports), &_ports);
|
|
if (ports == NULL)
|
|
return 1;
|
|
|
|
/* the inside IP packet is the one quoted from our side, thus
|
|
* its saddr is the local address */
|
|
*protocol = inside_iph->protocol;
|
|
*laddr = inside_iph->saddr;
|
|
*lport = ports[0];
|
|
*raddr = inside_iph->daddr;
|
|
*rport = ports[1];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct sock *
|
|
nf_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff,
|
|
const u8 protocol,
|
|
const __be32 saddr, const __be32 daddr,
|
|
const __be16 sport, const __be16 dport,
|
|
const struct net_device *in)
|
|
{
|
|
switch (protocol) {
|
|
case IPPROTO_TCP:
|
|
return inet_lookup(net, &tcp_hashinfo, skb, doff,
|
|
saddr, sport, daddr, dport,
|
|
in->ifindex);
|
|
case IPPROTO_UDP:
|
|
return udp4_lib_lookup(net, saddr, sport, daddr, dport,
|
|
in->ifindex);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb,
|
|
const struct net_device *indev)
|
|
{
|
|
__be32 daddr, saddr;
|
|
__be16 dport, sport;
|
|
const struct iphdr *iph = ip_hdr(skb);
|
|
struct sk_buff *data_skb = NULL;
|
|
u8 protocol;
|
|
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
|
enum ip_conntrack_info ctinfo;
|
|
struct nf_conn const *ct;
|
|
#endif
|
|
int doff = 0;
|
|
|
|
if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
|
|
struct tcphdr _hdr;
|
|
struct udphdr *hp;
|
|
|
|
hp = skb_header_pointer(skb, ip_hdrlen(skb),
|
|
iph->protocol == IPPROTO_UDP ?
|
|
sizeof(*hp) : sizeof(_hdr), &_hdr);
|
|
if (hp == NULL)
|
|
return NULL;
|
|
|
|
protocol = iph->protocol;
|
|
saddr = iph->saddr;
|
|
sport = hp->source;
|
|
daddr = iph->daddr;
|
|
dport = hp->dest;
|
|
data_skb = (struct sk_buff *)skb;
|
|
doff = iph->protocol == IPPROTO_TCP ?
|
|
ip_hdrlen(skb) + __tcp_hdrlen((struct tcphdr *)hp) :
|
|
ip_hdrlen(skb) + sizeof(*hp);
|
|
|
|
} else if (iph->protocol == IPPROTO_ICMP) {
|
|
if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
|
|
&sport, &dport))
|
|
return NULL;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
|
/* Do the lookup with the original socket address in
|
|
* case this is a reply packet of an established
|
|
* SNAT-ted connection.
|
|
*/
|
|
ct = nf_ct_get(skb, &ctinfo);
|
|
if (ct &&
|
|
((iph->protocol != IPPROTO_ICMP &&
|
|
ctinfo == IP_CT_ESTABLISHED_REPLY) ||
|
|
(iph->protocol == IPPROTO_ICMP &&
|
|
ctinfo == IP_CT_RELATED_REPLY)) &&
|
|
(ct->status & IPS_SRC_NAT_DONE)) {
|
|
|
|
daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
|
dport = (iph->protocol == IPPROTO_TCP) ?
|
|
ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
|
|
ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
|
|
}
|
|
#endif
|
|
|
|
return nf_socket_get_sock_v4(net, data_skb, doff, protocol, saddr,
|
|
daddr, sport, dport, indev);
|
|
}
|
|
EXPORT_SYMBOL_GPL(nf_sk_lookup_slow_v4);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
|
|
MODULE_DESCRIPTION("Netfilter IPv4 socket lookup infrastructure");
|