Merge pull request #6435 from akallabeth/drdynvc_fix_channel_close

Fixed double free on channel close in channel write.
This commit is contained in:
Martin Fleisz 2020-08-24 09:39:27 +02:00 committed by GitHub
commit 68c7bcc650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 20 deletions

View File

@ -30,10 +30,12 @@
#define TAG CHANNELS_TAG("drdynvc.client")
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU);
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr);
static void dvcman_channel_free(void* channel);
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data,
UINT32 dataSize);
UINT32 dataSize, BOOL* close);
static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s);
static void dvcman_wtslistener_free(DVCMAN_LISTENER* listener)
@ -446,6 +448,7 @@ fail:
static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, const BYTE* pBuffer,
void* pReserved)
{
BOOL close = FALSE;
UINT status;
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel;
@ -454,8 +457,12 @@ static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, con
return CHANNEL_RC_BAD_CHANNEL;
EnterCriticalSection(&(channel->lock));
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
status =
drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize, &close);
LeaveCriticalSection(&(channel->lock));
/* Close delayed, it removes the channel struct */
if (close)
dvcman_close_channel(channel->dvcman->drdynvc->channel_mgr, channel->channel_id, TRUE);
return status;
}
@ -602,8 +609,8 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManage
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU)
UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU)
{
DVCMAN_CHANNEL* channel;
UINT error = CHANNEL_RC_OK;
@ -802,7 +809,7 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
* @return 0 on success, otherwise a Win32 error code
*/
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data,
UINT32 dataSize)
UINT32 dataSize, BOOL* close)
{
wStream* data_out;
size_t pos;
@ -833,7 +840,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
if (dataSize == 0)
{
dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE);
*close = TRUE;
Stream_Release(data_out);
}
else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos)

View File

@ -242,7 +242,7 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c
Stream_Read_UINT32(s, OutputBufferSize);
Stream_Read_UINT32(s, RequestId);
InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize);
out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
if (!out)
return ERROR_OUTOFMEMORY;
@ -266,7 +266,11 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c
if (success)
{
Stream_Seek(out, OutputBufferSize);
if (!Stream_SafeSeek(out, OutputBufferSize))
{
Stream_Free(out, TRUE);
return ERROR_INVALID_DATA;
}
if (pdev->isExist(pdev) == 0)
Stream_Write_UINT32(out, 0);

View File

@ -81,6 +81,8 @@ struct _ASYNC_TRANSFER_USER_DATA
#endif
};
static void request_free(void* value);
static struct libusb_transfer* list_contains(wArrayList* list, UINT32 streamID)
{
int x, count;
@ -1222,7 +1224,6 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
return -1;
}
iso_transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
/** process URB_FUNCTION_IOSCH_TRANSFER */
libusb_fill_iso_transfer(iso_transfer, pdev->libusb_handle, EndpointAddress,
Stream_Pointer(user_data->data), BufferSize, NumberOfPackets,
@ -1235,8 +1236,7 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
WLog_Print(urbdrc->log, WLOG_WARN,
"Failed to queue iso transfer, streamID %08" PRIx32 " already in use!",
streamID);
async_transfer_user_data_free(user_data);
libusb_free_transfer(iso_transfer);
request_free(iso_transfer);
return -1;
}
return libusb_submit_transfer(iso_transfer);
@ -1298,7 +1298,6 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
async_transfer_user_data_free(user_data);
return -1;
}
transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
ep_desc = func_get_ep_desc(pdev->LibusbConfig, pdev->MsConfig, EndpointAddress);
@ -1306,8 +1305,7 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
{
WLog_Print(urbdrc->log, WLOG_ERROR, "func_get_ep_desc: endpoint 0x%" PRIx32 " not found",
EndpointAddress);
libusb_free_transfer(transfer);
async_transfer_user_data_free(user_data);
request_free(transfer);
return -1;
}
@ -1338,8 +1336,7 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
"urb_bulk_or_interrupt_transfer:"
" other transfer type 0x%" PRIX32 "",
transfer_type);
async_transfer_user_data_free(user_data);
libusb_free_transfer(transfer);
request_free(transfer);
return -1;
}
@ -1349,8 +1346,7 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
{
WLog_Print(urbdrc->log, WLOG_WARN,
"Failed to queue transfer, streamID %08" PRIx32 " already in use!", streamID);
async_transfer_user_data_free(user_data);
libusb_free_transfer(transfer);
request_free(transfer);
return -1;
}
return libusb_submit_transfer(transfer);
@ -1465,6 +1461,7 @@ static void udev_free(IUDEVICE* idev)
urbdrc = udev->urbdrc;
libusb_udev_cancel_all_transfer_request(&udev->iface);
if (udev->libusb_handle)
{
rc = libusb_reset_device(udev->libusb_handle);
@ -1613,6 +1610,7 @@ static void request_free(void* value)
user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
async_transfer_user_data_free(user_data);
transfer->user_data = NULL;
libusb_free_transfer(transfer);
}
static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUSB_DEVICE* device,
@ -1725,9 +1723,9 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUS
goto fail;
// deb_config_msg(pdev->libusb_dev, config_temp, devDescriptor->bNumConfigurations);
return (IUDEVICE*)pdev;
return &pdev->iface;
fail:
pdev->iface.free((IUDEVICE*)pdev);
pdev->iface.free(&pdev->iface);
return NULL;
}