summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Harris <pharris@opentext.com>2021-03-02 14:39:45 -0500
committerPeter Harris <pharris@opentext.com>2021-03-02 14:43:55 -0500
commit9529d2351fe52ffaaf9342343865073d5c5b6802 (patch)
tree248962046ced42cc1666cbdbddc00c854a6981e8 /src
parente7b2cae1ad9f07c188bcad27767a2f4fa6e0c2a4 (diff)
Fix use after free when font server connection lost
If there are multiple blocks waiting for the same font, only one of them will have ->freeFont set. The rest will be in a state of FS_DEPENDING. If the font server dies before the font finishes opening, the block with ->freeFont set will call ->unload_font, invalidating the pfont pointers in the remaining FS_DEPENDING blocks. Avoid a use after free (and potential crash) by passing conn to fs_cleanup_font instead of dereferencing pfont to find the conn. Signed-off-by: Peter Harris <pharris@opentext.com>
Diffstat (limited to 'src')
-rw-r--r--src/fc/fserve.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
index 23895d6..e739a8f 100644
--- a/src/fc/fserve.c
+++ b/src/fc/fserve.c
@@ -124,14 +124,14 @@ static CARD32 fs_blockState;
static int _fs_restart_connection ( FSFpePtr conn );
static void fs_send_query_bitmaps ( FontPathElementPtr fpe,
FSBlockDataPtr blockrec );
-static int fs_send_close_font ( FontPathElementPtr fpe, Font id );
+static int fs_send_close_font (FSFpePtr conn, Font id);
static void fs_client_died ( pointer client, FontPathElementPtr fpe );
static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync );
static void _fs_client_resolution ( FSFpePtr conn );
static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error);
static int fs_await_reply (FSFpePtr conn);
static void _fs_do_blocked (FSFpePtr conn);
-static void fs_cleanup_bfont (FSBlockedFontPtr bfont);
+static void fs_cleanup_bfont (FSFpePtr conn, FSBlockedFontPtr bfont);
char _fs_glyph_undefined;
char _fs_glyph_requested;
@@ -546,7 +546,7 @@ _fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
case FS_OPEN_FONT: {
FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
_fs_signal_clients_depending(&bfont->clients_depending);
break;
}
@@ -585,16 +585,12 @@ fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
* then unload the partially created font
*/
static void
-fs_cleanup_bfont (FSBlockedFontPtr bfont)
+fs_cleanup_bfont (FSFpePtr conn, FSBlockedFontPtr bfont)
{
- FSFontDataRec *fsd;
-
if (bfont->pfont)
{
- fsd = (FSFontDataRec *) bfont->pfont->fpePrivate;
-
/* make sure the FS knows we choked on it */
- fs_send_close_font(bfont->pfont->fpe, bfont->fontid);
+ fs_send_close_font(conn, bfont->fontid);
/*
* Either unload the font if it's being opened for
@@ -612,7 +608,10 @@ fs_cleanup_bfont (FSBlockedFontPtr bfont)
bfont->pfont = 0;
}
else
+ {
+ FSFontDataRec *fsd = (FSFontDataRec *)bfont->pfont->fpePrivate;
fsd->generation = -1;
+ }
}
}
@@ -746,7 +745,7 @@ fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
_fs_reply_failed (rep, fsOpenBitmapFontReply, "!=");
return BadFontName;
}
@@ -762,7 +761,7 @@ fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
if (rep->otherid && !(bfont->flags & FontReopen))
{
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
/* Find old font if we're completely done getting it from server. */
bfont->pfont = find_old_font(rep->otherid);
@@ -891,7 +890,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
_fs_reply_failed (rep, fsQueryXInfoReply, "<");
return BadFontName;
}
@@ -964,7 +963,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
if (ret == -1)
{
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
return AllocError;
}
@@ -983,7 +982,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
}
else
{
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
err = BadFontName;
}
_fs_free_props (pInfo);
@@ -1056,7 +1055,7 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
_fs_reply_failed (rep, fsQueryXExtents16Reply, "<");
return BadFontName;
}
@@ -1094,7 +1093,7 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
if (!pCI)
{
_fs_done_read (conn, rep->length << 2);
- fs_cleanup_bfont(bfont);
+ fs_cleanup_bfont(conn, bfont);
return AllocError;
}
fsfont->encoding = pCI;
@@ -1788,7 +1787,7 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
if (err == Successful)
*ppfont = bfont->pfont;
else
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
bfont->freeFont = FALSE;
_fs_remove_block_rec (conn, blockrec);
}
@@ -1845,7 +1844,7 @@ fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
if (err == Successful)
*ppfont = bfont->pfont;
else
- fs_cleanup_bfont (bfont);
+ fs_cleanup_bfont (conn, bfont);
_fs_remove_block_rec (conn, blockrec);
return err;
}
@@ -1856,9 +1855,8 @@ fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
/* ARGSUSED */
static int
-fs_send_close_font(FontPathElementPtr fpe, Font id)
+fs_send_close_font(FSFpePtr conn, Font id)
{
- FSFpePtr conn = (FSFpePtr) fpe->private;
fsCloseReq req;
if (conn->blockState & FS_GIVE_UP)
@@ -1882,7 +1880,7 @@ fs_close_font(FontPathElementPtr fpe, FontPtr pfont)
FSFpePtr conn = (FSFpePtr) fpe->private;
if (conn->generation == fsd->generation)
- fs_send_close_font(fpe, fsd->fontid);
+ fs_send_close_font(conn, fsd->fontid);
#ifdef DEBUG
{