Blame SOURCES/0004-CVE-2014-0210-unvalidated-lengths-when-reading-repli.patch

cf1e18
From cbb64aef35960b2882be721f4b8fbaa0fb649d12 Mon Sep 17 00:00:00 2001
cf1e18
From: Alan Coopersmith <alan.coopersmith@oracle.com>
cf1e18
Date: Fri, 25 Apr 2014 23:02:12 -0700
cf1e18
Subject: [PATCH 04/12] CVE-2014-0210: unvalidated lengths when reading replies from font server
cf1e18
cf1e18
Functions to handle replies to font server requests were casting replies
cf1e18
from the generic form to reply specific structs without first checking
cf1e18
that the reply was at least as long as the struct being cast to.
cf1e18
cf1e18
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
cf1e18
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
cf1e18
Reviewed-by: Adam Jackson <ajax@redhat.com>
cf1e18
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
cf1e18
---
cf1e18
 src/fc/fserve.c |   44 ++++++++++++++++++++++++++++++++++++++------
cf1e18
 1 files changed, 38 insertions(+), 6 deletions(-)
cf1e18
cf1e18
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
cf1e18
index aa9acdb..f08028f 100644
cf1e18
--- a/src/fc/fserve.c
cf1e18
+++ b/src/fc/fserve.c
cf1e18
@@ -91,6 +91,12 @@ in this Software without prior written authorization from The Open Group.
cf1e18
 			     (pci)->descent || \
cf1e18
 			     (pci)->characterWidth)
cf1e18
 
cf1e18
+/*
cf1e18
+ * SIZEOF(r) is in bytes, length fields in the protocol are in 32-bit words,
cf1e18
+ * so this converts for doing size comparisons.
cf1e18
+ */
cf1e18
+#define LENGTHOF(r)	(SIZEOF(r) >> 2)
cf1e18
+
cf1e18
 extern void ErrorF(const char *f, ...);
cf1e18
 
cf1e18
 static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
cf1e18
@@ -206,9 +212,22 @@ _fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep)
cf1e18
 		 rep->sequenceNumber,
cf1e18
 		 conn->reqbuffer[i].opcode);
cf1e18
 }
