我正在这样的过程中创建一个全局信号量对象:
CreateSemaphore(NULL, 1, 1, "Global\\bitmap");
现在,当我试图在子进程中打开它时(这是“另一个进程”的特殊情况,它不会是一个打开所创建的信号量的子代),如下所示:
bitmapSem = OpenSemaphore(NULL, TRUE, "Global\\bitmap");
bitmapSem
变量等于NULL
,我从GetLastError()
收到错误5(ERROR_ACCESS_DENIED)。
有什么想法吗?
答案 0 :(得分:7)
OpenSemaphore()
的第一个参数记录为:
dwDesiredAccess [in]
访问信号量对象。如果指定对象的安全描述符不允许对调用进程请求访问,则该函数将失败。有关访问权限的列表,请参阅同步对象安全性和访问权限。
在已发布的代码NULL
中指定:未记录为具有特殊含义。更改为Synchronization Object Security and Access Rights中记录的访问权限之一:
bitmapSem = OpenSemaphore(SYNCHRONIZE, TRUE, "Global\\bitmap");
编辑:
要创建一个可以授予Everyone
访问权限的安全描述符,请尝试以下(未经测试的)代码:
/* 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");
}
答案 1 :(得分:7)
我必须在其他答案和安全警告中加上澄清。
首先,将NULL作为lpSemaphoreAttributes
参数传递给::CreateSemaphore()
不意味着无法访问任何人;相反,它意味着将分配默认访问控制。 MSDN is crystal clear on that:如果此参数为NULL,则信号量将获取默认安全描述符。信号量的默认安全描述符中的ACL来自创建者的主要或模拟令牌。
通常,信号量可以由相同的用户身份打开和使用。因此,如果信号量由在同一交互式会话中运行的进程共享,或者在相同的服务标识下共享,则即使使用默认安全描述符创建,也可以由另一个进程打开信号量。正如@hmjd已经指出的那样,你必须始终明确地调出你想要在信号量上断言的权利:SYNCHRONIZE|SEMAPHORE_MODIFY_STATE
允许等待和释放它。
其次,要小心谨慎。通过授予Everyone对信号量的完全访问权限,如上所述,可能会创建DoS攻击的安全漏洞。您应该考虑是否希望任意进程能够获取和释放信号量。它是否适用于不受限制的公共用途?将最小的,允许范围很小的ACL分配给对象始终是一种好习惯。使用SDDL可能是编码安全描述符的最简单方法,尽管脚本本身不是很易读。
答案 2 :(得分:0)
lpSemaphoreAttributes [in,optional]
指向a的指针 SECURITY_ATTRIBUTES结构。如果此参数为NULL,则为句柄 不能被子进程继承。
使用空的DACL传递LPSECURITY_ATTRIBUTES
并将bInheritHandle
成员设置为第一个参数。
VB中的一个例子是:
'Setup the security descriptor
InitializeSecurityDescriptor SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION
SetSecurityDescriptorDacl SecurityDescriptor, 1, ByVal 0, 0 'Dacl is present and empty
'Setup the security attributes
SecurityAttributes.nLength = Len(SecurityAttributes)
SecurityAttributes.lpSecurityDescriptor = VarPtr(SecurityDescriptor)
SecurityAttributes.bInheritHandle = False