[patch] Add contextual out-of-bound checks in RTR Prefix PDU handler

Job Snijders job at fastly.com
Fri Sep 17 18:48:59 CEST 2021


Hi,

A broken RPKI Cache could contextually underflow or overflow the Max
Length value in RTR IPv4 / IPv6 Prefix PDUs. Below is a changeset
proposal which adds specific out-of-bounds checks and schedules a
reconnect for a later moment. This aligns BIRD's behavior with other
COTS BGP implementations.

RFC 6810 and RFC 8210 specify that the "Max Length" value MUST NOT be
less than the Prefix Length element (underflow). On the other side
overflow of the Max Length element also is possible, it being an 8-bit
unsigned integer allows for values larger than 32 or 128.

When a PDU is received where the Max Length field is corrputed, the RTR
client (BIRD) should immediately terminate the session, flush all data
learned from that cache, and log an error for the operator.

If this condition is hit, it seems better to follow the same approach
as for RPKI_CS_ERROR_TRANSPORT, because rpki_force_restart_proto()
causes an "as fast as possible" reconnect loop between BIRD and the RPKI
Cache server, which increases resource consumption on both sides.

Kind regards,

Job

diff --git proto/rpki/packets.c proto/rpki/packets.c
index dd11f997..09e20f38 100644
--- proto/rpki/packets.c
+++ proto/rpki/packets.c
@@ -737,6 +737,22 @@ rpki_handle_prefix_pdu(struct rpki_cache *cache, const struct pdu_header *pdu)
   net_addr_union addr = {};
   rpki_prefix_pdu_2_net_addr(pdu, &addr);
 
+  if (type == IPV4_PREFIX) {
+    if (addr.roa4.max_pxlen > IP4_MAX_PREFIX_LENGTH || addr.roa4.max_pxlen < addr.roa4.pxlen) {
+      RPKI_WARN(cache->p, "Received a corrupted packet from cache server");
+      rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, pdu, "Corrupted PDU");
+      rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
+      return RPKI_ERROR;
+    }
+  } else {
+    if (addr.roa6.max_pxlen > IP6_MAX_PREFIX_LENGTH || addr.roa6.max_pxlen < addr.roa6.pxlen) {
+      RPKI_WARN(cache->p, "Received a corrupted packet from cache server");
+      rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, pdu, "Corrupted PDU");
+      rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
+      return RPKI_ERROR;
+    }
+  }
+
   if (cf->ignore_max_length)
   {
     if (type == IPV4_PREFIX)
diff --git proto/rpki/rpki.c proto/rpki/rpki.c
index ab0837f3..91b69da0 100644
--- proto/rpki/rpki.c
+++ proto/rpki/rpki.c
@@ -288,9 +288,6 @@ rpki_cache_change_state(struct rpki_cache *cache, const enum rpki_cache_state ne
 
   case RPKI_CS_ERROR_FATAL:
     /* Fatal protocol error occurred. */
-    rpki_force_restart_proto(cache->p);
-    break;
-
   case RPKI_CS_ERROR_TRANSPORT:
     /* Error on the transport socket occurred. */
     rpki_close_connection(cache);


More information about the Bird-users mailing list