Blame SOURCES/0012-CVE-2014-0210-unvalidated-length-fields-in-fs_read_l.patch

cf1e18
From d338f81df1e188eb16e1d6aeea7f4800f89c1218 Mon Sep 17 00:00:00 2001
cf1e18
From: Alan Coopersmith <alan.coopersmith@oracle.com>
cf1e18
Date: Fri, 2 May 2014 19:24:17 -0700
cf1e18
Subject: [PATCH 12/12] CVE-2014-0210: unvalidated length fields in fs_read_list_info()
cf1e18
cf1e18
fs_read_list_info() parses a reply from the font server.  The reply
cf1e18
contains a number of additional data items with embedded length or
cf1e18
count fields, none of which are validated. This can cause out of
cf1e18
bound reads when looping over these items in the reply.
cf1e18
cf1e18
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
cf1e18
---
cf1e18
 src/fc/fserve.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
cf1e18
 1 files changed, 54 insertions(+), 0 deletions(-)
cf1e18
cf1e18
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
cf1e18
index 4dcdc04..c1cf9d6 100644
cf1e18
--- a/src/fc/fserve.c
cf1e18
+++ b/src/fc/fserve.c
cf1e18
@@ -2491,6 +2491,7 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     FSBlockedListInfoPtr	binfo = (FSBlockedListInfoPtr) blockrec->data;
cf1e18
     fsListFontsWithXInfoReply	*rep;
cf1e18
     char			*buf;
cf1e18
+    long			bufleft;
cf1e18
     FSFpePtr			conn = (FSFpePtr) fpe->private;
cf1e18
     fsPropInfo			*pi;
cf1e18
     fsPropOffset		*po;
cf1e18
@@ -2527,6 +2528,7 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     }
cf1e18
 
cf1e18
     buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply);
cf1e18
+    bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply);
cf1e18
 
cf1e18
     /*
cf1e18
      * The original FS implementation didn't match
cf1e18
@@ -2535,19 +2537,71 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
      */
cf1e18
     if (conn->fsMajorVersion <= 1)
cf1e18
     {
cf1e18
+	if (rep->nameLength > bufleft) {
cf1e18
+#ifdef DEBUG
cf1e18
+	    fprintf(stderr,
cf1e18
+		    "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
cf1e18
+		    (int) rep->nameLength, bufleft);
cf1e18
+#endif
cf1e18
+	    err = AllocError;
cf1e18
+	    goto done;
cf1e18
+	}
cf1e18
+	/* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
cf1e18
 	memcpy (binfo->name, buf, rep->nameLength);
cf1e18
 	buf += _fs_pad_length (rep->nameLength);
cf1e18
+	bufleft -= _fs_pad_length (rep->nameLength);
cf1e18
     }
cf1e18
     pi = (fsPropInfo *) buf;
cf1e18
+    if (SIZEOF (fsPropInfo) > bufleft) {
cf1e18
+#ifdef DEBUG
cf1e18
+	fprintf(stderr,
cf1e18
+		"fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n",
cf1e18
+		(int) SIZEOF (fsPropInfo), bufleft);
cf1e18
+#endif
cf1e18
+	err = AllocError;
cf1e18
+	goto done;
cf1e18
+    }
cf1e18
+    bufleft -= SIZEOF (fsPropInfo);
cf1e18
     buf += SIZEOF (fsPropInfo);
cf1e18
     po = (fsPropOffset *) buf;
cf1e18
+    if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) {
cf1e18
+#ifdef DEBUG
cf1e18
+	fprintf(stderr,
cf1e18
+		"fsListFontsWithXInfo: offset length (%d * %d) > bufleft (%ld)\n",
cf1e18
+		pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft);
cf1e18
+#endif
cf1e18
+	err = AllocError;
cf1e18
+	goto done;
cf1e18
+    }
cf1e18
+    bufleft -= pi->num_offsets * SIZEOF (fsPropOffset);
cf1e18
     buf += pi->num_offsets * SIZEOF (fsPropOffset);
cf1e18
     pd = (pointer) buf;
cf1e18
+    if (pi->data_len > bufleft) {
cf1e18
+#ifdef DEBUG
cf1e18
+	fprintf(stderr,
cf1e18
+		"fsListFontsWithXInfo: data length (%d) > bufleft (%ld)\n",
cf1e18
+		pi->data_len, bufleft);
cf1e18
+#endif
cf1e18
+	err = AllocError;
cf1e18
+	goto done;
cf1e18
+    }
cf1e18
+    bufleft -= pi->data_len;
cf1e18
     buf += pi->data_len;
cf1e18
     if (conn->fsMajorVersion > 1)
cf1e18
     {
cf1e18
+	if (rep->nameLength > bufleft) {
cf1e18
+#ifdef DEBUG
cf1e18
+	    fprintf(stderr,
cf1e18
+		    "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
cf1e18
+		    (int) rep->nameLength, bufleft);
cf1e18
+#endif
cf1e18
+	    err = AllocError;
cf1e18
+	    goto done;
cf1e18
+	}
cf1e18
+	/* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
cf1e18
 	memcpy (binfo->name, buf, rep->nameLength);
cf1e18
 	buf += _fs_pad_length (rep->nameLength);
cf1e18
+	bufleft -= _fs_pad_length (rep->nameLength);
cf1e18
     }
cf1e18
 
cf1e18
 #ifdef DEBUG
cf1e18
-- 
cf1e18
1.7.1
cf1e18