⬢ DragonFlyBSD Kernel Audit
DF-5746 / fix.diff
← back to finding ↓ download raw
--- a/sys/sys/iconv.h	2026-10-11 03:03:02.905635940 +0000
+++ b/sys/sys/iconv.h	2026-10-11 03:03:14.385487644 +0000
@@ -125,6 +125,7 @@
 	const char *	cp_from;
 	const char *	cp_to;
 	void *		cp_data;
+	int		cp_datalen;	/* size of cp_data in bytes */
 	struct iconv_converter_class * cp_dcp;
 	struct iconv_cspair *cp_base;
 	TAILQ_ENTRY(iconv_cspair)	cp_link;
--- a/sys/libiconv/iconv.c	2026-10-11 03:03:02.909635888 +0000
+++ b/sys/libiconv/iconv.c	2026-10-11 03:03:14.385487644 +0000
@@ -423,6 +423,7 @@
 		lockmgr(&iconv_lock, LK_RELEASE);
 		return error;
 	}
+	csp->cp_datalen = din.ia_datalen;
 	if (din.ia_datalen) {
 		csp->cp_data = kmalloc(din.ia_datalen, M_ICONVDATA, M_WAITOK);
 		error = copyin(din.ia_data, csp->cp_data, din.ia_datalen);
--- a/sys/libiconv/iconv_xlat16.c	2026-10-11 03:03:02.909635888 +0000
+++ b/sys/libiconv/iconv_xlat16.c	2026-10-11 03:03:14.385487644 +0000
@@ -56,13 +56,31 @@
 	struct iconv_cspair *	d_csp;
 };
 
+#define	XLAT16_IDXLEN	(0x200 * sizeof(uint32_t *))	/* index array */
+#define	XLAT16_BLKLEN	(0x80 * sizeof(uint32_t))	/* one data block */
+
 static int
 iconv_xlat16_open(struct iconv_converter_class *dcp,
 	struct iconv_cspair *csp, struct iconv_cspair *cspf, void **dpp)
 {
 	struct iconv_xlat16 *dp;
 	uint32_t *headp, **idxp;
-	int i;
+	int i, nnz;
+
+	/*
+	 * Do not trust the table layout: cp_data must be large enough to
+	 * hold the index array plus one data block per non-NULL index.
+	 */
+	if (csp->cp_datalen < XLAT16_IDXLEN)
+		return (EINVAL);
+	nnz = 0;
+	idxp = (uint32_t **)csp->cp_data;
+	for (i = 0; i < 0x200; i++) {
+		if (*idxp++ != 0)
+			nnz++;
+	}
+	if (csp->cp_datalen < XLAT16_IDXLEN + nnz * XLAT16_BLKLEN)
+		return (EINVAL);
 
 	dp = (struct iconv_xlat16 *)kobj_create((struct kobj_class*)dcp, M_ICONV, M_WAITOK);
 	headp = (uint32_t *)((caddr_t)csp->cp_data + sizeof(dp->d_table));
--- a/sys/libiconv/iconv_xlat.c	2026-10-11 03:03:02.909635888 +0000
+++ b/sys/libiconv/iconv_xlat.c	2026-10-11 03:03:14.385487644 +0000
@@ -57,6 +57,10 @@
 {
 	struct iconv_xlat *dp;
 
+	/* the xlat table must cover all 256 byte values */
+	if (csp->cp_datalen < 256)
+		return (EINVAL);
+
 	dp = (struct iconv_xlat *)kobj_create((struct kobj_class*)dcp, M_ICONV, M_WAITOK);
 	dp->d_table = csp->cp_data;
 	dp->d_csp = csp;