Introduce a new flag (TP_STATUS_CSUM_UNNECESSARY) to indicate that the driver has completely validated the checksums in the packet. The flag differs from TP_STATUS_CSUM_VALID in that it will only be set if all the layers are valid, while TP_STATUS_CSUM_VALID is set as well if only the IP layer is valid. The name is derived from the skb->ip_summed setting CHECKSUM_UNNECESSARY. Security tools such as Suricata, Snort, Zeek/Bro need to know not only that a packet has not been corrupted, but also that the checksums are correct. Without this an attacker could send a packet, for example a TCP RST packet, that would be accepted by the security tool, but rejected by the end host. To avoid this scenario tools will have to (re)calcultate/validate the checksum as well. This patch has been tested with Suricata with the virtio driver, where it reduced the ammount of time spent in the Suricata TCP checksum validation to about half. Signed-off-by: Victor Julien <victor@xxxxxxxxxxxx> --- Documentation/networking/packet_mmap.rst | 6 ++++++ include/uapi/linux/if_packet.h | 1 + net/packet/af_packet.c | 3 +++ 3 files changed, 10 insertions(+) diff --git a/Documentation/networking/packet_mmap.rst b/Documentation/networking/packet_mmap.rst index 6c009ceb1183..f670292e6d95 100644 --- a/Documentation/networking/packet_mmap.rst +++ b/Documentation/networking/packet_mmap.rst @@ -472,6 +472,12 @@ TP_STATUS_CSUM_VALID This flag indicates that at least the transport validated on the kernel side. If the flag is not set then we are free to check the checksum by ourselves provided that TP_STATUS_CSUMNOTREADY is also not set. +TP_STATUS_CSUM_UNNECESSARY This flag indicates that the driver validated all + the packets csums. If it is not set it might be that + the driver doesn't support this, or that one of the + layers csums is bad. TP_STATUS_CSUM_VALID may still + be set if the transport layer csum is correct or + if the driver supports only this mode. ====================== ======================================================= for convenience there are also the following defines:: diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h index 3d884d68eb30..76a5c762e2e0 100644 --- a/include/uapi/linux/if_packet.h +++ b/include/uapi/linux/if_packet.h @@ -113,6 +113,7 @@ struct tpacket_auxdata { #define TP_STATUS_BLK_TMO (1 << 5) #define TP_STATUS_VLAN_TPID_VALID (1 << 6) /* auxdata has valid tp_vlan_tpid */ #define TP_STATUS_CSUM_VALID (1 << 7) +#define TP_STATUS_CSUM_UNNECESSARY (1 << 8) /* Tx ring - header status */ #define TP_STATUS_AVAILABLE 0 diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 29bd405adbbd..5dd8bad9bc23 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2215,6 +2215,9 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (skb->ip_summed == CHECKSUM_PARTIAL) status |= TP_STATUS_CSUMNOTREADY; + else if (skb->pkt_type != PACKET_OUTGOING && + skb->ip_summed == CHECKSUM_UNNECESSARY) + status |= (TP_STATUS_CSUM_UNNECESSARY | TP_STATUS_CSUM_VALID); else if (skb->pkt_type != PACKET_OUTGOING && (skb->ip_summed == CHECKSUM_COMPLETE || skb_csum_unnecessary(skb))) -- 2.17.1