Merge pull request #4871 from akallabeth/drdynvc_checks

Fix for #4866: Added additional length checks
This commit is contained in:
Martin Fleisz 2018-09-21 13:01:58 +02:00 committed by GitHub
commit 205c612820
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -639,8 +639,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
if (channel->dvc_data) if (channel->dvc_data)
{ {
/* Fragmented data */ /* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity( if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data))
channel->dvc_data))
{ {
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
Stream_Release(channel->dvc_data); Stream_Release(channel->dvc_data);
@ -648,7 +647,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
} }
Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize); Stream_Copy(data, channel->dvc_data, dataSize);
if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length) if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length)
{ {
@ -880,6 +879,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
if (!drdynvc) if (!drdynvc)
return CHANNEL_RC_BAD_INIT_HANDLE; return CHANNEL_RC_BAD_INIT_HANDLE;
if (Stream_GetRemainingLength(s) < 3)
return ERROR_INVALID_DATA;
WLog_Print(drdynvc->log, WLOG_TRACE, "capability_request Sp=%d cbChId=%d", Sp, cbChId); WLog_Print(drdynvc->log, WLOG_TRACE, "capability_request Sp=%d cbChId=%d", Sp, cbChId);
Stream_Seek(s, 1); /* pad */ Stream_Seek(s, 1); /* pad */
Stream_Read_UINT16(s, drdynvc->version); Stream_Read_UINT16(s, drdynvc->version);
@ -889,6 +891,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
*/ */
if ((drdynvc->version == 2) || (drdynvc->version == 3)) if ((drdynvc->version == 2) || (drdynvc->version == 3))
{ {
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, drdynvc->PriorityCharge0); Stream_Read_UINT16(s, drdynvc->PriorityCharge0);
Stream_Read_UINT16(s, drdynvc->PriorityCharge1); Stream_Read_UINT16(s, drdynvc->PriorityCharge1);
Stream_Read_UINT16(s, drdynvc->PriorityCharge2); Stream_Read_UINT16(s, drdynvc->PriorityCharge2);
@ -900,6 +905,21 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
return status; return status;
} }
static UINT32 drdynvc_cblen_to_bytes(int cbLen)
{
switch (cbLen)
{
case 0:
return 1;
case 1:
return 2;
default:
return 4;
}
}
static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen) static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
{ {
UINT32 val; UINT32 val;
@ -935,6 +955,8 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
UINT32 ChannelId; UINT32 ChannelId;
wStream* data_out; wStream* data_out;
UINT channel_status; UINT channel_status;
char* name;
size_t length;
if (!drdynvc) if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE; return CHANNEL_RC_BAD_CHANNEL_HANDLE;
@ -957,13 +979,20 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
drdynvc->state = DRDYNVC_STATE_READY; drdynvc->state = DRDYNVC_STATE_READY;
} }
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
return ERROR_INVALID_DATA;
ChannelId = drdynvc_read_variable_uint(s, cbChId); ChannelId = drdynvc_read_variable_uint(s, cbChId);
pos = Stream_GetPosition(s); pos = Stream_GetPosition(s);
name = Stream_Pointer(s);
length = Stream_GetRemainingLength(s);
if (strnlen(name, length) >= length)
return ERROR_INVALID_DATA;
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s", WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s",
ChannelId, ChannelId, name);
Stream_Pointer(s)); channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name);
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId,
(char*) Stream_Pointer(s));
data_out = Stream_New(NULL, pos + 4); data_out = Stream_New(NULL, pos + 4);
if (!data_out) if (!data_out)
@ -1024,6 +1053,10 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
UINT status; UINT status;
UINT32 Length; UINT32 Length;
UINT32 ChannelId; UINT32 ChannelId;
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId) + drdynvc_cblen_to_bytes(Sp))
return ERROR_INVALID_DATA;
ChannelId = drdynvc_read_variable_uint(s, cbChId); ChannelId = drdynvc_read_variable_uint(s, cbChId);
Length = drdynvc_read_variable_uint(s, Sp); Length = drdynvc_read_variable_uint(s, Sp);
WLog_Print(drdynvc->log, WLOG_DEBUG, WLog_Print(drdynvc->log, WLOG_DEBUG,
@ -1047,6 +1080,10 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
wStream* s) wStream* s)
{ {
UINT32 ChannelId; UINT32 ChannelId;
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
return ERROR_INVALID_DATA;
ChannelId = drdynvc_read_variable_uint(s, cbChId); ChannelId = drdynvc_read_variable_uint(s, cbChId);
WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp, WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp,
cbChId, cbChId,
@ -1066,6 +1103,10 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
UINT error; UINT error;
UINT32 ChannelId; UINT32 ChannelId;
wStream* data_out; wStream* data_out;
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
return ERROR_INVALID_DATA;
ChannelId = drdynvc_read_variable_uint(s, cbChId); ChannelId = drdynvc_read_variable_uint(s, cbChId);
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"",
Sp, Sp,
@ -1108,6 +1149,10 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
int Cmd; int Cmd;
int Sp; int Sp;
int cbChId; int cbChId;
if (Stream_GetRemainingLength(s) < 1)
return ERROR_INVALID_DATA;
Stream_Read_UINT8(s, value); Stream_Read_UINT8(s, value);
Cmd = (value & 0xf0) >> 4; Cmd = (value & 0xf0) >> 4;
Sp = (value & 0x0c) >> 2; Sp = (value & 0x0c) >> 2;
@ -1166,7 +1211,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
{ {
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
Stream_Free(drdynvc->data_in, TRUE); Stream_Free(drdynvc->data_in, TRUE);