|
|
cf1e18 |
From 491291cabf78efdeec8f18b09e14726a9030cc8f Mon Sep 17 00:00:00 2001
|
|
|
cf1e18 |
From: Alan Coopersmith <alan.coopersmith@oracle.com>
|
|
|
cf1e18 |
Date: Fri, 25 Apr 2014 23:02:34 -0700
|
|
|
cf1e18 |
Subject: [PATCH 06/12] CVE-2014-0210: unvalidated length fields in fs_read_query_info()
|
|
|
cf1e18 |
|
|
|
cf1e18 |
fs_read_query_info() parses a reply from the font server. The reply
|
|
|
cf1e18 |
contains embedded length fields, none of which are validated. This
|
|
|
cf1e18 |
can cause out of bound reads in either fs_read_query_info() or in
|
|
|
cf1e18 |
_fs_convert_props() which it calls to parse the fsPropInfo in the reply.
|
|
|
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/fsconvert.c | 9 +++++++++
|
|
|
cf1e18 |
src/fc/fserve.c | 37 +++++++++++++++++++++++++++++++++++++
|
|
|
cf1e18 |
2 files changed, 46 insertions(+), 0 deletions(-)
|
|
|
cf1e18 |
|
|
|
cf1e18 |
diff --git a/src/fc/fsconvert.c b/src/fc/fsconvert.c
|
|
|
cf1e18 |
index 75b5372..dfa1317 100644
|
|
|
cf1e18 |
--- a/src/fc/fsconvert.c
|
|
|
cf1e18 |
+++ b/src/fc/fsconvert.c
|
|
|
cf1e18 |
@@ -118,6 +118,10 @@ _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
|
|
|
cf1e18 |
for (i = 0; i < nprops; i++, dprop++, is_str++)
|
|
|
cf1e18 |
{
|
|
|
cf1e18 |
memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
|
|
|
cf1e18 |
+ if ((local_off.name.position >= pi->data_len) ||
|
|
|
cf1e18 |
+ (local_off.name.length >
|
|
|
cf1e18 |
+ (pi->data_len - local_off.name.position)))
|
|
|
cf1e18 |
+ goto bail;
|
|
|
cf1e18 |
dprop->name = MakeAtom(&pdc[local_off.name.position],
|
|
|
cf1e18 |
local_off.name.length, 1);
|
|
|
cf1e18 |
if (local_off.type != PropTypeString) {
|
|
|
cf1e18 |
@@ -125,10 +129,15 @@ _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
|
|
|
cf1e18 |
dprop->value = local_off.value.position;
|
|
|
cf1e18 |
} else {
|
|
|
cf1e18 |
*is_str = TRUE;
|
|
|
cf1e18 |
+ if ((local_off.value.position >= pi->data_len) ||
|
|
|
cf1e18 |
+ (local_off.value.length >
|
|
|
cf1e18 |
+ (pi->data_len - local_off.value.position)))
|
|
|
cf1e18 |
+ goto bail;
|
|
|
cf1e18 |
dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
|
|
|
cf1e18 |
local_off.value.length, 1);
|
|
|
cf1e18 |
if (dprop->value == BAD_RESOURCE)
|
|
|
cf1e18 |
{
|
|
|
cf1e18 |
+ bail:
|
|
|
cf1e18 |
free (pfi->props);
|
|
|
cf1e18 |
pfi->nprops = 0;
|
|
|
cf1e18 |
pfi->props = 0;
|
|
|
cf1e18 |
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
|
|
|
cf1e18 |
index 3abbacf..ec5336e 100644
|
|
|
cf1e18 |
--- a/src/fc/fserve.c
|
|
|
cf1e18 |
+++ b/src/fc/fserve.c
|
|
|
cf1e18 |
@@ -854,6 +854,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
|
|
|
cf1e18 |
FSFpePtr conn = (FSFpePtr) fpe->private;
|
|
|
cf1e18 |
fsQueryXInfoReply *rep;
|
|
|
cf1e18 |
char *buf;
|
|
|
cf1e18 |
+ long bufleft; /* length of reply left to use */
|
|
|
cf1e18 |
fsPropInfo *pi;
|
|
|
cf1e18 |
fsPropOffset *po;
|
|
|
cf1e18 |
pointer pd;
|
|
|
cf1e18 |
@@ -885,6 +886,9 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
|
|
|
cf1e18 |
buf = (char *) rep;
|
|
|
cf1e18 |
buf += SIZEOF(fsQueryXInfoReply);
|
|
|
cf1e18 |
|
|
|
cf1e18 |
+ bufleft = rep->length << 2;
|
|
|
cf1e18 |
+ bufleft -= SIZEOF(fsQueryXInfoReply);
|
|
|
cf1e18 |
+
|
|
|
cf1e18 |
/* move the data over */
|
|
|
cf1e18 |
fsUnpack_XFontInfoHeader(rep, pInfo);
|
|
|
cf1e18 |
|
|
|
cf1e18 |
@@ -892,17 +896,50 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
|
|
|
cf1e18 |
_fs_init_fontinfo(conn, pInfo);
|
|
|
cf1e18 |
|
|
|
cf1e18 |
/* Compute offsets into the reply */
|
|
|
cf1e18 |
+ if (bufleft < SIZEOF(fsPropInfo))
|
|
|
cf1e18 |
+ {
|
|
|
cf1e18 |
+ ret = -1;
|
|
|
cf1e18 |
+#ifdef DEBUG
|
|
|
cf1e18 |
+ fprintf(stderr, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n",
|
|
|
cf1e18 |
+ bufleft);
|
|
|
cf1e18 |
+#endif
|
|
|
cf1e18 |
+ goto bail;
|
|
|
cf1e18 |
+ }
|
|
|
cf1e18 |
pi = (fsPropInfo *) buf;
|
|
|
cf1e18 |
buf += SIZEOF (fsPropInfo);
|
|
|
cf1e18 |
+ bufleft -= SIZEOF(fsPropInfo);
|
|
|
cf1e18 |
|
|
|
cf1e18 |
+ if ((bufleft / SIZEOF(fsPropOffset)) < pi->num_offsets)
|
|
|
cf1e18 |
+ {
|
|
|
cf1e18 |
+ ret = -1;
|
|
|
cf1e18 |
+#ifdef DEBUG
|
|
|
cf1e18 |
+ fprintf(stderr,
|
|
|
cf1e18 |
+ "fsQueryXInfo: bufleft (%ld) / SIZEOF(fsPropOffset) < %d\n",
|
|
|
cf1e18 |
+ bufleft, pi->num_offsets);
|
|
|
cf1e18 |
+#endif
|
|
|
cf1e18 |
+ goto bail;
|
|
|
cf1e18 |
+ }
|
|
|
cf1e18 |
po = (fsPropOffset *) buf;
|
|
|
cf1e18 |
buf += pi->num_offsets * SIZEOF(fsPropOffset);
|
|
|
cf1e18 |
+ bufleft -= pi->num_offsets * SIZEOF(fsPropOffset);
|
|
|
cf1e18 |
|
|
|
cf1e18 |
+ if (bufleft < pi->data_len)
|
|
|
cf1e18 |
+ {
|
|
|
cf1e18 |
+ ret = -1;
|
|
|
cf1e18 |
+#ifdef DEBUG
|
|
|
cf1e18 |
+ fprintf(stderr,
|
|
|
cf1e18 |
+ "fsQueryXInfo: bufleft (%ld) < data_len (%d)\n",
|
|
|
cf1e18 |
+ bufleft, pi->data_len);
|
|
|
cf1e18 |
+#endif
|
|
|
cf1e18 |
+ goto bail;
|
|
|
cf1e18 |
+ }
|
|
|
cf1e18 |
pd = (pointer) buf;
|
|
|
cf1e18 |
buf += pi->data_len;
|
|
|
cf1e18 |
+ bufleft -= pi->data_len;
|
|
|
cf1e18 |
|
|
|
cf1e18 |
/* convert the properties and step over the reply */
|
|
|
cf1e18 |
ret = _fs_convert_props(pi, po, pd, pInfo);
|
|
|
cf1e18 |
+ bail:
|
|
|
cf1e18 |
_fs_done_read (conn, rep->length << 2);
|
|
|
cf1e18 |
|
|
|
cf1e18 |
if (ret == -1)
|
|
|
cf1e18 |
--
|
|
|
cf1e18 |
1.7.1
|
|
|
cf1e18 |
|