diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-06-01 06:46:25 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-06-01 06:46:25 +0200 |
commit | 61e1a8b01dca5d1d6eaa191ac9c12c240e4b2d75 (patch) | |
tree | 0210c94dfa61a9768fa996e2c793c37db7a8b6c9 /src/receive.c | |
parent | go test: properly pad message (diff) | |
download | wireguard-monolithic-historical-61e1a8b01dca5d1d6eaa191ac9c12c240e4b2d75.tar.xz wireguard-monolithic-historical-61e1a8b01dca5d1d6eaa191ac9c12c240e4b2d75.zip |
receive: trim incoming packets to IP header length
Diffstat (limited to 'src/receive.c')
-rw-r--r-- | src/receive.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/src/receive.c b/src/receive.c index b582d00..5807465 100644 --- a/src/receive.c +++ b/src/receive.c @@ -237,10 +237,15 @@ void packet_consume_data_done(struct sk_buff *skb, struct wireguard_peer *peer, skb->dev = dev; skb->ip_summed = CHECKSUM_UNNECESSARY; if (skb->len >= sizeof(struct iphdr) && ip_hdr(skb)->version == 4) { + len = ntohs(ip_hdr(skb)->tot_len); + if (unlikely(len < sizeof(struct iphdr))) + goto dishonest_packet_size; skb->protocol = htons(ETH_P_IP); if (INET_ECN_is_ce(PACKET_CB(skb)->ds)) IP_ECN_set_ce(ip_hdr(skb)); + } else if (skb->len >= sizeof(struct ipv6hdr) && ip_hdr(skb)->version == 6) { + len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr); skb->protocol = htons(ETH_P_IPV6); if (INET_ECN_is_ce(PACKET_CB(skb)->ds)) IP6_ECN_set_ce(skb, ipv6_hdr(skb)); @@ -251,6 +256,16 @@ void packet_consume_data_done(struct sk_buff *skb, struct wireguard_peer *peer, goto packet_processed; } + if (unlikely(len > skb->len)) { +dishonest_packet_size: + net_dbg_ratelimited("%s: Packet is lying about its size from peer %Lu (%pISpfsc)\n", netdev_pub(peer->device)->name, peer->internal_id, &peer->endpoint.addr); + ++dev->stats.rx_errors; + ++dev->stats.rx_length_errors; + goto packet_processed; + } + if (len < skb->len && pskb_trim(skb, len)) + goto packet_processed; + timers_data_received(peer); routed_peer = routing_table_lookup_src(&wg->peer_routing_table, skb); |