views:

484

answers:

3

I am assuming that once a semaphore is created by a process, it will be accessible by any process/user.

Is it possible to put access restrictions on a particular semaphore so that it can be accessible by only certain processes/users or only certain processes can release the semaphore.
I see some problems if we make a semaphore accessible by all processes.Eg: a dummy process can read the semaphore and release the lock at wish making a false signal to the actual process that is really waiting for the semaphore lock.

All these questions are arising as I am getting very weird output with the following code snippet:

use Win32::Semaphore; 

$sem = Win32::Semaphore->new(0, 1,"reliance2692") 
    or print "Can't create semaphore\n";

$sem = Win32::Semaphore->open("reliance2692") 
    or print "Can't open semaphore\n";

print "Semaphore:" . $sem . "\n";

By running the above program, I am getting the following output

Can't create semaphore
Can't open semaphore

The output shows that its failed to create a semaphore and even failed to open semaphore. creating a semaphore might have failed if a semaphore already exists with the given name. I don't understand why opening a semaphore failed.

Can some clarify the scenario where both creating semaphore & opening semaphore fails.

+1  A: 

From Win32::Semaphore pod

$semaphore = Win32::Semaphore->new($initial, $maximum, [$name])

Constructor for a new semaphore object. $initial is the initial count, and $maximum is the maximum count for the semaphore. If $name is omitted or undef, creates an unnamed semaphore object.

If $name signifies an existing semaphore object, then $initial and $maximum are ignored and the object is opened. If this happens, $^E will be set to 183 (ERROR_ALREADY_EXISTS).

If I'm reading this correctly, if your call to Win32::Semaphore->new refers to an existing semaphore, then the new call will open the semaphore as well, and the subsequent open call will be redundant (it's not clear to me from the pod what should happen if you open a sempahore that is already open).

Perhaps you could step through the code, checking the value of $sem as well as $! and $^E at each step.

Additional reply: the Windows API does have methods for setting access control of semaphores, but

  1. they don't appear to be exposed in the Perl Win32::Semaphore module
  2. access control can't be set unless it was already allowed by the other process that created the semaphore

I don't know if you have any good options for this problem. Can you modify the process that creates the semaphore to relax access restrictions? Ask the Win32::Semaphore author to update his module? Try to fix Win32::Semaphore yourself?

mobrule
Naga Kiran
+3  A: 

Win32::Semaphore->new calls the Windows API function CreateSemaphore and gets the process's default security descriptor, which usually means that processes running as the same user as your script can have full access whereas processes running as other accounts get no access. So, for starters, your assumption is false.

The name you choose in your Perl code is passed directly to the API function, so it's subject to the same namespace rules as all other Win32 kernel objects.

Win32::Semaphore provides no interface for specifying access restrictions. Even if it did, Windows does not provide per-process permissions. Permissions are attached to the user, not the process.

If you're getting "access denied" from new, then that suggests there's another program running that chose to use that same name for something else — maybe another semaphore, or maybe something else, like an event or a mutex — and that process is running as a different user.

If you're getting "access denied" from open, then, in addition to the possibilities for new, it could be that another process has already opened a semaphore with the same name but has not granted full permissions to other users. Win32::Semaphore->open requests SEMAPHORE_ALL_ACCESS permission.

If the semaphore has already been opened by a process running as the same user, then you should not get "access denied." Neither new nor open should fail in that case, although $^E might hold 183 (ERROR_ALREADY_EXISTS) anyway.

Rob Kennedy
+2  A: 

For the record, I'm the author of Win32::Semaphore. As mobrule and Rob have explained, Windows security is user/group based. It's not possible to have a semaphore that only certain processes can access. If any process belonging to a user can access a semaphore, then any process of that user can access that semaphore.

Normally, the default access allows only the current user to access the semaphore. Nobody's ever requested the ability to have Win32::Semaphore specify a non-default security descriptor, and the associated API is non-trivial. If somebody created a module to manage a SECURITY_ATTRIBUTES structure, I'd be happy to add support for that to Win32::Semaphore and the related IPC modules. Win32-Security does not appear to be that module, although it might be a start.

If you need a semaphore to work across multiple users, your only solution right now is to create the semaphore outside of Win32::Semaphore, passing an appropriate SECURITY_ATTRIBUTES pointer. You could do that with a small helper program written in C, or using Inline::C. (Remember that once created, a semaphore exists as long as any process has an open handle to it, so your helper program needs to keep the semaphore handle open until you've called Win32::Semaphore->open on it.)

cjm