1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
From ece51493f1d970f45e53588e33a700464a42fbab Mon Sep 17 00:00:00 2001
From: Mike DePaulo <mikedep333@gmail.com>
Date: Sun, 8 Feb 2015 22:27:47 -0500
Subject: [PATCH 15/40] CVE-2014-0210: unvalidated length fields in
fs_read_glyphs() from xorg/lib/libXfont commit
520683652564c2a4e42328ae23eef9bb63271565
fs_read_glyphs() parses a reply from the font server. The reply
contains embedded length fields, none of which are validated.
This can cause out of bound reads when looping over the glyph
bitmaps in the reply.
---
nx-X11/lib/font/fc/fserve.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
--- a/nx-X11/lib/font/fc/fserve.c
+++ b/nx-X11/lib/font/fc/fserve.c
@@ -1917,6 +1917,7 @@ fs_read_glyphs(FontPathElementPtr fpe, F
FontInfoPtr pfi = &pfont->info;
fsQueryXBitmaps16Reply *rep;
char *buf;
+ long bufleft; /* length of reply left to use */
fsOffset32 *ppbits;
fsOffset32 local_off;
char *off_adr;
@@ -1948,9 +1949,33 @@ fs_read_glyphs(FontPathElementPtr fpe, F
buf = (char *) rep;
buf += SIZEOF (fsQueryXBitmaps16Reply);
+ bufleft = rep->length << 2;
+ bufleft -= SIZEOF (fsQueryXBitmaps16Reply);
+
+ if ((bufleft / SIZEOF (fsOffset32)) < rep->num_chars)
+ {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXBitmaps16: num_chars (%d) > bufleft (%ld) / %d\n",
+ rep->num_chars, bufleft, SIZEOF (fsOffset32));
+#endif
+ err = AllocError;
+ goto bail;
+ }
ppbits = (fsOffset32 *) buf;
buf += SIZEOF (fsOffset32) * (rep->num_chars);
+ bufleft -= SIZEOF (fsOffset32) * (rep->num_chars);
+ if (bufleft < rep->nbytes)
+ {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXBitmaps16: nbytes (%d) > bufleft (%ld)\n",
+ rep->nbytes, bufleft);
+#endif
+ err = AllocError;
+ goto bail;
+ }
pbitmaps = (pointer ) buf;
if (blockrec->type == FS_LOAD_GLYPHS)
@@ -2008,7 +2033,9 @@ fs_read_glyphs(FontPathElementPtr fpe, F
*/
if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
{
- if (local_off.length)
+ if (local_off.length &&
+ (local_off.position < rep->nbytes) &&
+ (local_off.length <= (rep->nbytes - local_off.position)))
{
bits = allbits;
allbits += local_off.length;
|