[MSAFD] Fix WSPSelect heap corruption and don't repeat sockets if they are in different fd_sets.

CORE-12324

svn path=/trunk/; revision=73241
This commit is contained in:
Peter Hater 2016-11-17 12:57:32 +00:00
parent 7408b63c91
commit 9cbc4837b7

View file

@ -1045,13 +1045,34 @@ WSPSelect(IN int nfds,
PSOCKET_INFORMATION Socket; PSOCKET_INFORMATION Socket;
SOCKET Handle; SOCKET Handle;
ULONG Events; ULONG Events;
fd_set selectfds;
/* Find out how many sockets we have, and how large the buffer needs /* Find out how many sockets we have, and how large the buffer needs
* to be */ * to be */
FD_ZERO(&selectfds);
if (readfds != NULL)
{
for (i = 0; i < readfds->fd_count; i++)
{
FD_SET(readfds->fd_array[i], &selectfds);
}
}
if (writefds != NULL)
{
for (i = 0; i < writefds->fd_count; i++)
{
FD_SET(writefds->fd_array[i], &selectfds);
}
}
if (exceptfds != NULL)
{
for (i = 0; i < exceptfds->fd_count; i++)
{
FD_SET(exceptfds->fd_array[i], &selectfds);
}
}
HandleCount = ( readfds ? readfds->fd_count : 0 ) + HandleCount = selectfds.fd_count;
( writefds ? writefds->fd_count : 0 ) +
( exceptfds ? exceptfds->fd_count : 0 );
if ( HandleCount == 0 ) if ( HandleCount == 0 )
{ {
@ -1082,7 +1103,7 @@ WSPSelect(IN int nfds,
if (Timeout.QuadPart > 0) if (Timeout.QuadPart > 0)
{ {
if (lpErrno) *lpErrno = WSAEINVAL; if (lpErrno) *lpErrno = WSAEINVAL;
return SOCKET_ERROR; return SOCKET_ERROR;
} }
TRACE("Timeout: Orig %d.%06d kernel %d\n", TRACE("Timeout: Orig %d.%06d kernel %d\n",
timeout->tv_sec, timeout->tv_usec, timeout->tv_sec, timeout->tv_usec,
@ -1123,9 +1144,26 @@ WSPSelect(IN int nfds,
PollInfo->Exclusive = FALSE; PollInfo->Exclusive = FALSE;
PollInfo->Timeout = Timeout; PollInfo->Timeout = Timeout;
for (i = 0; i < selectfds.fd_count; i++)
{
PollInfo->Handles[i].Handle = selectfds.fd_array[i];
}
if (readfds != NULL) { if (readfds != NULL) {
for (i = 0; i < readfds->fd_count; i++, j++) for (i = 0; i < readfds->fd_count; i++)
{ {
for (j = 0; j < HandleCount; j++)
{
if (PollInfo->Handles[j].Handle == readfds->fd_array[i])
break;
}
if (j >= HandleCount)
{
ERR("Error while counting readfds %ld > %ld\n", j, HandleCount);
if (lpErrno) *lpErrno = WSAEFAULT;
HeapFree(GlobalHeap, 0, PollBuffer);
NtClose(SockEvent);
return SOCKET_ERROR;
}
Socket = GetSocketStructure(readfds->fd_array[i]); Socket = GetSocketStructure(readfds->fd_array[i]);
if (!Socket) if (!Socket)
{ {
@ -1135,20 +1173,32 @@ WSPSelect(IN int nfds,
NtClose(SockEvent); NtClose(SockEvent);
return SOCKET_ERROR; return SOCKET_ERROR;
} }
PollInfo->Handles[j].Handle = readfds->fd_array[i]; PollInfo->Handles[j].Events |= AFD_EVENT_RECEIVE |
PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE | AFD_EVENT_DISCONNECT |
AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT |
AFD_EVENT_ABORT | AFD_EVENT_CLOSE |
AFD_EVENT_CLOSE | AFD_EVENT_ACCEPT;
AFD_EVENT_ACCEPT; //if (Socket->SharedData->OobInline != 0)
if (Socket->SharedData->OobInline != 0) // PollInfo->Handles[j].Events |= AFD_EVENT_OOB_RECEIVE;
PollInfo->Handles[j].Events |= AFD_EVENT_OOB_RECEIVE;
} }
} }
if (writefds != NULL) if (writefds != NULL)
{ {
for (i = 0; i < writefds->fd_count; i++, j++) for (i = 0; i < writefds->fd_count; i++)
{ {
for (j = 0; j < HandleCount; j++)
{
if (PollInfo->Handles[j].Handle == writefds->fd_array[i])
break;
}
if (j >= HandleCount)
{
ERR("Error while counting writefds %ld > %ld\n", j, HandleCount);
if (lpErrno) *lpErrno = WSAEFAULT;
HeapFree(GlobalHeap, 0, PollBuffer);
NtClose(SockEvent);
return SOCKET_ERROR;
}
Socket = GetSocketStructure(writefds->fd_array[i]); Socket = GetSocketStructure(writefds->fd_array[i]);
if (!Socket) if (!Socket)
{ {
@ -1159,15 +1209,28 @@ WSPSelect(IN int nfds,
return SOCKET_ERROR; return SOCKET_ERROR;
} }
PollInfo->Handles[j].Handle = writefds->fd_array[i]; PollInfo->Handles[j].Handle = writefds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_SEND; PollInfo->Handles[j].Events |= AFD_EVENT_SEND;
if (Socket->SharedData->NonBlocking != 0) if (Socket->SharedData->NonBlocking != 0)
PollInfo->Handles[j].Events |= AFD_EVENT_CONNECT; PollInfo->Handles[j].Events |= AFD_EVENT_CONNECT;
} }
} }
if (exceptfds != NULL) if (exceptfds != NULL)
{ {
for (i = 0; i < exceptfds->fd_count; i++, j++) for (i = 0; i < exceptfds->fd_count; i++)
{ {
for (j = 0; j < HandleCount; j++)
{
if (PollInfo->Handles[j].Handle == exceptfds->fd_array[i])
break;
}
if (j > HandleCount)
{
ERR("Error while counting exceptfds %ld > %ld\n", j, HandleCount);
if (lpErrno) *lpErrno = WSAEFAULT;
HeapFree(GlobalHeap, 0, PollBuffer);
NtClose(SockEvent);
return SOCKET_ERROR;
}
Socket = GetSocketStructure(exceptfds->fd_array[i]); Socket = GetSocketStructure(exceptfds->fd_array[i]);
if (!Socket) if (!Socket)
{ {
@ -1178,20 +1241,14 @@ WSPSelect(IN int nfds,
return SOCKET_ERROR; return SOCKET_ERROR;
} }
PollInfo->Handles[j].Handle = exceptfds->fd_array[i]; PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
PollInfo->Handles[j].Events = 0;
if (Socket->SharedData->OobInline == 0) if (Socket->SharedData->OobInline == 0)
PollInfo->Handles[j].Events |= AFD_EVENT_OOB_RECEIVE; PollInfo->Handles[j].Events |= AFD_EVENT_OOB_RECEIVE;
if (Socket->SharedData->NonBlocking != 0) if (Socket->SharedData->NonBlocking != 0)
PollInfo->Handles[j].Events |= AFD_EVENT_CONNECT_FAIL; PollInfo->Handles[j].Events |= AFD_EVENT_CONNECT_FAIL;
if (PollInfo->Handles[j].Events == 0)
{
TRACE("No events can be checked for exceptfds %d. It is nonblocking and OOB line is disabled. Skipping it.", exceptfds->fd_array[i]);
j--;
}
} }
} }
PollInfo->HandleCount = j; PollInfo->HandleCount = HandleCount;
PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE); PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
/* Send IOCTL */ /* Send IOCTL */