⬢ DragonFlyBSD Kernel Audit
DF-5690 / fix.diff
← back to finding ↓ download raw
--- a/sys/libprop/prop_string.c
+++ b/sys/libprop/prop_string.c
@@ -185,6 +185,31 @@
  *	Create an immutable string that contains a refrence to the
  *	provided C string.
  */
+#if defined(_KERNEL) || defined(PROP_RIG_FORCE_NOCOPY_COPY)
+/*
+ * DF-5690: in a kernel build the "nocopy" borrowing semantics are a
+ * use-after-free / heap-overflow foot-gun: the prop_string keeps a raw
+ * pointer to caller-owned memory, never owns or copies it
+ * (_prop_string_free skips PS_F_NOCOPY buffers, prop_string.c:85-87), and
+ * ps_size is frozen at creation while prop_string_cstring()/
+ * externalization re-read the buffer to its *current* NUL
+ * (prop_string.c:302-304).  A plist that outlives (or outgrows) the
+ * caller's buffer therefore reads freed/stale kernel memory into data
+ * copied back to userspace (prop_array_copyout_ioctl externalize path),
+ * and the copy variant can overflow its ps_size+1 allocation.  There are
+ * no in-kernel callers today; make the kernel build copy so a plist can
+ * never reference caller-owned transient memory.
+ *
+ * PROP_RIG_FORCE_NOCOPY_COPY is a verification-rig-only activation define
+ * (findings/poc/DF-5690); it is undefined in every real build.
+ */
+prop_string_t
+prop_string_create_cstring_nocopy(const char *str)
+{
+
+	return (prop_string_create_cstring(str));
+}
+#else
 prop_string_t
 prop_string_create_cstring_nocopy(const char *str)
 {
@@ -198,6 +223,7 @@
 	}
 	return (ps);
 }
+#endif
 
 /*
  * prop_string_copy --