cf1e18
+
cf1e18
+#define _fs_reply_failed(rep, name, op) do {                            \
cf1e18
+    if (rep) {                                                          \
cf1e18
+        if (rep->type == FS_Error)                                      \
cf1e18
+            fprintf (stderr, "Error: %d Request: %s\n",                 \
cf1e18
+                     ((fsError *)rep)->request, #name);                 \
cf1e18
+        else                                                            \
cf1e18
+            fprintf (stderr, "Bad Length for %s Reply: %d %s %d\n",     \
cf1e18
+                     #name, rep->length, op, LENGTHOF(name));           \
cf1e18
+    }                                                                   \
cf1e18
+} while (0)
cf1e18
+
cf1e18
 #else
cf1e18
 #define _fs_add_req_log(conn,op)    ((conn)->current_seq++)
cf1e18
 #define _fs_add_rep_log(conn,rep)
cf1e18
+#define _fs_reply_failed(rep,name,op)
cf1e18
 #endif
cf1e18
 
cf1e18
 static Bool
cf1e18
@@ -682,13 +701,15 @@ fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     int			    ret;
cf1e18
 
cf1e18
     rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret;;
cf1e18
-    if (!rep || rep->type == FS_Error)
cf1e18
+    if (!rep || rep->type == FS_Error ||
cf1e18
+	(rep->length != LENGTHOF(fsOpenBitmapFontReply)))
cf1e18
     {
cf1e18
 	if (ret == FSIO_BLOCK)
cf1e18
 	    return StillWorking;
cf1e18
 	if (rep)
cf1e18
 	    _fs_done_read (conn, rep->length << 2);
cf1e18
 	fs_cleanup_bfont (bfont);
cf1e18
+	_fs_reply_failed (rep, fsOpenBitmapFontReply, "!=");
cf1e18
 	return BadFontName;
cf1e18
     }
cf1e18
 
cf1e18
@@ -824,13 +845,15 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     int			ret;
cf1e18
 
cf1e18
     rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret;;
cf1e18
-    if (!rep || rep->type == FS_Error)
cf1e18
+    if (!rep || rep->type == FS_Error ||
cf1e18
+	(rep->length < LENGTHOF(fsQueryXInfoReply)))
cf1e18
     {
cf1e18
 	if (ret == FSIO_BLOCK)
cf1e18
 	    return StillWorking;
cf1e18
 	if (rep)
cf1e18
 	    _fs_done_read (conn, rep->length << 2);
cf1e18
 	fs_cleanup_bfont (bfont);
cf1e18
+	_fs_reply_failed (rep, fsQueryXInfoReply, "<");
cf1e18
 	return BadFontName;
cf1e18
     }
cf1e18
 
cf1e18
@@ -951,13 +974,15 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     FontInfoRec		    *fi = &bfont->pfont->info;
cf1e18
 
cf1e18
     rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret;;
cf1e18
-    if (!rep || rep->type == FS_Error)
cf1e18
+    if (!rep || rep->type == FS_Error ||
cf1e18
+	(rep->length < LENGTHOF(fsQueryXExtents16Reply)))
cf1e18
     {
cf1e18
 	if (ret == FSIO_BLOCK)
cf1e18
 	    return StillWorking;
cf1e18
 	if (rep)
cf1e18
 	    _fs_done_read (conn, rep->length << 2);
cf1e18
 	fs_cleanup_bfont (bfont);
cf1e18
+	_fs_reply_failed (rep, fsQueryXExtents16Reply, "<");
cf1e18
 	return BadFontName;
cf1e18
     }
cf1e18
 
cf1e18
@@ -1823,13 +1848,15 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     unsigned long	    minchar, maxchar;
cf1e18
 
cf1e18
     rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret;;
cf1e18
-    if (!rep || rep->type == FS_Error)
cf1e18
+    if (!rep || rep->type == FS_Error ||
cf1e18
+	(rep->length < LENGTHOF(fsQueryXBitmaps16Reply)))
cf1e18
     {
cf1e18
 	if (ret == FSIO_BLOCK)
cf1e18
 	    return StillWorking;
cf1e18
 	if (rep)
cf1e18
 	    _fs_done_read (conn, rep->length << 2);
cf1e18
 	err = AllocError;
cf1e18
+	_fs_reply_failed (rep, fsQueryXBitmaps16Reply, "<");
cf1e18
 	goto bail;
cf1e18
     }
cf1e18
 
cf1e18
@@ -2232,12 +2259,14 @@ fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     int			err;
cf1e18
 
cf1e18
     rep = (fsListFontsReply *) fs_get_reply (conn, &ret;;
cf1e18
-    if (!rep || rep->type == FS_Error)
cf1e18
+    if (!rep || rep->type == FS_Error ||
cf1e18
+	(rep->length < LENGTHOF(fsListFontsReply)))
cf1e18
     {
cf1e18
 	if (ret == FSIO_BLOCK)
cf1e18
 	    return StillWorking;
cf1e18
 	if (rep)
cf1e18
 	    _fs_done_read (conn, rep->length << 2);
cf1e18
+	_fs_reply_failed (rep, fsListFontsReply, "<");
cf1e18
 	return AllocError;
cf1e18
     }
cf1e18
     data = (char *) rep + SIZEOF (fsListFontsReply);
cf1e18
@@ -2356,12 +2385,15 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
cf1e18
     _fs_free_props (&binfo->info);
cf1e18
 
cf1e18
     rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret;;
cf1e18
-    if (!rep || rep->type == FS_Error)
cf1e18
+    if (!rep || rep->type == FS_Error ||
cf1e18
+	((rep->nameLength != 0) &&
cf1e18
+	 (rep->length < LENGTHOF(fsListFontsWithXInfoReply))))
cf1e18
     {
cf1e18
 	if (ret == FSIO_BLOCK)
cf1e18
 	    return StillWorking;
cf1e18
 	binfo->status = FS_LFWI_FINISHED;
cf1e18
 	err = AllocError;
cf1e18
+	_fs_reply_failed (rep, fsListFontsWithXInfoReply, "<");
cf1e18
 	goto done;
cf1e18
     }
cf1e18
     /*
cf1e18
-- 
cf1e18
1.7.1
cf1e18