Skip to content

Commit 4d54e91

Browse files
vseanreesermsftdotnet-botdipeshmsft
authored
Merging internal commits for release/7.0 (#9006)
* [internal/release/7.0] Update dependencies from dnceng/internal/dotnet-winforms * Fixes PenIMC UAF MSRC .NET 7 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-winforms build 20240311.11 Microsoft.Dotnet.WinForms.ProjectTemplates , Microsoft.Private.Winforms From Version 7.0.18-servicing.24158.8 -> To Version 7.0.18-servicing.24161.11 * Local dependencies updated based on build with BAR id 217431 (20240314.4 from https://dev.azure.com/dnceng/internal/_git/dotnet-winforms@refs/heads/internal/release/7.0) * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-winforms build Microsoft.Dotnet.WinForms.ProjectTemplates , Microsoft.Private.Winforms From Version 7.0.18-servicing.24164.4 -> To Version 7.0.18-servicing.24169.17 Dependency coherency updates Microsoft.NETCore.App.Ref,Microsoft.NETCore.App.Runtime.win-x64,VS.Redist.Common.NetCore.SharedFramework.x64.7.0 From Version 7.0.18 -> To Version 7.0.18 (parent: Microsoft.Private.Winforms --------- Co-authored-by: dotnet-bot <[email protected]> Co-authored-by: DotNet Bot <[email protected]> Co-authored-by: dipeshmsft <[email protected]>
1 parent e89a778 commit 4d54e91

File tree

5 files changed

+109
-14
lines changed

5 files changed

+109
-14
lines changed

NuGet.config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<clear />
66
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
77
<!-- Begin: Package sources from dotnet-runtime -->
8+
<add key="darc-int-dotnet-runtime-544c7e6" value="https://pkgs.dev.azure.com/dnceng/internal/_packaging/darc-int-dotnet-runtime-544c7e6e/nuget/v3/index.json" />
89
<!-- End: Package sources from dotnet-runtime -->
910
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
1011
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
@@ -20,6 +21,7 @@
2021
<disabledPackageSources>
2122
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
2223
<!-- Begin: Package sources from dotnet-runtime -->
24+
<add key="darc-int-dotnet-runtime-544c7e6" value="true" />
2325
<!-- End: Package sources from dotnet-runtime -->
2426
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
2527
</disabledPackageSources>

eng/Version.Details.xml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Dependencies>
33
<ProductDependencies>
4-
<Dependency Name="Microsoft.Private.Winforms" Version="7.0.17-servicing.24116.2">
4+
<Dependency Name="Microsoft.Private.Winforms" Version="7.0.18-servicing.24169.17">
55
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-winforms</Uri>
6-
<Sha>a21b74e7f5e96ccb8d95dcde605669feb30f6c5b</Sha>
6+
<Sha>1a5db9acafb5677490e44ad00d91cfff0dc11ddf</Sha>
77
</Dependency>
8-
<Dependency Name="Microsoft.Dotnet.WinForms.ProjectTemplates" Version="7.0.17-servicing.24116.2">
8+
<Dependency Name="Microsoft.Dotnet.WinForms.ProjectTemplates" Version="7.0.18-servicing.24169.17">
99
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-winforms</Uri>
10-
<Sha>a21b74e7f5e96ccb8d95dcde605669feb30f6c5b</Sha>
10+
<Sha>1a5db9acafb5677490e44ad00d91cfff0dc11ddf</Sha>
1111
</Dependency>
1212
<Dependency Name="System.CodeDom" Version="7.0.0" CoherentParentDependency="Microsoft.Private.Winforms">
1313
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
@@ -61,17 +61,17 @@
6161
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
6262
<Sha>d099f075e45d2aa6007a22b71b45a08758559f80</Sha>
6363
</Dependency>
64-
<Dependency Name="Microsoft.NETCore.App.Ref" Version="7.0.17" CoherentParentDependency="Microsoft.Private.Winforms">
64+
<Dependency Name="Microsoft.NETCore.App.Ref" Version="7.0.18" CoherentParentDependency="Microsoft.Private.Winforms">
6565
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
66-
<Sha>dff486f2d78d3f932d0f9bfa38043f85e358fb8c</Sha>
66+
<Sha>544c7e6eb3d5525c6f85341f51217d81d7c8ed80</Sha>
6767
</Dependency>
68-
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="7.0.17" CoherentParentDependency="Microsoft.Private.Winforms">
68+
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="7.0.18" CoherentParentDependency="Microsoft.Private.Winforms">
6969
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
70-
<Sha>dff486f2d78d3f932d0f9bfa38043f85e358fb8c</Sha>
70+
<Sha>544c7e6eb3d5525c6f85341f51217d81d7c8ed80</Sha>
7171
</Dependency>
72-
<Dependency Name="VS.Redist.Common.NetCore.SharedFramework.x64.7.0" Version="7.0.17-servicing.24115.8" CoherentParentDependency="Microsoft.Private.Winforms">
72+
<Dependency Name="VS.Redist.Common.NetCore.SharedFramework.x64.7.0" Version="7.0.18-servicing.24169.14" CoherentParentDependency="Microsoft.Private.Winforms">
7373
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
74-
<Sha>dff486f2d78d3f932d0f9bfa38043f85e358fb8c</Sha>
74+
<Sha>544c7e6eb3d5525c6f85341f51217d81d7c8ed80</Sha>
7575
</Dependency>
7676
</ProductDependencies>
7777
<ToolsetDependencies>

eng/Versions.props

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
</PropertyGroup>
2323
<!-- Packages that come from https://github.com/dotnet/winforms -->
2424
<PropertyGroup>
25-
<MicrosoftPrivateWinformsVersion>7.0.17-servicing.24116.2</MicrosoftPrivateWinformsVersion>
25+
<MicrosoftPrivateWinformsVersion>7.0.18-servicing.24169.17</MicrosoftPrivateWinformsVersion>
2626
</PropertyGroup>
2727
<!-- Packages that come from https://github.com/dotnet/runtime -->
2828
<PropertyGroup>
29-
<VSRedistCommonNetCoreSharedFrameworkx6470PackageVersion>7.0.17-servicing.24115.8</VSRedistCommonNetCoreSharedFrameworkx6470PackageVersion>
30-
<MicrosoftNETCoreAppRefVersion>7.0.17</MicrosoftNETCoreAppRefVersion>
31-
<MicrosoftNETCoreAppRuntimewinx64Version>7.0.17</MicrosoftNETCoreAppRuntimewinx64Version>
29+
<VSRedistCommonNetCoreSharedFrameworkx6470PackageVersion>7.0.18-servicing.24169.14</VSRedistCommonNetCoreSharedFrameworkx6470PackageVersion>
30+
<MicrosoftNETCoreAppRefVersion>7.0.18</MicrosoftNETCoreAppRefVersion>
31+
<MicrosoftNETCoreAppRuntimewinx64Version>7.0.18</MicrosoftNETCoreAppRuntimewinx64Version>
3232
<MicrosoftNETCorePlatformsVersion>7.0.4</MicrosoftNETCorePlatformsVersion>
3333
<SystemCodeDomPackageVersion>7.0.0</SystemCodeDomPackageVersion>
3434
<SystemConfigurationConfigurationManagerPackageVersion>7.0.0</SystemConfigurationConfigurationManagerPackageVersion>

src/Microsoft.DotNet.Wpf/src/PenImc/dll/ComLockableWrapper.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ namespace ComUtils
4040
// The apartment is verified during this call.
4141
HRESULT Unlock();
4242

43+
// Unlocking a wrapper permanently nulls out the server object pointer, so a
44+
// wrapper contains a non-null server object pointer if and only if it is
45+
// bound to a server object which has never been unlocked.
46+
bool HasNotBeenUnlocked() { return (m_serverObject != nullptr); }
47+
4348
private:
4449

4550
IUnknown *m_serverObject;

src/Microsoft.DotNet.Wpf/src/PenImc/dll/PimcManager.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,94 @@ void CPimcManager::TerminateHookThread(__inout CHookThreadItem * pThread)
396396
void CPimcManager::FinalRelease()
397397
{
398398
m_wispManagerLock.RevokeIfValid();
399+
400+
//
401+
// The CComObject<CPimcManager> destructor is the only function which calls into this
402+
// FinalRelease code.
403+
//
404+
// In all successful usage of CPimcManager: 1) Managed WPF code uses CoCreateInstance
405+
// to acquire an IPimcManager2 interface to a brand-new CPimcManager instance (created by
406+
// the ATL CComCreator<T>::CreateInstance machinery), meaning FinalConstruct by-definition
407+
// completes successfully, meaning "m_managerLock" is therefore guaranteed to be locked;
408+
// 2) Managed WPF code then runs through its full end-to-end usage of the CPimcManager
409+
// object (generally managed by the code in PenThreadWorker.cs); 3) When/if the managed WPF
410+
// code determines that the CPimcManager object is no longer needed, it sends a
411+
// RELEASE_MANAGER_EXT message (see UnsafeNativeMethods.ReleaseManagerExternalLock()) which
412+
// unlocks "m_managerLock"; 4) Now that it is unlocked, the CComObject<CPimcManager> object
413+
// can be destroyed when/if its refcount drops to zero, and this FinalRelease function will
414+
// run at that time.
415+
//
416+
// So in all successful usage cases, it is guaranteed that "m_managerLock" is already
417+
// unlocked when this code runs (because if it was still locked, the lock itself would have
418+
// prevented the refcount from reaching zero, and would have prevented this function from
419+
// ever running).
420+
//
421+
// That said, in unsuccessful usage cases, the ATL CComCreator<T>::CreateInstance machinery
422+
// can fail, meaning it will destroy the brand-new CPimcManager instance before returning
423+
// an error back to the CreateInstance caller. Destroying the brand-new instance triggers
424+
// the CComObject<CPimcManager> destructor and therefore calls into this function during
425+
// the CComCreator<T>::CreateInstance operation itself.
426+
//
427+
// The final step in CComCreator<T>::CreateInstance is a QI which queries the newly-created
428+
// object for whatever interface has been requested by the caller. This operation is the
429+
// main way that CComCreator<T>::CreateInstance can fail. For example, this QI is
430+
// guaranteed to fail whenever the CoCreateInstance caller targets the CPimcManager CLSID
431+
// but passes in a "random" IID that has nothing to do with IPimcManager2 or anything else
432+
// that CPimcManager implements.
433+
//
434+
// (In CPimcManager construction, outside of pathological cases (e.g., where a small heap
435+
// allocation in OS code fails due to out-of-memory), there are no other known ways that
436+
// the CComCreator<T>::CreateInstance sequence can fail; so the QI failure is the only
437+
// failure mode that is known to be of general interest.)
438+
//
439+
// The QI failure can only occur after the preceding FinalConstruct call has completed
440+
// successfully (since any FinalConstruct failure would have caused
441+
// CComCreator<T>::CreateInstance to abort without ever trying the QI); since
442+
// CPimcManager::FinalConstruct always locks the "m_managerLock", this implies that the
443+
// "m_managerLock" is guaranteed to be locked when this code runs (which is exactly
444+
// opposite to what happens in all successful usage cases as discussed above).
445+
//
446+
// In this case, it is crucial to unlock "m_managerLock" before allowing this CPimcManager
447+
// object to be destroyed. Without the unlock, this CPimcManager object would be destroyed
448+
// while the associated CStdIdentity in the OS code still holds a reference to it; during
449+
// any future apartment unload, the OS code would release this reference, and the release
450+
// would be a use-after-free at that point.
451+
//
452+
// Note that the crucial unlock causes overactive ATL debug asserts to fire if a chk build
453+
// of this DLL is used; specifically:
454+
//
455+
// - The code in the CComObject<CPimcManager> destructor always stomps the refcount to
456+
// 0xc0000001 (i.e., "-(LONG_MAX/2)"), meaning this CPimcManager object's refcount is
457+
// always 0xc0000001 when this code runs; unlocking "m_managerLock" will cause the refcount
458+
// to drop by one (because, as discussed above, the crucial operation which prevents
459+
// use-after-free problems will release the associated CStdIdentity's reference to this
460+
// CPimcManager object, and in this way releases the reference that was added when
461+
// "managerLock" was locked during FinalConstruct); as a result, unlocking "m_managerLock"
462+
// will move this CPimcManager object's refcount through a "0xc0000001 -> 0xc0000000"
463+
// transition.
464+
//
465+
// - Both of the CComObjectRootEx<T>::InternalRelease specializations contain debug asserts
466+
// which will fire whenever the refcount drops below 0xc0000001, so this transition always
467+
// triggers a debug assert when using a chk build of this DLL.
468+
//
469+
// - That said, all evidence strongly suggests that this is just an overactive assert in
470+
// the ATL code (probably just indicating that it is rare for FinalConstruct to add
471+
// "self-references" like it does for CPimcManager (since these self-references generally
472+
// prevent the server object from being destroyed unless a manual action like the
473+
// RELEASE_MANAGER_EXT message is taken later on), meaning it is rare to have a situation
474+
// where FinalRelease needs to release self-references that were acquired in
475+
// FinalConstruct, meaning this is a rare enough case that the ATL authors either didn't
476+
// test it or didn't think it was common enough to warrant adjusting the assert).
477+
//
478+
// Since this change is being made in servicing, attempt to change behavior as little as
479+
// possible in the "successful usage" cases where "m_managerLock" is already unlocked,
480+
// while still ensuring that FinalRelease will always run the crucial unlock in all
481+
// "unsuccessful usage" cases.
482+
//
483+
if (m_managerLock.HasNotBeenUnlocked())
484+
{
485+
m_managerLock.Unlock();
486+
}
399487
}
400488

401489
/////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)