From e29bbd5bf0565eaf7c02f85a57b87f66531fa6b3 Mon Sep 17 00:00:00 2001
From: Mike DePaulo <mikedep333@gmail.com>
Date: Sun, 8 Feb 2015 22:08:09 -0500
Subject: [PATCH 11/40] CVE-2014-0210: unvalidated length fields in
 fs_read_query_info() from xorg/lib/libXfont commit
 491291cabf78efdeec8f18b09e14726a9030cc8f

fs_read_query_info() parses a reply from the font server.  The reply
contains embedded length fields, none of which are validated.  This
can cause out of bound reads in either fs_read_query_info() or in
_fs_convert_props() which it calls to parse the fsPropInfo in the reply.

v2: apply correctly on nx-libs 3.6.x (Mihai Moldovan)
---
 nx-X11/lib/font/fc/fsconvert.c | 19 ++++++++++++++-----
 nx-X11/lib/font/fc/fserve.c    | 43 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/nx-X11/lib/font/fc/fsconvert.c b/nx-X11/lib/font/fc/fsconvert.c
index 9a5e194..afa2c32 100644
--- a/nx-X11/lib/font/fc/fsconvert.c
+++ b/nx-X11/lib/font/fc/fsconvert.c
@@ -123,6 +123,10 @@ _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
     for (i = 0; i < nprops; i++, dprop++, is_str++) 
     {
 	memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
+	if ((local_off.name.position >= pi->data_len) ||
+		(local_off.name.length >
+		 (pi->data_len - local_off.name.position)))
+	    goto bail;
 	dprop->name = MakeAtom(&pdc[local_off.name.position],
 			       local_off.name.length, 1);
 	if (local_off.type != PropTypeString) {
@@ -130,15 +134,20 @@ _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
 	    dprop->value = local_off.value.position;
 	} else {
 	    *is_str = TRUE;
+	    if ((local_off.value.position >= pi->data_len) ||
+			(local_off.value.length >
+			 (pi->data_len - local_off.value.position)))
+			goto bail;
 	    dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
 					    local_off.value.length, 1);
 	    if (dprop->value == BAD_RESOURCE)
 	    {
-		xfree (pfi->props);
-		pfi->nprops = 0;
-		pfi->props = 0;
-		pfi->isStringProp = 0;
-		return -1;
+		  bail:
+			xfree (pfi->props);
+			pfi->nprops = 0;
+			pfi->props = 0;
+			pfi->isStringProp = 0;
+			return -1;
 	    }
 	}
 	off_adr += SIZEOF(fsPropOffset);
diff --git a/nx-X11/lib/font/fc/fserve.c b/nx-X11/lib/font/fc/fserve.c
index 9e652d2..75cabdd 100644
--- a/nx-X11/lib/font/fc/fserve.c
+++ b/nx-X11/lib/font/fc/fserve.c
@@ -866,6 +866,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
     FSFpePtr		conn = (FSFpePtr) fpe->private;
     fsQueryXInfoReply	*rep;
     char		*buf;
+    long		bufleft = 0; /* length of reply left to use */
     fsPropInfo		*pi;
     fsPropOffset	*po;
     pointer		pd;
@@ -896,7 +897,10 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
 
     buf = (char *) rep;
     buf += SIZEOF(fsQueryXInfoReply);
-    
+ 
+    bufleft = rep->length << 2;
+    bufleft -= SIZEOF(fsQueryXInfoReply);
+
     /* move the data over */
     fsUnpack_XFontInfoHeader(rep, pInfo);
     
@@ -904,19 +908,52 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
     _fs_init_fontinfo(conn, pInfo);
 
     /* Compute offsets into the reply */
+    if (bufleft < SIZEOF(fsPropInfo))
+    {
+	ret = -1;
+#ifdef DEBUG
+	fprintf(stderr, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n",
+		bufleft);
+#endif
+	goto bail;
+    }
     pi = (fsPropInfo *) buf;
     buf += SIZEOF (fsPropInfo);
-    
+    bufleft -= SIZEOF (fsPropInfo);
+
+    if ((bufleft / SIZEOF (fsPropOffset)) < pi->num_offsets)
+    {
+	ret = -1;
+#ifdef DEBUG
+	fprintf(stderr,
+		"fsQueryXInfo: (bufleft / SIZEOF (fsPropOffset)) (%ld) < pi->num_offsets (%d)\n",
+		bufleft / SIZEOF (fsPropOffset), pi->num_offsets);
+#endif
+	goto bail;
+    }
     po = (fsPropOffset *) buf;
     buf += pi->num_offsets * SIZEOF(fsPropOffset);
+    bufleft -= pi->num_offsets * SIZEOF(fsPropOffset);
 
+    if (bufleft < pi->data_len)
+    {
+	ret = -1;
+#ifdef DEBUG
+	fprintf(stderr,
+		"fsQueryXInfo: bufleft (%ld) < data_len (%d)\n",
+		bufleft, pi->data_len);
+#endif
+	goto bail;
+    }
     pd = (pointer) buf;
     buf += pi->data_len;
+    bufleft -= pi->data_len;
     
     /* convert the properties and step over the reply */
     ret = _fs_convert_props(pi, po, pd, pInfo);
+  bail:    
     _fs_done_read (conn, rep->length << 2);
-    
+
     if (ret == -1)
     {
 	fs_cleanup_bfont (bfont);
-- 
2.1.4

