From b65259bf3bcca15b5069cb7a6c06f95a40f79813 Mon Sep 17 00:00:00 2001 From: Mike DePaulo Date: Sun, 8 Feb 2015 22:38:32 -0500 Subject: [PATCH 17/40] CVE-2014-0210: unvalidated length fields in fs_read_list_info() from xorg/lib/libXfont commit d338f81df1e188eb16e1d6aeea7f4800f89c1218 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. --- nx-X11/lib/font/fc/fserve.c | 56 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) --- a/nx-X11/lib/font/fc/fserve.c +++ b/nx-X11/lib/font/fc/fserve.c @@ -2501,6 +2501,7 @@ fs_read_list_info(FontPathElementPtr fpe FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; fsListFontsWithXInfoReply *rep; char *buf; + long bufleft; FSFpePtr conn = (FSFpePtr) fpe->private; fsPropInfo *pi; fsPropOffset *po; @@ -2537,7 +2538,8 @@ fs_read_list_info(FontPathElementPtr fpe } buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); - + bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply); + /* * The original FS implementation didn't match * the spec, version 1 was respecified to match the FS. @@ -2545,19 +2547,71 @@ fs_read_list_info(FontPathElementPtr fpe */ 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