Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't open semaphore from another process

I'm creating a global semaphore object in a process like this:

CreateSemaphore(NULL, 1, 1, "Global\\bitmap");

now, when I'm trying to open it in a child process (it's a special case of "another process", it's not going to be a child that opens the semaphore created) like this:

bitmapSem = OpenSemaphore(NULL, TRUE, "Global\\bitmap");

the bitmapSem variable equals NULL and I'm getting error 5 (ERROR_ACCESS_DENIED) from GetLastError().

Any ideas?

like image 433
MeLight Avatar asked Dec 05 '22 18:12

MeLight


2 Answers

I must add a clarification to other answers, and a security warning.

First, passing NULL as the lpSemaphoreAttributes argument to ::CreateSemaphore() does not mean no access to anybody; rather, it means that default access control will be assigned. MSDN is crystal clear on that: If this parameter is NULL, the semaphore gets a default security descriptor. The ACLs in the default security descriptor for a semaphore come from the primary or impersonation token of the creator.

Normally, the semaphore can be opened and used by the same user identity. So, if the semaphore is shared by processes running in the same interactive session, or under the same service identity, it may be opened by another process even if created with the default security descriptor. As @hmjd already noted, you must always explicitly call out the right that you want to assert on the semaphore: SYNCHRONIZE|SEMAPHORE_MODIFY_STATE allows both waiting on and releasing it.

Second of all, a word of caution. By granting Everyone full access to the semaphore, as it was suggested above, a security hole for a DoS attack is potentially created. You should consider whether you want arbitrary processes to be able to grab and release the semaphore. Is it intended for unrestricted public use? It is always a good practice to assign minimal, narrowly permitting ACLs to objects. Using SDDL is probably the easiest way to encode a security descriptor, albeit the script itself is not very readable.

like image 74
kkm Avatar answered Dec 22 '22 02:12

kkm


The first argument to OpenSemaphore() is documented as:

dwDesiredAccess [in]

The access to the semaphore object. The function fails if the security descriptor of the specified object does not permit the requested access for the calling process. For a list of access rights, see Synchronization Object Security and Access Rights.

In the posted code NULL is specified: which is not documented as having a special meaning. Change to one of the access rights documented at Synchronization Object Security and Access Rights:

bitmapSem = OpenSemaphore(SYNCHRONIZE, TRUE, "Global\\bitmap");

EDIT:

To create a security descriptor that would grant access to Everyone try the following (untested) code:

/* Create a security descriptor that has an an empty DACL, to
   grant access to 'Everyone'. */
SECURITY_DESCRIPTOR sd;
if (0 == InitializeSecurityDescriptor(&sd,
                                      SECURITY_DESCRIPTOR_REVISION) ||
    0 == SetSecurityDescriptorDacl(&sd,
                                   TRUE,
                                   (PACL)0,
                                   FALSE))
{
    /* Failed to create security descriptor. */
}
else
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength              = sizeof(sa);
    sa.lpSecurityDescriptor = &sd;
    sa.bInheritHandle       = FALSE;

    HANDLE sh = CreateSemaphore(&sa, 1, 1, "Global\\bitmap");
}
like image 20
hmjd Avatar answered Dec 22 '22 01:12

hmjd