Fixed oob read in irp_write and similar

This commit is contained in:
akallabeth 2020-04-15 17:21:46 +02:00
parent 795842f409
commit 6b485b146a
6 changed files with 48 additions and 18 deletions

View File

@ -331,6 +331,7 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
DRIVE_FILE* file;
UINT32 Length;
UINT64 Offset;
void* ptr;
if (!drive || !irp || !irp->input || !irp->output || !irp->Complete)
return ERROR_INVALID_PARAMETER;
@ -341,6 +342,9 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */
ptr = Stream_Pointer(irp->input);
if (!Stream_SafeSeek(irp->input, Length))
return ERROR_INVALID_DATA;
file = drive_get_file_by_id(drive, irp->FileId);
if (!file)
@ -353,7 +357,7 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
irp->IoStatus = drive_map_windows_err(GetLastError());
Length = 0;
}
else if (!drive_file_write(file, Stream_Pointer(irp->input), Length))
else if (!drive_file_write(file, ptr, Length))
{
irp->IoStatus = drive_map_windows_err(GetLastError());
Length = 0;

View File

@ -478,10 +478,16 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
UINT64 Offset;
rdpPrintJob* printjob = NULL;
UINT error = CHANNEL_RC_OK;
void* ptr;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */
ptr = Stream_Pointer(irp->input);
if (!Stream_SafeSeek(irp->input, Length))
return ERROR_INVALID_DATA;
if (printer_dev->printer)
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
@ -492,7 +498,7 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
}
else
{
error = printjob->Write(printjob, Stream_Pointer(irp->input), Length);
error = printjob->Write(printjob, ptr, Length);
}
if (error)

View File

@ -445,6 +445,9 @@ static UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
UINT16 eventId;
UINT32 pduLength;
UINT error;
if (Stream_GetRemainingLength(s) < 6)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */
Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */
#ifdef WITH_DEBUG_RDPEI

View File

@ -142,10 +142,9 @@ static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
Stream_Seek_UINT32(irp->input); /* CreateOptions (4 bytes) */
Stream_Read_UINT32(irp->input, PathLength); /* PathLength (4 bytes) */
if (Stream_GetRemainingLength(irp->input) < PathLength)
if (!Stream_SafeSeek(irp->input, PathLength)) /* Path (variable) */
return ERROR_INVALID_DATA;
Stream_Seek(irp->input, PathLength); /* Path (variable) */
assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */
#ifndef _WIN32
/* Windows 2012 server sends on a first call :
@ -300,6 +299,7 @@ static UINT serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
{
UINT32 Length;
UINT64 Offset;
void* ptr;
DWORD nbWritten = 0;
if (Stream_GetRemainingLength(irp->input) < 32)
@ -307,7 +307,9 @@ static UINT serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */
Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
if (!Stream_SafeSeek(irp->input, 20)) /* Padding (20 bytes) */
return ERROR_INVALID_DATA;
/* MS-RDPESP 3.2.5.1.5: The Offset field is ignored
* assert(Offset == 0);
*
@ -317,8 +319,11 @@ static UINT serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
WLog_Print(serial->log, WLOG_DEBUG, "writing %" PRIu32 " bytes to %s", Length,
serial->device.name);
ptr = Stream_Pointer(irp->input);
if (!Stream_SafeSeek(irp->input, Length))
return ERROR_INVALID_DATA;
/* FIXME: CommWriteFile to be replaced by WriteFile */
if (CommWriteFile(serial->hComm, Stream_Pointer(irp->input), Length, &nbWritten, NULL))
if (CommWriteFile(serial->hComm, ptr, Length, &nbWritten, NULL))
{
irp->IoStatus = STATUS_SUCCESS;
}

View File

@ -304,7 +304,8 @@ static wStream* rdg_receive_packet(rdpRdg* rdg)
Stream_Seek(s, 4);
Stream_Read_UINT32(s, packetLength);
if ((packetLength > INT_MAX) || !Stream_EnsureCapacity(s, packetLength))
if ((packetLength > INT_MAX) || !Stream_EnsureCapacity(s, packetLength) ||
(packetLength < header))
{
Stream_Free(s, TRUE);
return NULL;

View File

@ -91,9 +91,9 @@ static BOOL nego_security_connect(rdpNego* nego);
static BOOL nego_send_preconnection_pdu(rdpNego* nego);
static BOOL nego_recv_response(rdpNego* nego);
static void nego_send(rdpNego* nego);
static void nego_process_negotiation_request(rdpNego* nego, wStream* s);
static void nego_process_negotiation_response(rdpNego* nego, wStream* s);
static void nego_process_negotiation_failure(rdpNego* nego, wStream* s);
static BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s);
static BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s);
static BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s);
/**
* Negotiate protocol security and connect.
@ -618,7 +618,8 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
switch (type)
{
case TYPE_RDP_NEG_RSP:
nego_process_negotiation_response(nego, s);
if (!nego_process_negotiation_response(nego, s))
return -1;
WLog_DBG(TAG, "selected_protocol: %" PRIu32 "", nego->SelectedProtocol);
/* enhanced security selected ? */
@ -645,7 +646,8 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
break;
case TYPE_RDP_NEG_FAILURE:
nego_process_negotiation_failure(nego, s);
if (!nego_process_negotiation_failure(nego, s))
return -1;
break;
}
}
@ -795,7 +797,8 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
return FALSE;
}
nego_process_negotiation_request(nego, s);
if (!nego_process_negotiation_request(nego, s))
return FALSE;
}
return tpkt_ensure_stream_consumed(s, length);
@ -918,15 +921,19 @@ fail:
* @param s
*/
void nego_process_negotiation_request(rdpNego* nego, wStream* s)
BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
{
BYTE flags;
UINT16 length;
if (Stream_GetRemainingLength(s) < 7)
return FALSE;
Stream_Read_UINT8(s, flags);
Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->RequestedProtocols);
WLog_DBG(TAG, "RDP_NEG_REQ: RequestedProtocol: 0x%08" PRIX32 "", nego->RequestedProtocols);
nego->state = NEGO_STATE_FINAL;
return TRUE;
}
/**
@ -935,7 +942,7 @@ void nego_process_negotiation_request(rdpNego* nego, wStream* s)
* @param s
*/
void nego_process_negotiation_response(rdpNego* nego, wStream* s)
BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s)
{
UINT16 length;
WLog_DBG(TAG, "RDP_NEG_RSP");
@ -944,13 +951,14 @@ void nego_process_negotiation_response(rdpNego* nego, wStream* s)
{
WLog_ERR(TAG, "Invalid RDP_NEG_RSP");
nego->state = NEGO_STATE_FAIL;
return;
return FALSE;
}
Stream_Read_UINT8(s, nego->flags);
Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->SelectedProtocol);
nego->state = NEGO_STATE_FINAL;
return TRUE;
}
/**
@ -959,12 +967,14 @@ void nego_process_negotiation_response(rdpNego* nego, wStream* s)
* @param s
*/
void nego_process_negotiation_failure(rdpNego* nego, wStream* s)
BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
{
BYTE flags;
UINT16 length;
UINT32 failureCode;
WLog_DBG(TAG, "RDP_NEG_FAILURE");
if (Stream_GetRemainingLength(s) < 7)
return FALSE;
Stream_Read_UINT8(s, flags);
Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, failureCode);
@ -999,6 +1009,7 @@ void nego_process_negotiation_failure(rdpNego* nego, wStream* s)
}
nego->state = NEGO_STATE_FAIL;
return TRUE;
}
/**