Page MenuHomeFreeBSD

D22712.id69173.diff
No OneTemporary

D22712.id69173.diff

Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -68,6 +68,7 @@
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#include <netinet/icmp6.h>
@@ -103,6 +104,28 @@
SYSCTL_DECL(_net_inet6_icmp6);
+/*
+ * Global limit and per-VNET count for the maximum amount of default routers
+ * we accept in the list and equally for prefixes.
+ * The sysctls are not adjustable per-VNET to keep things simple and avoid
+ * VNETs allowing themselves to be a DoS target exhausting memory. Otherwise
+ * we need to make this a PROC as well and handle a global max cap per-vnet.
+ */
+static int nd6_defrouter_max = 16;
+SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_defrouter_max,
+ CTLFLAG_RW, &nd6_defrouter_max, 0,
+ "Maximum number of IPv6 default routers. 0 accept unlimited.");
+VNET_DEFINE_STATIC(int, nd6_defrouter_cur);
+#define V_nd6_defrouter_cur VNET(nd6_defrouter_cur)
+
+static int nd6_prefixes_max = 64;
+SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_prefixes_max,
+ CTLFLAG_RW, &nd6_prefixes_max, 0,
+ "Maximum number of IPv6 prefix list entries. 0 accept unlimited.");
+VNET_DEFINE_STATIC(int, nd6_prefixes_cur);
+#define V_nd6_prefixes_cur VNET(nd6_prefixes_cur)
+
+
/* RTPREF_MEDIUM has to be 0! */
#define RTPREF_HIGH 1
#define RTPREF_MEDIUM 0
@@ -136,6 +159,7 @@
ND6_WLOCK_ASSERT();
TAILQ_REMOVE(&V_nd6_defrouter, dr, dr_entry);
+ V_nd6_defrouter_cur--;
V_nd6_list_genid++;
if (drq != NULL)
TAILQ_INSERT_TAIL(drq, dr, dr_entry);
@@ -1102,10 +1126,20 @@
/*
* The preferred router may have changed, so relocate this
* router.
+ * We are removing the dr from the list only to re-add it
+ * later, so we skip any default router list limit checks here.
+ * This way we make sure we do not lose a (hopefully) valid
+ * and working default router in case we are under attack.
*/
TAILQ_REMOVE(&V_nd6_defrouter, dr, dr_entry);
n = dr;
} else {
+ if (nd6_defrouter_max > 0 &&
+ V_nd6_defrouter_cur >= nd6_defrouter_max) {
+ ND6_WUNLOCK();
+ ICMP6STAT_INC(icp6s_overflowdefrtr);
+ return (NULL);
+ }
n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO);
if (n == NULL) {
ND6_WUNLOCK();
@@ -1114,6 +1148,7 @@
memcpy(n, new, sizeof(*n));
/* Initialize with an extra reference for the caller. */
refcount_init(&n->refcnt, 2);
+ V_nd6_defrouter_cur++;
}
/*
@@ -1369,7 +1404,14 @@
IN6_MASK_ADDR(&new->ndpr_prefix.sin6_addr, &new->ndpr_mask);
ND6_WLOCK();
+ if (nd6_prefixes_max > 0 && V_nd6_prefixes_cur >= nd6_prefixes_max) {
+ ND6_WUNLOCK();
+ ICMP6STAT_INC(icp6s_overflowprfx);
+ free(new, M_IP6NDP);
+ return (ENOBUFS);
+ }
LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry);
+ V_nd6_prefixes_cur++;
V_nd6_list_genid++;
ND6_WUNLOCK();
@@ -1410,6 +1452,7 @@
ND6_WLOCK_ASSERT();
LIST_REMOVE(pr, ndpr_entry);
+ V_nd6_prefixes_cur--;
V_nd6_list_genid++;
if (list != NULL)
LIST_INSERT_HEAD(list, pr, ndpr_entry);

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 10, 12:58 AM (12 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31183889
Default Alt Text
D22712.id69173.diff (3 KB)

Event Timeline