gpt4 book ai didi

windows - 当由 Windows 服务生成的进程调用时,CreateMutex() 失败并显示 ERROR_ACCESS_DENIED

转载 作者:可可西里 更新时间:2023-11-01 13:31:39 26 4
gpt4 key购买 nike

我刚刚花了几天时间来追踪一个错误,该错误是由于调用::CreateMutex() 失败而引发未处理的异常。请记住,CreateMutex() 不会尝试锁定互斥量,只是为了打开一个句柄。 即使互斥量已经存在也不应该失败,至少只要我将 bInitialOwner 设置为 FALSE,我就是这样做的。

但是如果我从 Windows 服务生成的程序调用 ::CreateMutexA(0, 0, "testtesttest123");(w3wp.exe 是它的父级和 scvhost.exe 是它的祖 parent ,它在 IIS APPPOOL\Worker1 用户帐户下运行),然后它失败并返回 NULL 如果互斥体已经被创建在 IIS APPPOOL\* 下运行的另一个进程。

我创建了一个重现此问题的最小示例:

void main()
{
HANDLE handle = CreateMutexA(0, 0, "testtesttest123");
std::string lastError = MyGetLastErrorAsText();
MyAppendToLog("%p %s\n", handle, lastError.c_str());
Sleep(INFINITE);
}

我通过从资源管理器(普通用户帐户)双击运行可执行文件 2 次,然后使其由 Windows 服务生成,然后再次从资源管理器运行它。

这会创建以下日志:

C:\Test\ReproduceMutexCrash.exe: 00000034 ERROR_SUCCESSC:\Test\ReproduceMutexCrash.exe: 00000034 ERROR_ALREADY_EXISTSc:\inetpub\wwwroot\Worker1\ReproduceMutexCrash.exe: 00000034 ERROR_SUCCESSc:\inetpub\wwwroot\Worker2\ReproduceMutexCrash.exe: 00000000 ERROR_ACCESS_DENIEDC:\Test\ReproduceMutexCrash.exe: 00000034 ERROR_ALREADY_EXISTS

这里的Worker1在IIS APPPOOL\Worker1下运行,而Worker2在IIS APPPOOL\Worker2用户账户下运行。

从日志中可以明显看出,如果互斥量是由普通用户进程创建的,这不会阻止其他用户进程甚至 Windows 服务打开句柄。但是,如果一个 Windows 服务创建了一个互斥量,则 ::CreateMutex() 在被另一个 Windows 服务调用时会失败,尽管用户进程仍然可以顺利打开一个句柄。

有人知道为什么会这样吗?

编辑:当进程由 Explorer 生成时,我看到互斥对象是 \Sessions\1\BaseNamedObjects\testtesttest123,而它是 \BaseNamedObjects\testtesttest123 当进程由 IIS 创建时,所有者为 Worker1(第一个成功创建互斥锁的进程)。

最佳答案

感谢评论的帮助,我终于弄明白了为什么会这样。这确实是因为权限,并且因为进程是从不同的用户帐户运行的。我通过运行 2 个单独的进程验证了这一点,但来自同一用户帐户 - IIS APPPOOL\Worker1,并且对于 ::CreateMutex() 都有效并返回了一个有效的 HANDLE。

仅当互斥量已被 IIS APPPOOL\Worker1 下的进程锁定并且 IIS APPPOOL\Worker2 下的进程尝试访问它时才会失败。

此外,我尝试在没有任何安全措施的情况下创建互斥锁,by creating an empty DACL :

SECURITY_ATTRIBUTES sa = { sizeof(sa) };
SECURITY_DESCRIPTOR SD;
InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&SD, TRUE, NULL, FALSE);
sa.lpSecurityDescriptor = &SD;
HANDLE mutex = CreateMutexA(&sa, 0, "testtesttest123");

使用空 DACL,来自不同用户帐户的 2 个进程可以打开同一个互斥体。

此外,用户进程创建的互斥量没有导致 ERROR_ACCESS_DENIED 的原因是它在不同的范围内创建互斥量 - \Sessions\1\BaseNamedObjects\testtesttest123,所以没有权限冲突,因为 Web 服务进程在 \BaseNamedObjects\testtesttest123 处创建了一个新的互斥量,所以它们无论如何都不会访问同一个对象。

关于windows - 当由 Windows 服务生成的进程调用时,CreateMutex() 失败并显示 ERROR_ACCESS_DENIED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36062608/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com