Tun: reject packets with bad length

Those packets are probably packets truncated because the buffer is not
large enough.
This commit is contained in:
Théophile Bastian 2020-06-16 20:24:59 +02:00
parent 79dbf23784
commit 0b8cf0edc1
5 changed files with 19 additions and 7 deletions

View file

@ -76,13 +76,18 @@ size_t UdpVpn::read_from_tun(char* buffer, size_t len) {
} }
size_t UdpVpn::read_from_tun(TunnelledPacket& packet) { size_t UdpVpn::read_from_tun(TunnelledPacket& packet) {
size_t nread = size_t payload_space = packet.get_payload_space();
read_from_tun(packet.get_payload(), packet.get_payload_space()); size_t nread = read_from_tun(packet.get_payload(), payload_space);
packet.set_payload_size(nread); packet.set_payload_size(nread);
if(!packet.parse_as_ipv6()) { if(!packet.parse_as_ipv6()) {
debugf("Ignoring packet with invalid header\n"); debugf("Ignoring packet with invalid header\n");
return 0; return 0;
} }
if(nread != packet.get_ipv6_header().packet_length()) {
debugf("Ignoring packet with bad size (expected %d, got %d, buffer %d)\n",
packet.get_ipv6_header().packet_length(), nread, payload_space);
return 0;
}
return nread; return nread;
} }

View file

@ -31,7 +31,7 @@ VpnPacketTLV VpnPacket::first_tlv() {
} }
size_t VpnPacket::get_tunnelled_mtu(size_t udp_mtu) { size_t VpnPacket::get_tunnelled_mtu(size_t udp_mtu) {
return udp_mtu - VPN_HEADER_BYTES - TLV_HEADER_BYTES; return udp_mtu - OUTER_HEADERS_BYTES - VPN_HEADER_BYTES - TLV_HEADER_BYTES;
} }
uint32_t VpnPacket::get_seqno() const { uint32_t VpnPacket::get_seqno() const {
@ -102,6 +102,12 @@ void VpnPacketTLV::set_payload_size(uint16_t size) {
_packet.increase_payload_size(size - old_size); _packet.increase_payload_size(size - old_size);
} }
uint16_t VpnPacketTLV::get_payload_space() const {
return _packet.get_payload_space()
- _packet.get_payload_size()
+ get_payload_size();
}
VpnPacket::PayloadType VpnPacketTLV::get_type() const { VpnPacket::PayloadType VpnPacketTLV::get_type() const {
return (VpnPacket::PayloadType)(*(uint8_t*)(get_data())); return (VpnPacket::PayloadType)(*(uint8_t*)(get_data()));
} }

View file

@ -159,10 +159,7 @@ class VpnPacketTLV {
/// Set the current payload size /// Set the current payload size
void set_payload_size(uint16_t size); void set_payload_size(uint16_t size);
/// Get the total available raw data space /// Get the total available raw data space
uint16_t get_payload_space() const { uint16_t get_payload_space() const;
return _packet.get_payload_space()
- _packet.get_payload_size()
- get_payload_size(); }
/// Get a pointer to the raw data (const version) /// Get a pointer to the raw data (const version)
const char* get_data() const { const char* get_data() const {

View file

@ -15,5 +15,6 @@ bool parse_ipv6_header(const char* data, size_t len, IPv6Header& header) {
memcpy(&(header.source), data + 8, 16); memcpy(&(header.source), data + 8, 16);
memcpy(&(header.dest), data + 24, 16); memcpy(&(header.dest), data + 24, 16);
header.payload_length = ntohs(*(uint16_t*)(data + 4));
return true; return true;
} }

View file

@ -5,6 +5,9 @@
struct IPv6Header { struct IPv6Header {
in6_addr source; in6_addr source;
in6_addr dest; in6_addr dest;
uint16_t payload_length;
uint16_t packet_length() const { return payload_length + 40; }
}; };
/** Parse an IPv6 header, filling `header`. Returns `true` on success. */ /** Parse an IPv6 header, filling `header`. Returns `true` on success. */