summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@oracle.com>2014-05-02 19:24:17 -0700
committerAlan Coopersmith <alan.coopersmith@oracle.com>2014-05-13 08:30:17 -0700
commit23a7a10aaada0a4b00272b512bd430545ce799e3 (patch)
tree77e7ae89eb5de8f7733c25ec8f5c173545f54806
parenta455f111eb2779e3258d49c1c003d3023d1b9bab (diff)
CVE-2014-0210: unvalidated length fields in fs_read_list_info()
fs_read_list_info() parses a reply from the font server. The reply contains a number of additional data items with embedded length or count fields, none of which are validated. This can cause out of bound reads when looping over these items in the reply. Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> (cherry picked from commit d338f81df1e188eb16e1d6aeea7f4800f89c1218)
-rw-r--r--src/fc/fserve.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
index 37aff24..1e1093c 100644
--- a/src/fc/fserve.c
+++ b/src/fc/fserve.c
@@ -2491,6 +2491,7 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
fsListFontsWithXInfoReply *rep;
char *buf;
+ long bufleft;
FSFpePtr conn = (FSFpePtr) fpe->private;
fsPropInfo *pi;
fsPropOffset *po;
@@ -2527,6 +2528,7 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
}
buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply);
+ bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply);
/*
* The original FS implementation didn't match
@@ -2535,19 +2537,71 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
*/
if (conn->fsMajorVersion <= 1)
{
+ if (rep->nameLength > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
+ (int) rep->nameLength, bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
memcpy (binfo->name, buf, rep->nameLength);
buf += _fs_pad_length (rep->nameLength);
+ bufleft -= _fs_pad_length (rep->nameLength);
}
pi = (fsPropInfo *) buf;
+ if (SIZEOF (fsPropInfo) > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n",
+ (int) SIZEOF (fsPropInfo), bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ bufleft -= SIZEOF (fsPropInfo);
buf += SIZEOF (fsPropInfo);
po = (fsPropOffset *) buf;
+ if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: offset length (%d * %d) > bufleft (%ld)\n",
+ pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ bufleft -= pi->num_offsets * SIZEOF (fsPropOffset);
buf += pi->num_offsets * SIZEOF (fsPropOffset);
pd = (pointer) buf;
+ if (pi->data_len > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: data length (%d) > bufleft (%ld)\n",
+ pi->data_len, bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ bufleft -= pi->data_len;
buf += pi->data_len;
if (conn->fsMajorVersion > 1)
{
+ if (rep->nameLength > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
+ (int) rep->nameLength, bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
memcpy (binfo->name, buf, rep->nameLength);
buf += _fs_pad_length (rep->nameLength);
+ bufleft -= _fs_pad_length (rep->nameLength);
}
#ifdef DEBUG