April 5th, 2022

Adventures in application compatibility: The case of the RAII type that failed to run its destructor

A customer reported that their system crashed with bugcheck code 0xEF: CRITICAL_PROCESS_DIED because the RPCSS service died. The investigation of this failure was difficult because by the time the crash occurred, everything was badly corrupted with no evidence as to who did the corrupting. The data that was being corrupted is per-thread data that is normally managed by an RAII type, so there should be no way it could be getting corrupted, assuming that the RAII type is being used properly: Always created and destructed in LIFO order, which is typically accomplished by making it a local variable in a non-coroutine function.

The team scoured their code for all uses of that RAII type and couldn’t find any place where they could possibly be using it incorrectly.

Eventually, the team discovered that a third party anti-malware application had injected itself into the RPCSS service and was detouring some functions.¹ And for some reason, the detour was unhappy, but instead of failing the call, it raised a structured exception.

This structured exception was caught by the RPC equivalent of the giant try/catch that COM wraps around every server method. For RPC, this wrapper goes by the name Rpc­Exception­Filter. The exception was raised from their detour and it so happens that the exception they raised is not one that the Rpc­Exception­Filter function deems to be noteworthy, so the Rpc­Exception­Filter function swallows the exception and returns an RPC failure to the client.

As I noted, this structured exception bypasses C++ destructors.

And that’s why the RAII class was not working. The code wasn’t holding it wrong. Rather, the third party code broke the rules.

Now, the third party code had this problem all along: The rogue exception caused an entire RPC call to become abandoned mid-stream, resulting in lots of leaks and missing cleanup. What changed is that there’s new code in the RPCSS service that was counting on the cleanup to avoid a crash.

This particular anti-malware program must be somewhat popular because the problem recurs about once or twice a year with a different customer each time. This is the bitter spot² in bug frequency, because it’s not frequent enough that the problem remains on your mind whenever you get a mystery crash so you can open the discussion with the customer by saying, “Okay, before I spend too much time on this, can you tell me if you recently installed or reconfigured Contoso anti-malware?” On the other hand, the issue is frequent enough that it consumes a lot of time and effort to gather crash dumps and eventually realize that it’s that Contoso anti-malware problem again.

¹ Windows does not support detouring the operating system. This anti-malware software is doing unsupported things, but good luck explaining that to their customers.

² The bitter spot is the opposite of the sweet spot. Or is the opposite of the sweet spot the salty spot? The sour spot? Maybe it’s all of them. When you find yourself in this spot, you are probably going to be sour, bitter and probably a little salty.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

10 comments

Discussion is closed. Login to edit/delete existing comments.

  • Richard Russell

    You left out the umami spot.

  • Henke37

    Fighting games seem to have settled on “sour spot”.

  • Alois Kraus

    It could help to get a short wpr recording of the machine which collects all loaded modules besides a memory dump as default action. I had my own share of AV induced issues and did write https://github.com/Siemens-Healthineers/ETWAnalyzer to be able to quickly query all known AV vendors in the stacks. With proper stacktags one can quickly find out if the slowness of an application comes from SmartScreen, Mc Affee or any other AV vendor. I...

    Read more
  • David Wolff

    When I worked at Prime Computer, we had an automated dump-analysis tool that had rules about what things in a crash dump were clues to known crashes. For example, if a particular routine crashed, and the third parameter was invalid, it was a known crashing bug (fixed in a later release). Doesn’t Microsoft have something similar?

    • Tim Weis

      Windows Error Reporting, as I recall, (used to) categorize defects into buckets, where ideally each bucket would refer to the same core issue. Microspeak: Bucket bugs, bucket spray, bug spray, and failure shift goes over some of the challenges and illustrates the outcomes when things are less than ideal.

      Read more
  • Jacob Manaker · Edited

    Eventually, the team discovered that a third party anti-malware application had injected itself into the RPCSS service and was detouring some functions.

    The first time I read this, I missed the “anti-” in “anti-malware application.” It made a lot more sense that way.

    • Nathan Williams

      Anti-malware software is the most common type of malware after all.

  • 紅樓鍮 · Edited

    Bonus chatter: Rust considers RAII leaks (which Rust supports officially through e. g. ) to be safe. This is normally OK, until someone tries to rely on destructors being run to guarantee safety, like did (crates.io thread-scoped).

    Rust reconciled them with a new continuation-passing style API (), which by design prevents ting the join guard.
    (Not that it would help the case of an unhandled structured exception.)

    Bonus bonus chatter: Doing anything that involves...

    Read more
  • Henry Skoglund

    When helping someone with a weirdly behaving program, in the old days #1 advice used to be “Upgrade your video driver” but today I always start with “Do you have any 3rd-party antivirus program installed” because sadly they are often the culprit.
    Also thank you for making me laugh: “… The code wasn’t holding it wrong. . “” 🙂