⬢ DragonFlyBSD Kernel Audit
DF-5675 / fix.diff
← back to finding ↓ download raw
--- a/sys/libprop/prop_object_impl.h
+++ b/sys/libprop/prop_object_impl.h
@@ -45,6 +45,16 @@
 	unsigned int	poec_depth;		/* nesting depth */
 };
 
+/*
+ * Maximum container nesting the (recursive) externalize walk will emit.
+ * Internalize, release and equals are iterative (prop_stack) and accept
+ * any depth; externalize recurses one stack frame per nesting level, so
+ * an attacker-supplied plist with deep <array>/<dict> nesting would
+ * otherwise exhaust the 16KB kernel thread stack (DF-5675: double fault
+ * at depth ~192, 64B/frame).  Real-world plists nest < 10 levels.
+ */
+#define	_PROP_EXTERNALIZE_MAX_DEPTH	64
+
 bool		_prop_object_externalize_start_tag(
 				struct _prop_object_externalize_context *,
 				const char *);
--- a/sys/libprop/prop_array.c
+++ b/sys/libprop/prop_array.c
@@ -155,6 +155,9 @@
 	unsigned int i;
 	bool rv = false;
 
+	if (ctx->poec_depth >= _PROP_EXTERNALIZE_MAX_DEPTH)
+		return (false);
+
 	_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
 
 	if (pa->pa_count == 0) {
--- a/sys/libprop/prop_dictionary.c
+++ b/sys/libprop/prop_dictionary.c
@@ -433,6 +433,9 @@
 	unsigned int i;
 	bool rv = false;
 
+	if (ctx->poec_depth >= _PROP_EXTERNALIZE_MAX_DEPTH)
+		return (false);
+
 	_PROP_RWLOCK_RDLOCK(pd->pd_rwlock);
 
 	if (pd->pd_count == 0) {