Address memory allocation overflow security issues

This commit is contained in:
matt335672 2020-04-18 16:56:53 +01:00
parent 1c4e14415d
commit 7ef01f7b0c
3 changed files with 71 additions and 7 deletions

View File

@ -39,6 +39,9 @@
#include "xrdp_sockets.h" #include "xrdp_sockets.h"
#include "audin.h" #include "audin.h"
#define CHANNEL_NAME_BYTES 7
#define MAX_PATH 260
static struct trans *g_lis_trans = 0; static struct trans *g_lis_trans = 0;
static struct trans *g_con_trans = 0; static struct trans *g_con_trans = 0;
static struct trans *g_api_lis_trans = 0; static struct trans *g_api_lis_trans = 0;
@ -1042,7 +1045,7 @@ my_api_trans_data_in(struct trans *trans)
int rv; int rv;
int bytes; int bytes;
int ver; int ver;
int channel_name_bytes; unsigned int channel_name_bytes;
struct chansrv_drdynvc_procs procs; struct chansrv_drdynvc_procs procs;
char *chan_name; char *chan_name;
@ -1067,6 +1070,13 @@ my_api_trans_data_in(struct trans *trans)
rv = 1; rv = 1;
in_uint32_le(s, channel_name_bytes); in_uint32_le(s, channel_name_bytes);
//g_writeln("my_api_trans_data_in: channel_name_bytes %d", channel_name_bytes); //g_writeln("my_api_trans_data_in: channel_name_bytes %d", channel_name_bytes);
/*
* Name is limited to CHANNEL_NAME_BYTES for an SVC, or MAX_PATH
* bytes for a DVC */
if (channel_name_bytes > MAX(CHANNEL_NAME_BYTES, MAX_PATH))
{
return 1;
}
chan_name = g_new0(char, channel_name_bytes + 1); chan_name = g_new0(char, channel_name_bytes + 1);
if (chan_name == NULL) if (chan_name == NULL)
{ {

View File

@ -586,9 +586,18 @@ int
scard_process_list_readers(struct trans *con, struct stream *in_s) scard_process_list_readers(struct trans *con, struct stream *in_s)
{ {
int hContext; int hContext;
int bytes_groups; unsigned int bytes_groups;
int cchReaders; int cchReaders;
char *groups; /*
* At the time of writing, the groups strings which can be sent
* over this interface are all small:-
*
* "SCard$AllReaders", "SCard$DefaultReaders", "SCard$LocalReaders" and
* "SCard$SystemReaders"
*
* We'll allow a bit extra in case the interface changes
*/
char groups[256];
struct pcsc_uds_client *uds_client; struct pcsc_uds_client *uds_client;
struct pcsc_context *lcontext; struct pcsc_context *lcontext;
struct pcsc_list_readers *pcscListReaders; struct pcsc_list_readers *pcscListReaders;
@ -597,8 +606,14 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
uds_client = (struct pcsc_uds_client *) (con->callback_data); uds_client = (struct pcsc_uds_client *) (con->callback_data);
in_uint32_le(in_s, hContext); in_uint32_le(in_s, hContext);
in_uint32_le(in_s, bytes_groups); in_uint32_le(in_s, bytes_groups);
groups = (char *) g_malloc(bytes_groups + 1, 1); if (bytes_groups > (sizeof(groups) - 1))
{
LLOGLN(0, ("scard_process_list_readers: Unreasonable string length %u",
bytes_groups));
return 1;
}
in_uint8a(in_s, groups, bytes_groups); in_uint8a(in_s, groups, bytes_groups);
groups[bytes_groups] = '\0';
in_uint32_le(in_s, cchReaders); in_uint32_le(in_s, cchReaders);
LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d", LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d",
hContext, cchReaders)); hContext, cchReaders));
@ -615,7 +630,6 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
pcscListReaders->cchReaders = cchReaders; pcscListReaders->cchReaders = cchReaders;
scard_send_list_readers(pcscListReaders, lcontext->context, scard_send_list_readers(pcscListReaders, lcontext->context,
lcontext->context_bytes, groups, cchReaders, 1); lcontext->context_bytes, groups, cchReaders, 1);
g_free(groups);
return 0; return 0;
} }

View File

@ -25,6 +25,8 @@
#include <config_ac.h> #include <config_ac.h>
#endif #endif
#include <limits.h>
#include "xrdp.h" #include "xrdp.h"
#include "log.h" #include "log.h"
@ -93,6 +95,30 @@ static const unsigned int g_crc_table[256] =
(in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8) (in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8)
#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ 0xFFFFFFFF) #define CRC_END(in_crc) (in_crc) = ((in_crc) ^ 0xFFFFFFFF)
/*****************************************************************************/
/* Allocate bitmap for specified dimensions, checking for int overflow */
static char *
alloc_bitmap_data(int width, int height, int Bpp)
{
char *result = NULL;
if (width > 0 && height > 0 && Bpp > 0)
{
int len = width;
/* g_malloc() currently takes an 'int' size */
if (len < INT_MAX / height)
{
len *= height;
if (len < INT_MAX / Bpp)
{
len *= Bpp;
result = (char *)malloc(len);
}
}
}
return result;
}
/*****************************************************************************/ /*****************************************************************************/
struct xrdp_bitmap * struct xrdp_bitmap *
xrdp_bitmap_create(int width, int height, int bpp, xrdp_bitmap_create(int width, int height, int bpp,
@ -123,14 +149,28 @@ xrdp_bitmap_create(int width, int height, int bpp,
if (self->type == WND_TYPE_BITMAP || self->type == WND_TYPE_IMAGE) if (self->type == WND_TYPE_BITMAP || self->type == WND_TYPE_IMAGE)
{ {
self->data = (char *)g_malloc(width * height * Bpp, 0); self->data = alloc_bitmap_data(width, height, Bpp);
if (self->data == NULL)
{
LLOGLN(0, ("xrdp_bitmap_create: size overflow %dx%dx%d",
width, height, Bpp));
g_free(self);
return NULL;
}
} }
#if defined(XRDP_PAINTER) #if defined(XRDP_PAINTER)
if (self->type == WND_TYPE_SCREEN) /* noorders */ if (self->type == WND_TYPE_SCREEN) /* noorders */
{ {
LLOGLN(0, ("xrdp_bitmap_create: noorders")); LLOGLN(0, ("xrdp_bitmap_create: noorders"));
self->data = (char *) g_malloc(width * height * Bpp, 0); self->data = alloc_bitmap_data(width, height, Bpp);
if (self->data == NULL)
{
LLOGLN(0, ("xrdp_bitmap_create: size overflow %dx%dx%d",
width, height, Bpp));
g_free(self);
return NULL;
}
} }
#endif #endif