Merge branch 'ipv6-kfree_skb_reason'
Menglong Dong says: ==================== net: use kfree_skb_reason() for ip/udp packet receive In this series patches, kfree_skb() is replaced with kfree_skb_reason() during ipv4 and udp4 packet receiving path, and following drop reasons are introduced: SKB_DROP_REASON_SOCKET_FILTER SKB_DROP_REASON_NETFILTER_DROP SKB_DROP_REASON_OTHERHOST SKB_DROP_REASON_IP_CSUM SKB_DROP_REASON_IP_INHDR SKB_DROP_REASON_IP_RPFILTER SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST SKB_DROP_REASON_XFRM_POLICY SKB_DROP_REASON_IP_NOPROTO SKB_DROP_REASON_SOCKET_RCVBUFF SKB_DROP_REASON_PROTO_MEM TCP is more complex, so I left it in the next series. I just figure out how __print_symbolic() works. It doesn't base on the array index, but searching for symbols by loop. So I'm a little afraid it's performance. Changes since v3: - fix some small problems in the third patch (net: ipv4: use kfree_skb_reason() in ip_rcv_core()), as David Ahern said Changes since v2: - use SKB_DROP_REASON_PKT_TOO_SMALL for a path in ip_rcv_core() Changes since v1: - add document for all drop reasons, as David advised - remove unreleated cleanup - remove EARLY_DEMUX and IP_ROUTE_INPUT drop reason - replace {UDP, TCP}_FILTER with SOCKET_FILTER ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
47c1a9a4ea
|
@ -314,12 +314,38 @@ struct sk_buff;
|
|||
* used to translate the reason to string.
|
||||
*/
|
||||
enum skb_drop_reason {
|
||||
SKB_DROP_REASON_NOT_SPECIFIED,
|
||||
SKB_DROP_REASON_NO_SOCKET,
|
||||
SKB_DROP_REASON_PKT_TOO_SMALL,
|
||||
SKB_DROP_REASON_TCP_CSUM,
|
||||
SKB_DROP_REASON_SOCKET_FILTER,
|
||||
SKB_DROP_REASON_UDP_CSUM,
|
||||
SKB_DROP_REASON_NOT_SPECIFIED, /* drop reason is not specified */
|
||||
SKB_DROP_REASON_NO_SOCKET, /* socket not found */
|
||||
SKB_DROP_REASON_PKT_TOO_SMALL, /* packet size is too small */
|
||||
SKB_DROP_REASON_TCP_CSUM, /* TCP checksum error */
|
||||
SKB_DROP_REASON_SOCKET_FILTER, /* dropped by socket filter */
|
||||
SKB_DROP_REASON_UDP_CSUM, /* UDP checksum error */
|
||||
SKB_DROP_REASON_NETFILTER_DROP, /* dropped by netfilter */
|
||||
SKB_DROP_REASON_OTHERHOST, /* packet don't belong to current
|
||||
* host (interface is in promisc
|
||||
* mode)
|
||||
*/
|
||||
SKB_DROP_REASON_IP_CSUM, /* IP checksum error */
|
||||
SKB_DROP_REASON_IP_INHDR, /* there is something wrong with
|
||||
* IP header (see
|
||||
* IPSTATS_MIB_INHDRERRORS)
|
||||
*/
|
||||
SKB_DROP_REASON_IP_RPFILTER, /* IP rpfilter validate failed.
|
||||
* see the document for rp_filter
|
||||
* in ip-sysctl.rst for more
|
||||
* information
|
||||
*/
|
||||
SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST, /* destination address of L2
|
||||
* is multicast, but L3 is
|
||||
* unicast.
|
||||
*/
|
||||
SKB_DROP_REASON_XFRM_POLICY, /* xfrm policy check failed */
|
||||
SKB_DROP_REASON_IP_NOPROTO, /* no support for IP protocol */
|
||||
SKB_DROP_REASON_SOCKET_RCVBUFF, /* socket receive buff is full */
|
||||
SKB_DROP_REASON_PROTO_MEM, /* proto memory limition, such as
|
||||
* udp packet drop out of
|
||||
* udp_memory_allocated.
|
||||
*/
|
||||
SKB_DROP_REASON_MAX,
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,17 @@
|
|||
EM(SKB_DROP_REASON_TCP_CSUM, TCP_CSUM) \
|
||||
EM(SKB_DROP_REASON_SOCKET_FILTER, SOCKET_FILTER) \
|
||||
EM(SKB_DROP_REASON_UDP_CSUM, UDP_CSUM) \
|
||||
EM(SKB_DROP_REASON_NETFILTER_DROP, NETFILTER_DROP) \
|
||||
EM(SKB_DROP_REASON_OTHERHOST, OTHERHOST) \
|
||||
EM(SKB_DROP_REASON_IP_CSUM, IP_CSUM) \
|
||||
EM(SKB_DROP_REASON_IP_INHDR, IP_INHDR) \
|
||||
EM(SKB_DROP_REASON_IP_RPFILTER, IP_RPFILTER) \
|
||||
EM(SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST, \
|
||||
UNICAST_IN_L2_MULTICAST) \
|
||||
EM(SKB_DROP_REASON_XFRM_POLICY, XFRM_POLICY) \
|
||||
EM(SKB_DROP_REASON_IP_NOPROTO, IP_NOPROTO) \
|
||||
EM(SKB_DROP_REASON_SOCKET_RCVBUFF, SOCKET_RCVBUFF) \
|
||||
EM(SKB_DROP_REASON_PROTO_MEM, PROTO_MEM) \
|
||||
EMe(SKB_DROP_REASON_MAX, MAX)
|
||||
|
||||
#undef EM
|
||||
|
|
|
@ -196,7 +196,8 @@ resubmit:
|
|||
if (ipprot) {
|
||||
if (!ipprot->no_policy) {
|
||||
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb,
|
||||
SKB_DROP_REASON_XFRM_POLICY);
|
||||
return;
|
||||
}
|
||||
nf_reset_ct(skb);
|
||||
|
@ -215,7 +216,7 @@ resubmit:
|
|||
icmp_send(skb, ICMP_DEST_UNREACH,
|
||||
ICMP_PROT_UNREACH, 0);
|
||||
}
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_IP_NOPROTO);
|
||||
} else {
|
||||
__IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
|
||||
consume_skb(skb);
|
||||
|
@ -318,8 +319,10 @@ static int ip_rcv_finish_core(struct net *net, struct sock *sk,
|
|||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
int (*edemux)(struct sk_buff *skb);
|
||||
int err, drop_reason;
|
||||
struct rtable *rt;
|
||||
int err;
|
||||
|
||||
drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
|
||||
if (ip_can_use_hint(skb, iph, hint)) {
|
||||
err = ip_route_use_hint(skb, iph->daddr, iph->saddr, iph->tos,
|
||||
|
@ -396,19 +399,23 @@ static int ip_rcv_finish_core(struct net *net, struct sock *sk,
|
|||
* so-called "hole-196" attack) so do it for both.
|
||||
*/
|
||||
if (in_dev &&
|
||||
IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST))
|
||||
IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST)) {
|
||||
drop_reason = SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST;
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
|
||||
return NET_RX_SUCCESS;
|
||||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, drop_reason);
|
||||
return NET_RX_DROP;
|
||||
|
||||
drop_error:
|
||||
if (err == -EXDEV)
|
||||
if (err == -EXDEV) {
|
||||
drop_reason = SKB_DROP_REASON_IP_RPFILTER;
|
||||
__NET_INC_STATS(net, LINUX_MIB_IPRPFILTER);
|
||||
}
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
@ -436,13 +443,16 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
|||
static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
|
||||
{
|
||||
const struct iphdr *iph;
|
||||
int drop_reason;
|
||||
u32 len;
|
||||
|
||||
/* When the interface is in promisc. mode, drop all the crap
|
||||
* that it receives, do not try to analyse it.
|
||||
*/
|
||||
if (skb->pkt_type == PACKET_OTHERHOST)
|
||||
if (skb->pkt_type == PACKET_OTHERHOST) {
|
||||
drop_reason = SKB_DROP_REASON_OTHERHOST;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
__IP_UPD_PO_STATS(net, IPSTATS_MIB_IN, skb->len);
|
||||
|
||||
|
@ -452,6 +462,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
|
|||
goto out;
|
||||
}
|
||||
|
||||
drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
||||
goto inhdr_error;
|
||||
|
||||
|
@ -488,6 +499,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
|
|||
|
||||
len = ntohs(iph->tot_len);
|
||||
if (skb->len < len) {
|
||||
drop_reason = SKB_DROP_REASON_PKT_TOO_SMALL;
|
||||
__IP_INC_STATS(net, IPSTATS_MIB_INTRUNCATEDPKTS);
|
||||
goto drop;
|
||||
} else if (len < (iph->ihl*4))
|
||||
|
@ -516,11 +528,14 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
|
|||
return skb;
|
||||
|
||||
csum_error:
|
||||
drop_reason = SKB_DROP_REASON_IP_CSUM;
|
||||
__IP_INC_STATS(net, IPSTATS_MIB_CSUMERRORS);
|
||||
inhdr_error:
|
||||
if (drop_reason == SKB_DROP_REASON_NOT_SPECIFIED)
|
||||
drop_reason = SKB_DROP_REASON_IP_INHDR;
|
||||
__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, drop_reason);
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -2093,16 +2093,20 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
rc = __udp_enqueue_schedule_skb(sk, skb);
|
||||
if (rc < 0) {
|
||||
int is_udplite = IS_UDPLITE(sk);
|
||||
int drop_reason;
|
||||
|
||||
/* Note that an ENOMEM error is charged twice */
|
||||
if (rc == -ENOMEM)
|
||||
if (rc == -ENOMEM) {
|
||||
UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS,
|
||||
is_udplite);
|
||||
else
|
||||
drop_reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
|
||||
} else {
|
||||
UDP_INC_STATS(sock_net(sk), UDP_MIB_MEMERRORS,
|
||||
is_udplite);
|
||||
drop_reason = SKB_DROP_REASON_PROTO_MEM;
|
||||
}
|
||||
UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, drop_reason);
|
||||
trace_udp_fail_queue_rcv_skb(rc, sk);
|
||||
return -1;
|
||||
}
|
||||
|
@ -2120,14 +2124,17 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
*/
|
||||
static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
int drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
int is_udplite = IS_UDPLITE(sk);
|
||||
|
||||
/*
|
||||
* Charge it to the socket, dropping if the queue is full.
|
||||
*/
|
||||
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
|
||||
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
|
||||
drop_reason = SKB_DROP_REASON_XFRM_POLICY;
|
||||
goto drop;
|
||||
}
|
||||
nf_reset_ct(skb);
|
||||
|
||||
if (static_branch_unlikely(&udp_encap_needed_key) && up->encap_type) {
|
||||
|
@ -2204,8 +2211,10 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
|
|||
udp_lib_checksum_complete(skb))
|
||||
goto csum_error;
|
||||
|
||||
if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr)))
|
||||
if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr))) {
|
||||
drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
udp_csum_pull_header(skb);
|
||||
|
||||
|
@ -2213,11 +2222,12 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
|
|||
return __udp_queue_rcv_skb(sk, skb);
|
||||
|
||||
csum_error:
|
||||
drop_reason = SKB_DROP_REASON_UDP_CSUM;
|
||||
__UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
|
||||
drop:
|
||||
__UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
|
||||
atomic_inc(&sk->sk_drops);
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, drop_reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -621,7 +621,8 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
|
|||
case NF_ACCEPT:
|
||||
break;
|
||||
case NF_DROP:
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb,
|
||||
SKB_DROP_REASON_NETFILTER_DROP);
|
||||
ret = NF_DROP_GETERR(verdict);
|
||||
if (ret == 0)
|
||||
ret = -EPERM;
|
||||
|
|
Loading…
Reference in New Issue