Reputation: 22275
I'm trying to create a named global event that could be shared among my service and user process(-es). The user process may run under credentials of any low privileged logged in Windows user (even a built-in guest.) There's also no way of knowing which process will create this event first, i.e. service or a user process.
So from both the service & user-mode process the event is created/opened as such:
//Event name is made up using special/shared file path, and basically becomes something like this
strEventName = L"Global\\sa_evt_C:_Users_Name_C++_Mod0110_debug_TmLog0";
//Create descriptor for "ALL access"
PSECURITY_DESCRIPTOR psdAll;
if(::ConvertStringSecurityDescriptorToSecurityDescriptor(
isWindowsVistaOrLater ? L"D:(A;;GA;;;WD)(A;;GA;;;AN)S:(ML;;;;;S-1-16-0)" : L"D:(A;;GA;;;WD)(A;;GA;;;AN)",
SDDL_REVISION_1, &psdAll, NULL))
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = psdAll;
hEvent = ::CreateEvent(&sa, TRUE, FALSE, strEventName);
LocalFree(psdAll);
}
The issue I'm experiencing is that the event is created by both the service and user mode process(-es) but it's almost like if they each create their own (non-shared) copies of the event, i.e. when I signal it the other module does not see it (via WaitForSingleObject API.)
I also ran it through the debugger and, say, after this event is created in the service, I would expect the CreateEvent() API in the user process to succeed and return GetLastError as ERROR_ALREADY_EXISTS
, but it returns NO_ERROR
.
Any idea what am I doing wrong here and how to make it work?
Upvotes: 4
Views: 5392
Reputation: 1
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
Which I used to sync between IE activeX and native app, but it again failed. then i switched to ConvertStringSecurityDescriptorToSecurityDescriptor
, it works well.
Upvotes: -1
Reputation: 22275
Fixed it. Silly mistake. Forgot that those kernel object names are case sensitive. What I should've done is called CharLower() on the part of the name that follows Global\
to make it all lower case, and then it would've worked just fine.
As for the length of the kernel object name and characters allowed in it, there're basically two restrictions that I know of:
The part of the name that follows Global\
(or Local\
, or Session\
) may contain any characters, except slashes, i.e. \
or /
.
And the full object name itself cannot exceed MAX_PATH
characters (which is 260.) So it can be quite long.
Upvotes: 3
Reputation: 596602
So from both the service & user-mode process the event is created/opened as such
There is an easier way to create a security descriptor that allows unrestricted access to the event:
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = &sd;
hEvent = ::CreateEvent(&sa, TRUE, FALSE, strEventName);
There's also no way of knowing which process will create this event first, i.e. service or a user process.
You could require the user processes to use OpenEvent()
instead of CreateEvent()
. If the service is not running yet, the event would not be available to the processes. Non-admin/elevated processes should not be creating objects in the Global\
namespace, only consuming them, as they do not have the SeCreateGlobalPrivilege
permission by default.
Upvotes: 2