[PR #3414] [MERGED] Prevent cleanup of object given to handle that failed access check #25349

Open
opened 2026-01-31 09:08:56 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/3414
Author: @miniksa
Created: 11/1/2019
Status: Merged
Merged: 11/5/2019
Merged by: @miniksa

Base: masterHead: dev/miniksa/3216


📝 Commits (4)

  • 63e0a76 Ensure rights check and increments pass before assigning an object to a handle (since deallocation of handles will automatically attempt to cleanup).
  • d78db89 Add feature test derived from sample code to check if we can close without crashing.
  • 5b36bfc code format
  • 5917443 Add unit test as well.

📊 Changes

12 files changed (+217 additions, -23 deletions)

View changed files

📝 src/host/ft_host/API_BufferTests.cpp (+50 -0)
📝 src/host/ft_host/Common.cpp (+8 -0)
📝 src/host/ft_host/Common.hpp (+2 -0)
📝 src/host/ft_host/InitTests.cpp (+1 -1)
📝 src/host/ut_host/Host.UnitTests.vcxproj (+1 -0)
📝 src/host/ut_host/Host.UnitTests.vcxproj.filters (+3 -0)
src/host/ut_host/ObjectTests.cpp (+100 -0)
📝 src/host/ut_host/sources (+1 -0)
📝 src/server/ObjectHandle.cpp (+33 -12)
📝 src/server/ObjectHandle.h (+7 -5)
📝 src/server/ObjectHeader.cpp (+7 -5)
📝 src/server/ObjectHeader.h (+4 -0)

📄 Description

Summary of the Pull Request

Stops a crash that occurs when Cooked Read fails to acquire the screen buffer handle and accidentally cleans up the entire buffer on failure.

References

PR Checklist

Detailed Description of the Pull Request / Additional comments

When I refactored the object management and server layer in the console host, I divided each segment into objects with their own role and tried to ensure that things cleaned themselves up appropriately when errors occurred.

Turns out, one of those things got a little bit too aggressive.

ObjectHandle is given out for each client process or activity touching either the input or output objects (the input buffer and output buffers, respectively.) They also track their own permission state because each access can have different permission to the same object.

However, the objects themselves in the ObjectHeader have to keep track of their open count, that is how many outstanding ObjectHandles there should be referencing a particular object.

When an ObjectHandle closes, it decrements the counts on the object to represent itself going away, but it will also finally check if the outstanding count reaches zero and trigger the object itself to leave when there are no longer any references.

This all sounds good, except for the fact that a Handle was created referencing the screen buffer before the access check occurred, the check failed, and the Handle was freed as we exited early.... which then decremented the count to zero despite the increment never happening... cleaned up the object... and then later when the client application came by to shut the object... crash. It's already gone.

The resolution here is to not actually give Handle the rights to the object until the access check and increment has occurred. The Handle still has cleanup rights if it has the object pointer, now given after all the checks. Otherwise, it should just leave everything alone.

The problem is actually in the read operation. Because the read is a "cooked read" where the conhost is supposed to process the characters interactively, it acquires a handle to the active screen buffer before operating. However, if that buffer doesn't have share rights, it's not allowed and did the cleanup (oops). It should probably just fail and go on. That's what V1 did.

Validation Steps Performed

  • Used the sample application in #3216
  • Put in an automated test from this sample application (feature test)
  • Put in automated tests exercising handle counts (unit tests)
  • Check that conhostv1 did indeed have the sharing error

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/3414 **Author:** [@miniksa](https://github.com/miniksa) **Created:** 11/1/2019 **Status:** ✅ Merged **Merged:** 11/5/2019 **Merged by:** [@miniksa](https://github.com/miniksa) **Base:** `master` ← **Head:** `dev/miniksa/3216` --- ### 📝 Commits (4) - [`63e0a76`](https://github.com/microsoft/terminal/commit/63e0a769143d7a79e357b54c4984a73964806550) Ensure rights check and increments pass before assigning an object to a handle (since deallocation of handles will automatically attempt to cleanup). - [`d78db89`](https://github.com/microsoft/terminal/commit/d78db89268a642fe283c5e0307e241ab7e053ebd) Add feature test derived from sample code to check if we can close without crashing. - [`5b36bfc`](https://github.com/microsoft/terminal/commit/5b36bfc95322918c340b0d5d215478385ee4e21e) code format - [`5917443`](https://github.com/microsoft/terminal/commit/5917443241138395534183e738552f43208977a5) Add unit test as well. ### 📊 Changes **12 files changed** (+217 additions, -23 deletions) <details> <summary>View changed files</summary> 📝 `src/host/ft_host/API_BufferTests.cpp` (+50 -0) 📝 `src/host/ft_host/Common.cpp` (+8 -0) 📝 `src/host/ft_host/Common.hpp` (+2 -0) 📝 `src/host/ft_host/InitTests.cpp` (+1 -1) 📝 `src/host/ut_host/Host.UnitTests.vcxproj` (+1 -0) 📝 `src/host/ut_host/Host.UnitTests.vcxproj.filters` (+3 -0) ➕ `src/host/ut_host/ObjectTests.cpp` (+100 -0) 📝 `src/host/ut_host/sources` (+1 -0) 📝 `src/server/ObjectHandle.cpp` (+33 -12) 📝 `src/server/ObjectHandle.h` (+7 -5) 📝 `src/server/ObjectHeader.cpp` (+7 -5) 📝 `src/server/ObjectHeader.h` (+4 -0) </details> ### 📄 Description <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Stops a crash that occurs when Cooked Read fails to acquire the screen buffer handle and accidentally cleans up the entire buffer on failure. <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> ## References <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #3216 * [x] I work here * [x] Tests added/passed * [x] Doc comments added, MSDN docs should be fine * [x] I'm a core contributor and I was the one that broke this <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments When I refactored the object management and server layer in the console host, I divided each segment into objects with their own role and tried to ensure that things cleaned themselves up appropriately when errors occurred. Turns out, one of those things got a little bit too aggressive. `ObjectHandle` is given out for each client process or activity touching either the input or output objects (the input buffer and output buffers, respectively.) They also track their own permission state because each access can have different permission to the same object. However, the objects themselves in the `ObjectHeader` have to keep track of their open count, that is how many outstanding `ObjectHandle`s there should be referencing a particular object. When an `ObjectHandle` closes, it decrements the counts on the object to represent itself going away, but it will also finally check if the outstanding count reaches zero and trigger the object itself to leave when there are no longer any references. This all sounds good, except for the fact that a Handle was created referencing the screen buffer before the access check occurred, the check failed, and the Handle was freed as we exited early.... which then decremented the count to zero despite the increment never happening... cleaned up the object... and then later when the client application came by to shut the object... crash. It's already gone. The resolution here is to not actually give `Handle` the rights to the object until the access check and increment has occurred. The `Handle` still has cleanup rights if it has the object pointer, now given after all the checks. Otherwise, it should just leave everything alone. The problem is actually in the read operation. Because the read is a "cooked read" where the conhost is supposed to process the characters interactively, it acquires a handle to the active screen buffer before operating. However, if that buffer doesn't have share rights, it's not allowed and did the cleanup (oops). It should probably just fail and go on. That's what V1 did. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed * [x] Used the sample application in #3216 * [x] Put in an automated test from this sample application (feature test) * [x] Put in automated tests exercising handle counts (unit tests) * [x] Check that `conhostv1` did indeed have the sharing error --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:08:56 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#25349