幽灵/崩溃补丁导致COM方法返回E_ACCESSDENIED

RAZ*_*Taz 7 windows com patch visual-studio visual-c++

我正在开发一个大量使用COM的项目,新的Spectre/Meltdown补丁毫无疑问地搞乱了程序中的通信.

我怎么知道?我重新映像了一台Windows机器(2017年5月),这个补丁不存在.我安装了我的程序,一切都按预期工作.然后我下载了所有必需的更新.该计划不再有效.然后,我仅卸载了Meltdown/Spectre补丁(2018-01基于x64的系统的Windows 10版本1507的累积更新(KB4056893)),程序恢复正常行为.

我将调试器连接到我的程序并将其追溯到这段代码.

INvRtrControl4Itf * poRouterControl = GetNvRtrControl4();
if(poRouterControl)
{
    //the following line of code always returns E_ACCESSDENIED
    HRESULT hr = poRouterControl->GetXPTExtendedInfoForOutputs(lNumPorts, poOutputPorts, poXPTAndLPRInfo, peStatus);
    if(FAILED(hr))
    {
        ConnectToRouterControl();
        poRouterControl->Release();
        return hr;
    }
    poRouterControl->Release();
}
Run Code Online (Sandbox Code Playgroud)

未修补系统上的Windows调试器:

poRouterControl->GetXPTExtendedInfoForOutputs returns S_OK
Run Code Online (Sandbox Code Playgroud)

修补系统上的Windows调试程序:

poRouterControl->GetXPTExtendedInfoForOutputs returns E_ACCESSDENIED
Run Code Online (Sandbox Code Playgroud)

我有一个COM服务器A尝试与COM服务器B通信,两者都具有相同的权限(SYSTEM).在PATCHED系统上,当A从COM接口INvDevControl2Itf调用方法时,服务器B调用该方法而没有错误.当同一服务器A尝试从进程B上的不同接口INvRtrControl4Itf调用方法时,将返回E_ACCESSDENIED,并且我从未遇到过COM接口.在UN-PATCHED系统上,一切都按预期工作.

有没有人用COM和新的Spectre/Meltdown补丁遇到这个问题?我将继续寻找原因,但相同的确切代码运行完全没有安装补丁.但是,客户最终会想要更新他们的系统,因此我不建议也不要告诉他们永远不要安装补丁.

RAZ*_*Taz 3

在补丁本身的 Windows 支持页面的帮助下,我能够通过更改 COM 服务的 CoInitializeSecurity() 方法调用中的一些代码来解决 COM 服务无法调用 GetXPTExtendedInfoForOutputs 方法的问题

hRes = CoInitializeSecurity(NULL, -1, NULL, NULL,
        RPC_C_AUTHN_LEVEL_NONE,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        EOAC_NONE,
        NULL);
Run Code Online (Sandbox Code Playgroud)

hRes = CoInitializeSecurity(NULL, -1, NULL, NULL,
        RPC_C_AUTHN_LEVEL_CALL, //<----------- changed
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        EOAC_NONE,
        NULL);
Run Code Online (Sandbox Code Playgroud)

虽然它解决了这个问题,但有些接口在原始代码中工作得很好,而 INvRtrControl4Itf 等其他接口却失败了,这有点令人不安。此外,我不需要更改正在与我通信的其他 COM 服务中的 CoInitializeSecurity 方法初始化,只需更改调用方 COM 服务即可。其他 COM 服务仍然可以使用 RPC_C_AUTHN_LEVEL_NONE 进行初始化,并且我的程序像以前一样工作。

但是,我确实将所有 CoInitializeSecurity 方法调用更改为使用 RPC_C_AUTHN_LEVEL_CALL,这应该可以减轻未来出现 E_ACCESSDENIED hresults 的可能性。不幸的是,现在对 RPC 服务器的每次调用都需要身份验证,我将假设我的程序的性能可能会受到一点影响。我怀疑这会引起任何关注。

也许这就是为什么有些人在使用 Spectre/Meltdown 补丁更新系统时注意到性能受到影响的原因……只是一个想法。