File xrdp-CVE-2023-42822.patch of Package xrdp.31568
From 3896cfb2f63241725790c4cdbee60ee97b6ee9ed Mon Sep 17 00:00:00 2001
From: matt335672 <30179339+matt335672@users.noreply.github.com>
Date: Mon, 25 Sep 2023 11:25:04 +0100
Subject: [PATCH] CVE-2023-42822
- font_items in struct xrdp_font renamed to chars to catch all
accesses to it. This name is consistent with the type of
the array elements (struct xrdp_font_char).
- Additional fields added to struct xrdp_font to allow for range
checking and for a default character to be provided
- Additional checks and logic added to xrdp_font_create()
- New macro XRDP_FONT_GET_CHAR() added to perform checked access
to chars field in struct xrdp_font
---
xrdp/xrdp.h | 13 ++++++-
xrdp/xrdp_font.c | 94 ++++++++++++++++++++++++++++++++++++++-------
xrdp/xrdp_painter.c | 10 ++---
xrdp/xrdp_types.h | 16 +++++---
4 files changed, 107 insertions(+), 26 deletions(-)
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 697081db..a8c917f5 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -316,8 +316,17 @@ xrdp_font_create(struct xrdp_wm* wm);
void
xrdp_font_delete(struct xrdp_font* self);
int
-xrdp_font_item_compare(struct xrdp_font_char* font1,
- struct xrdp_font_char* font2);
+xrdp_font_item_compare(struct xrdp_font_char *font1,
+ struct xrdp_font_char *font2);
+/**
+ * Gets a checked xrdp_font_char from a font
+ * @param f Font
+ * @param c32 Unicode codepoint
+ */
+#define XRDP_FONT_GET_CHAR(f, c32) \
+ (((unsigned int)(c32) >= ' ') && ((unsigned int)(c32) < (f)->char_count) \
+ ? ((f)->chars + (unsigned int)(c32)) \
+ : (f)->default_char)
/* funcs.c */
int
diff --git a/xrdp/xrdp_font.c b/xrdp/xrdp_font.c
index ae2e116f..fd6a1efe 100644
--- a/xrdp/xrdp_font.c
+++ b/xrdp/xrdp_font.c
@@ -65,6 +65,12 @@ static char w_char[] =
};
#endif
+// Unicode definitions
+#define UNICODE_WHITE_SQUARE 0x25a1
+
+// First character allocated in the 'struct xrdp_font.chars' array
+#define FIRST_CHAR ' '
+
/*****************************************************************************/
struct xrdp_font *
xrdp_font_create(struct xrdp_wm *wm)
@@ -74,8 +80,8 @@ xrdp_font_create(struct xrdp_wm *wm)
int fd;
int b;
int i;
- int index;
- int datasize;
+ unsigned int char_count;
+ unsigned int datasize; // Size of glyph data on disk
int file_size;
struct xrdp_font_char *f;
char file_path[256];
@@ -100,29 +106,67 @@ xrdp_font_create(struct xrdp_wm *wm)
}
self = (struct xrdp_font *)g_malloc(sizeof(struct xrdp_font), 1);
+ if (self == NULL)
+ {
+ log_message(LOG_LEVEL_ERROR, "xrdp_font_create: "
+ "Can't allocate memory for font");
+ return self;
+ }
self->wm = wm;
make_stream(s);
init_stream(s, file_size + 1024);
fd = g_file_open(file_path);
- if (fd != -1)
+ if (fd < 0)
+ {
+ log_message(LOG_LEVEL_ERROR,
+ "xrdp_font_create: Can't open %s - %s", file_path,
+ g_get_strerror());
+ g_free(self);
+ self = NULL;
+ }
+ else
{
b = g_file_read(fd, s->data, file_size + 1024);
g_file_close(fd);
- if (b > 0)
+ // Got at least a header?
+ if (b < (4 + 32 + 2 + 2 + 2 + 2 + 4))
+ {
+ log_message(LOG_LEVEL_ERROR,
+ "xrdp_font_create: Font %s is truncated", file_path);
+ g_free(self);
+ self = NULL;
+ }
+ else
{
s->end = s->data + b;
in_uint8s(s, 4);
in_uint8a(s, self->name, 32);
in_uint16_le(s, self->size);
in_uint16_le(s, self->style);
- in_uint8s(s, 8);
- index = 32;
+ in_uint8s(s, 4);
+ char_count = FIRST_CHAR;
- while (s_check_rem(s, 16))
+ while (!s_check_end(s))
{
- f = self->font_items + index;
+ if (!s_check_rem(s, 16))
+ {
+ log_message(LOG_LEVEL_WARNING,
+ "xrdp_font_create: "
+ "Can't parse header for character U+%X", char_count);
+ break;
+ }
+
+ if (char_count >= MAX_FONT_CHARS)
+ {
+ log_message(LOG_LEVEL_WARNING,
+ "xrdp_font_create: "
+ "Ignoring characters >= U+%x", MAX_FONT_CHARS);
+ break;
+ }
+
+ f = self->chars + char_count;
in_sint16_le(s, i);
f->width = i;
in_sint16_le(s, i);
@@ -141,7 +185,7 @@ xrdp_font_create(struct xrdp_wm *wm)
/* shouldn't happen */
log_message(LOG_LEVEL_ERROR,"error in xrdp_font_create, datasize wrong");
log_message(LOG_LEVEL_DEBUG,"width %d height %d datasize %d index %d",
- f->width, f->height, datasize, index);
+ f->width, f->height, datasize, char_count);
break;
}
@@ -155,7 +199,31 @@ xrdp_font_create(struct xrdp_wm *wm)
log_message(LOG_LEVEL_ERROR,"error in xrdp_font_create");
}
- index++;
+ ++char_count;
+ }
+
+ self->char_count = char_count;
+ if (char_count <= FIRST_CHAR)
+ {
+ /* We read no characters from the font */
+ xrdp_font_delete(self);
+ self = NULL;
+ }
+ else
+ {
+ // Find a default glyph
+ if (char_count > UNICODE_WHITE_SQUARE)
+ {
+ self->default_char = &self->chars[UNICODE_WHITE_SQUARE];
+ }
+ else if (char_count > '?')
+ {
+ self->default_char = &self->chars['?'];
+ }
+ else
+ {
+ self->default_char = &self->chars[FIRST_CHAR];
+ }
}
}
}
@@ -178,16 +246,16 @@ xrdp_font_create(struct xrdp_wm *wm)
void
xrdp_font_delete(struct xrdp_font *self)
{
- int i;
+ unsigned int i;
if (self == 0)
{
return;
}
- for (i = 0; i < NUM_FONTS; i++)
+ for (i = FIRST_CHAR; i < self->char_count; i++)
{
- g_free(self->font_items[i].data);
+ g_free(self->chars[i].data);
}
g_free(self);
diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c
index 97ae5cc3..fe952b53 100644
--- a/xrdp/xrdp_painter.c
+++ b/xrdp/xrdp_painter.c
@@ -464,7 +464,7 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
for (index = 0; index < len; index++)
{
- font_item = self->font->font_items + wstr[index];
+ font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
rv = rv + font_item->incby;
}
@@ -502,7 +502,7 @@ xrdp_painter_text_height(struct xrdp_painter *self, const char *text)
for (index = 0; index < len; index++)
{
- font_item = self->font->font_items + wstr[index];
+ font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
rv = MAX(rv, font_item->height);
}
@@ -879,7 +879,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
total_height = 0;
for (index = 0; index < len; index++)
{
- font_item = font->font_items + wstr[index];
+ font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
k = font_item->incby;
total_width += k;
total_height = MAX(total_height, font_item->height);
@@ -913,7 +913,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
draw_rect.bottom - draw_rect.top);
for (index = 0; index < len; index++)
{
- font_item = font->font_items + wstr[index];
+ font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
g_memset(&pat, 0, sizeof(pat));
pat.format = PT_FORMAT_c1;
pat.width = font_item->width;
@@ -955,7 +955,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
for (index = 0; index < len; index++)
{
- font_item = font->font_items + wstr[index];
+ font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
i = xrdp_cache_add_char(self->wm->cache, font_item);
f = HIWORD(i);
c = LOWORD(i);
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index b0c8b559..aebf891b 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -493,7 +493,7 @@ struct xrdp_bitmap
int crc16;
};
-#define NUM_FONTS 0x4e00
+#define MAX_FONT_CHARS 0x4e00
#define DEFAULT_FONT_NAME "sans-10.fv1"
#define DEFAULT_ELEMENT_TOP 35
@@ -512,11 +512,15 @@ struct xrdp_bitmap
/* font */
struct xrdp_font
{
- struct xrdp_wm* wm;
- struct xrdp_font_char font_items[NUM_FONTS];
- char name[32];
- int size;
- int style;
+ struct xrdp_wm *wm;
+ // Font characters, accessed by Unicode codepoint. The first 32
+ // entries are unused.
+ struct xrdp_font_char chars[MAX_FONT_CHARS];
+ unsigned int char_count; // # elements in above array
+ struct xrdp_font_char *default_char; // Pointer into above array
+ char name[32];
+ int size;
+ int style;
};
/* module */
--
2.42.1