Author: jimtabor
Date: Mon Feb 16 03:16:01 2015
New Revision: 66309
URL: http://svn.reactos.org/svn/reactos?rev=66309&view=rev
Log:
[NtUser]
- This fixes use after free linking in the message system. See CORE-9173. Dedicated to Thomas Faber.
Modified:
trunk/reactos/win32ss/user/ntuser/msgqueue.c
Modified: trunk/reactos/win32ss/user/ntuser/msgqueue.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/msgque…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/msgqueue.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/msgqueue.c [iso-8859-1] Mon Feb 16 03:16:01 2015
@@ -789,8 +789,7 @@
/* insert it to the list of messages that are currently dispatched by this
message queue */
- InsertTailList(&pti->LocalDispatchingMessagesHead,
- &Message->ListEntry);
+ InsertTailList(&pti->LocalDispatchingMessagesHead, &Message->ListEntry);
ClearMsgBitsMask(pti, Message->QS_Flags);
@@ -866,7 +865,7 @@
}
/* remove the message from the dispatching list if needed, so lock the sender's message queue */
- if (Message->ptiSender)
+ if (Message->ptiSender && !(Message->ptiSender->TIF_flags & TIF_INCLEANUP))
{
if (Message->DispatchingListEntry.Flink != NULL)
{
@@ -953,8 +952,8 @@
ListHead = &pti->SentMessagesListHead;
while (CurrentEntry != ListHead)
{
- SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- ListEntry);
+ SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
+
if(SentMessage->Msg.hwnd == Window->head.h)
{
TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
@@ -1187,6 +1186,7 @@
Message->CompletionEvent = NULL;
Message->Result = NULL;
RemoveEntryList(&Message->ListEntry);
+ RemoveEntryList(&Message->DispatchingListEntry);
ClearMsgBitsMask(ptirec, Message->QS_Flags);
ExFreePoolWithTag(Message, TAG_USRMSG);
break;
@@ -1194,30 +1194,8 @@
Entry = Entry->Flink;
}
- /* Remove from the local dispatching list so the other thread knows,
- it can't pass a result and it must not set the completion event anymore */
- Entry = pti->DispatchingMessagesHead.Flink;
- while (Entry != &pti->DispatchingMessagesHead)
- {
- if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
- == Message)
- {
- /* We can access Message here, it's secure because the sender's message is locked
- and the message has definitely not yet been destroyed, otherwise it would
- have been removed from this list by the dispatching routine right after
- dispatching the message */
- Message->CompletionEvent = NULL;
- Message->Result = NULL;
- RemoveEntryList(&Message->DispatchingListEntry);
- Message->DispatchingListEntry.Flink = NULL;
- break;
- }
- Entry = Entry->Flink;
- }
-
TRACE("MsqSendMessage (blocked) timed out 1 Status %p\n",WaitStatus);
-
- }
+ }
// Receiving thread passed on and left us hanging with issues still pending.
if ( WaitStatus == STATUS_WAIT_1 )
{
@@ -1272,29 +1250,9 @@
Message->CompletionEvent = NULL;
Message->Result = NULL;
RemoveEntryList(&Message->ListEntry);
+ RemoveEntryList(&Message->DispatchingListEntry);
ClearMsgBitsMask(ptirec, Message->QS_Flags);
ExFreePoolWithTag(Message, TAG_USRMSG);
- break;
- }
- Entry = Entry->Flink;
- }
-
- /* Remove from the local dispatching list so the other thread knows,
- it can't pass a result and it must not set the completion event anymore */
- Entry = pti->DispatchingMessagesHead.Flink;
- while (Entry != &pti->DispatchingMessagesHead)
- {
- if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
- == Message)
- {
- /* We can access Message here, it's secure because the sender's message is locked
- and the message has definitely not yet been destroyed, otherwise it would
- have been removed from this list by the dispatching routine right after
- dispatching the message */
- Message->CompletionEvent = NULL;
- Message->Result = NULL;
- RemoveEntryList(&Message->DispatchingListEntry);
- Message->DispatchingListEntry.Flink = NULL;
break;
}
Entry = Entry->Flink;
@@ -1375,12 +1333,7 @@
MessageQueue = pti->MessageQueue;
- if (dwQEvent)
- {
- ERR("Post Msg; System Qeued Event Message!\n");
- InsertHeadList(&pti->PostedMessagesListHead, &Message->ListEntry);
- }
- else if (!HardwareMessage)
+ if (!HardwareMessage)
{
InsertTailList(&pti->PostedMessagesListHead, &Message->ListEntry);
}
@@ -2122,8 +2075,7 @@
while (!IsListEmpty(&pti->PostedMessagesListHead))
{
CurrentEntry = RemoveHeadList(&pti->PostedMessagesListHead);
- CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
- ListEntry);
+ CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
MsqDestroyMessage(CurrentMessage);
}
@@ -2131,8 +2083,7 @@
while (!IsListEmpty(&pti->SentMessagesListHead))
{
CurrentEntry = RemoveHeadList(&pti->SentMessagesListHead);
- CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- ListEntry);
+ CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
/* Only if the message has a sender was the message in the DispatchingList */
@@ -2163,8 +2114,7 @@
while (!IsListEmpty(&pti->LocalDispatchingMessagesHead))
{
CurrentEntry = RemoveHeadList(&pti->LocalDispatchingMessagesHead);
- CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- ListEntry);
+ CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
/* remove the message from the dispatching list */
if(CurrentSentMessage->DispatchingListEntry.Flink != NULL)
@@ -2194,8 +2144,7 @@
while (! IsListEmpty(&pti->DispatchingMessagesHead))
{
CurrentEntry = RemoveHeadList(&pti->DispatchingMessagesHead);
- CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- DispatchingListEntry);
+ CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, DispatchingListEntry);
CurrentSentMessage->CompletionEvent = NULL;
CurrentSentMessage->Result = NULL;
Author: tfaber
Date: Sun Feb 15 22:20:34 2015
New Revision: 66304
URL: http://svn.reactos.org/svn/reactos?rev=66304&view=rev
Log:
[NTOS]
- In ExpReleaseOrWaitForKeyedEvent, always restore previous values for ETHREAD::KeyedWaitValue and ETHREAD::KeyedWaitChain, as these fields have alternative meanings outside of keyed events
- Add missing list walk in ExpReleaseOrWaitForKeyedEvent
- In Nt(WaitFor|Release)KeyedEvent, refuse keys that are not two-byte aligned as shown by Wine tests
- Don't forget to set KTHREAD::Process on thread creation
Fixes hang when running ntdll_winetest:om as well as failing tests.
ROSTESTS-118 #resolve
Modified:
trunk/reactos/ntoskrnl/ex/keyedevt.c
trunk/reactos/ntoskrnl/ke/thrdobj.c
trunk/rostests/winetests/ntdll/om.c
Modified: trunk/reactos/ntoskrnl/ex/keyedevt.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/keyedevt.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/keyedevt.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/keyedevt.c [iso-8859-1] Sun Feb 15 22:20:34 2015
@@ -132,6 +132,7 @@
PLIST_ENTRY ListEntry, WaitListHead1, WaitListHead2;
NTSTATUS Status;
ULONG_PTR HashIndex;
+ PVOID PreviousKeyedWaitValue;
/* Get the current process */
CurrentProcess = KeGetCurrentProcess();
@@ -167,6 +168,7 @@
be signaled by this thread or, when the wait is aborted due to thread
termination, then it first needs to acquire the list lock. */
Thread = CONTAINING_RECORD(ListEntry, ETHREAD, KeyedWaitChain);
+ ListEntry = ListEntry->Flink;
/* Check if this thread is a correct waiter */
if ((Thread->Tcb.Process == CurrentProcess) &&
@@ -179,7 +181,10 @@
InitializeListHead(&Thread->KeyedWaitChain);
/* Wake the thread */
- KeReleaseSemaphore(&Thread->KeyedWaitSemaphore, 0, 1, FALSE);
+ KeReleaseSemaphore(&Thread->KeyedWaitSemaphore,
+ IO_NO_INCREMENT,
+ 1,
+ FALSE);
Thread = NULL;
/* Unlock the list. After this it is not safe to access Thread */
@@ -193,7 +198,8 @@
/* Get the current thread */
CurrentThread = PsGetCurrentThread();
- /* Set the wait key */
+ /* Set the wait key and remember the old value */
+ PreviousKeyedWaitValue = CurrentThread->KeyedWaitValue;
CurrentThread->KeyedWaitValue = KeyedWaitValue;
/* Initialize the wait semaphore */
@@ -221,16 +227,20 @@
ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
/* Check if the wait list entry is still in the list */
- if (CurrentThread->KeyedWaitChain.Flink != &CurrentThread->KeyedWaitChain)
+ if (!IsListEmpty(&CurrentThread->KeyedWaitChain))
{
/* Remove the thread from the list */
RemoveEntryList(&CurrentThread->KeyedWaitChain);
+ InitializeListHead(&CurrentThread->KeyedWaitChain);
}
/* Unlock the list */
ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
KeLeaveCriticalRegion();
}
+
+ /* Restore the previous KeyedWaitValue, since this is a union member */
+ CurrentThread->KeyedWaitValue = PreviousKeyedWaitValue;
return Status;
}
@@ -412,6 +422,12 @@
NTSTATUS Status;
LARGE_INTEGER TimeoutCopy;
+ /* Key must always be two-byte aligned */
+ if ((ULONG_PTR)Key & 1)
+ {
+ return STATUS_INVALID_PARAMETER_1;
+ }
+
/* Check if the caller passed a timeout value and this is from user mode */
if ((Timeout != NULL) && (PreviousMode != KernelMode))
{
@@ -472,6 +488,12 @@
NTSTATUS Status;
LARGE_INTEGER TimeoutCopy;
+ /* Key must always be two-byte aligned */
+ if ((ULONG_PTR)Key & 1)
+ {
+ return STATUS_INVALID_PARAMETER_1;
+ }
+
/* Check if the caller passed a timeout value and this is from user mode */
if ((Timeout != NULL) && (PreviousMode != KernelMode))
{
Modified: trunk/reactos/ntoskrnl/ke/thrdobj.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/thrdobj.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/thrdobj.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/thrdobj.c [iso-8859-1] Sun Feb 15 22:20:34 2015
@@ -838,8 +838,9 @@
TimerWaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead;
TimerWaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead;
- /* Set the TEB */
+ /* Set the TEB and process */
Thread->Teb = Teb;
+ Thread->Process = Process;
/* Check if we have a kernel stack */
if (!KernelStack)
Modified: trunk/rostests/winetests/ntdll/om.c
URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/om.c?rev=…
==============================================================================
--- trunk/rostests/winetests/ntdll/om.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/om.c [iso-8859-1] Sun Feb 15 22:20:34 2015
@@ -1080,8 +1080,5 @@
test_query_object();
test_type_mismatch();
test_event();
- if (winetest_interactive)
- test_keyed_events();
- else
- skip("Skipping test_keyed_events(). ROSTESTS-118.\n");
-}
+ test_keyed_events();
+}
Author: tfaber
Date: Sun Feb 15 18:20:59 2015
New Revision: 66302
URL: http://svn.reactos.org/svn/reactos?rev=66302&view=rev
Log:
[ADVAPI32_WINETEST]
- Skip over service timeout tests because they take too long. This is not a bug, the tests are completing successfully -- however they are designed to cause service manager timeouts and take two minutes in doing so. Testbot time is too valuable to do this on every commit.
ROSTESTS-151
Modified:
trunk/rostests/winetests/advapi32/service.c
Modified: trunk/rostests/winetests/advapi32/service.c
URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/servic…
==============================================================================
--- trunk/rostests/winetests/advapi32/service.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/advapi32/service.c [iso-8859-1] Sun Feb 15 18:20:59 2015
@@ -2266,6 +2266,12 @@
goto cleanup;
}
+ if (!winetest_interactive)
+ {
+ skip("ROSTESTS-151: Skipping service start timeout tests because they take too long. This is not a bug!\n");
+ goto cleanup;
+ }
+
/* Again with a process that exits right away */
displayname = "Winetest Exit Service";
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);