|
|
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 |
|