Answer to quick puzzle about security and synchronization


As many people quickly figured out, the reason why the the WaitForSingleObject returns immediately is that the call is failing. The reason is that the second process opened the handle with EVENT_MODIFY_STATE access, which grants permission to call the SetEvent function, the ResetEvent function, and the fatally flawed PulseEvent function, but it doesn't include SYNCHRONIZE access, which is necessary if you intend to synchronize on the object (i.e., wait on it).

The fix is for Process B to ask for SYNCHRONIZE access instead of EVENT_MODIFY_STATE.

The fact that it's happening in a second process is a red herring. You can put this code in the same process and it will fail/succeed in the same way:

HANDLE hEventA = CreateEvent(NULL, FALSE, TRUE, TEXT("MyNamedEvent"));
HANDLE hEventB = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("MyNamedEvent"));
WaitForSingleObject(hEventB, INFINITE); // fails

Indeed, the fact that the object is named is a red herring. It has nothing to do with named/unnamed objects.

HANDLE hEventA = CreateEvent(NULL, FALSE, TRUE, NULL);
HANDLE hEventB;
DuplicateHandle(GetCurrentProcess(), hEventA,
                GetCurrentProcess(), &hEventB,
                EVENT_MODIFY_STATE, FALSE, 0);
WaitForSingleObject(hEventB, INFINITE); // fails

In all three cases, the fix is to change EVENT_MODIFY_STATE to SYNCHRONIZE.

Comments (5)
  1. Anonymous says:

    And of course, a named handle with a hardcoded name is very easy to squat. Any app can register/signal that event, thus affecting your prog into unfavorable situation (denial of service, maybe worse things)

  2. Anonymous says:

    Since it doesn’t seem to be possible to post under the PulseEvent blog entry any more, I’ll post it here: PulseEvent is not flawed. Rather, what is flawed is a programmer trying to use it as means to signal a specific thread.

    The contract of PulseEvent is that it will wake up 0 or 1 thread, depending on circumstances. If you’re not content with the 0 outcome, don’t use PulseEvent.

  3. Anonymous says:

    This is sorta off topic but I am just curious. What is your job at Microsoft? It sounds like you did some core work back in the day (because you did some power toys) but moved into App Compat (apparently). Your posts are very intuitive and interesting, you have posted very.. enlightening scenarios. Somewhat related but not totally, at the Microsoft Community Blogs page, I looked for your blog under App Compate and found nothing, what category are you under?

  4. Anonymous says:

    Jonathan: If you call CreateEvent, and an event with that name already exists, it will give you a new handle to that event and GetLastError() will return ERROR_ALREADY_EXISTS (183). This way, you can at least tell if the event existed already without causing a race condition.

  5. David,

    Raymond’s the wizard. That’s his job.

Comments are closed.