BSOD:KERNEL_SECURITY_CHECK_FAILURE

  • log1
*** Fatal System Error: 0x00000139
                       (0x0000000000000003,0xFFFF800B63DD24B0,0xFFFF800B63DD2408,0x0000000000000000)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

For analysis of this file, run !analyze -v
nt!DbgBreakPointWithStatus:
fffff803`233cbcc0 cc              int     3
1: kd> !analyze -v
*** Unable to resolve unqualified symbol in Bp expression 'nepk_test::install'.
Connected to Windows 10 17763 x64 target at (Mon Aug  2 14:27:18.454 2021 (UTC + 8:00)), ptr64 TRUE
*** Unable to resolve unqualified symbol in Bp expression 'nepk_test::install'.
Loading Kernel Symbols
...............................................................
................................................................
.................................................
Loading User Symbols
......................................................
Loading unloaded module list
..................
*** Unable to resolve unqualified symbol in Bp expression 'nepk_test::install'.

************* Symbol Loading Error Summary **************
Module name            Error
SharedUserData         No error - symbol load deferred

You can troubleshoot most symbol related issues by turning on symbol loading diagnostics (!sym noisy) and repeating the command that caused symbols to be loaded.
You should also verify that your symbol search path (.sympath) is correct.
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

KERNEL_SECURITY_CHECK_FAILURE (139)
A kernel component has corrupted a critical data structure.  The corruption
could potentially allow a malicious user to gain control of this machine.
Arguments:
Arg1: 0000000000000003, A LIST_ENTRY has been corrupted (i.e. double remove).
Arg2: ffff800b63dd24b0, Address of the trap frame for the exception that caused the bugcheck
Arg3: ffff800b63dd2408, Address of the exception record for the exception that caused the bugcheck
Arg4: 0000000000000000, Reserved

Debugging Details:
------------------

KEY_VALUES_STRING: 1

PROCESSES_ANALYSIS: 1

SERVICE_ANALYSIS: 1

STACKHASH_ANALYSIS: 1

TIMELINE_ANALYSIS: 1

DUMP_CLASS: 1

DUMP_QUALIFIER: 0

BUILD_VERSION_STRING:  17763.1.amd64fre.rs5_release.180914-1434

DUMP_TYPE:  0

BUGCHECK_P1: 3

BUGCHECK_P2: ffff800b63dd24b0

BUGCHECK_P3: ffff800b63dd2408

BUGCHECK_P4: 0

TRAP_FRAME:  ffff800b63dd24b0 -- (.trap 0xffff800b63dd24b0)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=ffff9b0c14c33dd8 rbx=0000000000000000 rcx=0000000000000003
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff803232e90bf rsp=ffff800b63dd2640 rbp=ffff800b63dd26b1
 r8=0000000000000001  r9=0000000000000000 r10=0000000000000002
r11=ffff800b63dd26a0 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz ac pe cy
nt!KeWaitForSingleObject+0xcdf:
fffff803`232e90bf cd29            int     29h
Resetting default scope

EXCEPTION_RECORD:  ffff800b63dd2408 -- (.exr 0xffff800b63dd2408)
ExceptionAddress: fffff803232e90bf (nt!KeWaitForSingleObject+0x0000000000000cdf)
   ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: 0000000000000003
Subcode: 0x3 FAST_FAIL_CORRUPT_LIST_ENTRY

CPU_COUNT: 2

CPU_MHZ: bb8

CPU_VENDOR:  GenuineIntel

CPU_FAMILY: 6

CPU_MODEL: 9e

CPU_STEPPING: a

CPU_MICROCODE: 6,9e,a,0 (F,M,S,R)  SIG: CA'00000000 (cache) CA'00000000 (init)

BUGCHECK_STR:  0x139

PROCESS_NAME:  svchost.exe

CURRENT_IRQL:  2

DEFAULT_BUCKET_ID:  FAIL_FAST_CORRUPT_LIST_ENTRY

ERROR_CODE: (NTSTATUS) 0xc0000409 - <Unable to get error code text>

EXCEPTION_CODE: (NTSTATUS) 0xc0000409 - <Unable to get error code text>

EXCEPTION_CODE_STR:  c0000409

EXCEPTION_PARAMETER1:  0000000000000003

ANALYSIS_SESSION_HOST:  HIH-D-26062

ANALYSIS_SESSION_TIME:  08-02-2021 14:27:22.0570

ANALYSIS_VERSION: 10.0.18362.1 amd64fre

LAST_CONTROL_TRANSFER:  from fffff803234a0dd2 to fffff803233cbcc0

  • log2
STACK_TEXT:  
ffff800b`63dd19c8 fffff803`234a0dd2 : 00000000`00000003 00000000`00000003 ffff800b`63dd1b30 fffff803`2336b640 : nt!DbgBreakPointWithStatus
ffff800b`63dd19d0 fffff803`234a0557 : 00000000`00000003 ffff800b`63dd1b30 fffff803`233d80e0 00000000`00000139 : nt!KiBugCheckDebugBreak+0x12
ffff800b`63dd1a30 fffff803`233c4147 : 00000000`00000000 00000000`00000000 ffff8480`3acc0180 00000000`00000000 : nt!KeBugCheck2+0x957
ffff800b`63dd2150 fffff803`233d58e9 : 00000000`00000139 00000000`00000003 ffff800b`63dd24b0 ffff800b`63dd2408 : nt!KeBugCheckEx+0x107
ffff800b`63dd2190 fffff803`233d5c90 : ffff800b`00000000 00000000`00000070 00000000`00000000 fffff803`233d470d : nt!KiBugCheckDispatch+0x69
ffff800b`63dd22d0 fffff803`233d408e : ffff9b0c`00000038 00000000`00000000 00000000`00000040 00000000`00000040 : nt!KiFastFailDispatch+0xd0
ffff800b`63dd24b0 fffff803`232e90bf : 00000000`00000000 00000000`00000030 00000000`6d6b693f fffff803`236eabf8 : nt!KiRaiseSecurityCheckFailure+0x30e
ffff800b`63dd2640 fffff803`2332efc9 : ffff9b0c`14c33dd0 fffff803`00000022 ffff800b`63dd2700 fffff803`299e4500 : nt!KeWaitForSingleObject+0xcdf
ffff800b`63dd2710 fffff803`2332f58b : ffff9b0c`143cd3a0 00000000`00000000 00000000`00000000 ffff800b`00000000 : nt!ExpAcquireFastMutexContended+0x79
ffff800b`63dd2750 fffff803`299e8c6a : fffff803`236eabf8 ffff9b0c`16344ba0 00000000`00000000 fffff803`29a0a06a : nt!KeAcquireGuardedMutex+0x6b
ffff800b`63dd2780 fffff803`29a09a44 : ffff800b`63dd27e0 ffff9b0c`14c33db8 ffff9b0c`14c6e790 fffff803`299ea07c : MY_DRIVER!common_sync::SafeGuardedMutex::SafeGuardedMutex+0x3a [E:\job_src\MYDriver\MY_DRIVER\src\Common\CmSync.hpp @ 16] 
ffff800b`63dd27b0 fffff803`29a09b84 : ffff9b0c`14c33db0 ffff800b`63dd2850 00000000`0000003f fffff803`299ea9eb : MY_DRIVER!SafeUniqueSet<ThreadInformation>::del+0x24 [E:\job_src\MYDriver\MY_DRIVER\src\Common\Container\SafeUniqueSet.hpp @ 33] 
ffff800b`63dd2820 fffff803`299f08f5 : ffff9b0c`14c33cf8 ffff9b0c`0dd03b10 00000000`000023a0 ffff800b`63dd2900 : MY_DRIVER!ProcessInformation::eraseThread+0x44 [E:\job_src\MYDriver\MY_DRIVER\src\System\ProcessInformation.cpp @ 109] 
ffff800b`63dd2880 fffff803`23815240 : 00000000`000019e4 00000000`000023a0 ffff9b0c`143cd000 fffff803`2382ce82 : MY_DRIVER!ThreadCallback::createThreadNotifyRoutine+0x155 [E:\job_src\MYDriver\MY_DRIVER\src\Callbacks\ThreadCallback.cpp @ 47] 
ffff800b`63dd2930 fffff803`23868714 : 00000000`00000000 00000000`00000000 ffff9b0c`143cd080 ffff9b0c`13e461b0 : nt!PspCallThreadNotifyRoutines+0x140
ffff800b`63dd2970 fffff803`23893733 : 00000000`00000000 00000093`7e037000 00000000`00000000 00000000`00000000 : nt!PspExitThread+0x114
ffff800b`63dd2a70 fffff803`238936ba : 00000000`00000000 00000000`00000000 ffff9b0c`143cd080 00007fff`eb5cc290 : nt!PspTerminateThreadByPointer+0x53
ffff800b`63dd2ab0 fffff803`233d5305 : 00000000`00000000 ffff9b0c`143cd080 ffff800b`63dd2b80 ffff9b0c`1435f2e0 : nt!NtTerminateThread+0x4a
ffff800b`63dd2b00 00007fff`eddf01c4 : 00007fff`eddba2ee 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25
00000093`7e2ffbe8 00007fff`eddba2ee : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00300000 : ntdll!NtTerminateThread+0x14
00000093`7e2ffbf0 00007fff`edda0b66 : 00000000`00000000 00007fff`00000000 00000093`7e037000 00000000`00000000 : ntdll!RtlExitUserThread+0x4e
00000093`7e2ffc30 00007fff`ec297974 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!TppWorkerThread+0xbe6
00000093`7e2fff20 00007fff`eddba271 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
00000093`7e2fff50 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21

THREAD_SHA1_HASH_MOD_FUNC:  88bb020a525835c5e4accfc8f28c35273d989009

THREAD_SHA1_HASH_MOD_FUNC_OFFSET:  7bef90b2d84e9e618e99c83f7ca9f82cfcc84797

THREAD_SHA1_HASH_MOD:  9b40081a7a36a12f0ce07177b6b1c87cacd715c7

FOLLOWUP_IP: 
MY_DRIVER!common_sync::SafeGuardedMutex::SafeGuardedMutex+3a [E:\job_src\MYDriver\MY_DRIVER\src\Common\CmSync.hpp @ 16]
fffff803`299e8c6a 488b442430      mov     rax,qword ptr [rsp+30h]

FAULT_INSTR_CODE:  24448b48

FAULTING_SOURCE_LINE:  E:\job_src\MYDriver\MY_DRIVER\src\Common\CmSync.hpp

FAULTING_SOURCE_FILE:  E:\job_src\MYDriver\MY_DRIVER\src\Common\CmSync.hpp

FAULTING_SOURCE_LINE_NUMBER:  16

FAULTING_SOURCE_CODE:  
    12:     class SafeGuardedMutex {
    13:     public:
    14:         SafeGuardedMutex(KGUARDED_MUTEX& guardedMutex): m_guardedMutex{guardedMutex} {
    15:             KeAcquireGuardedMutex(&m_guardedMutex);
>   16:         }
    17:         virtual ~SafeGuardedMutex() {
    18:             KeReleaseGuardedMutex(&m_guardedMutex);
    19:         }
    20: 
    21:     private:

SYMBOL_STACK_INDEX:  a

SYMBOL_NAME:  MY_DRIVER!common_sync::SafeGuardedMutex::SafeGuardedMutex+3a

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: MY_DRIVER

IMAGE_NAME:  MY_DRIVER.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  61078ae8

STACK_COMMAND:  .thread ; .cxr ; kb

BUCKET_ID_FUNC_OFFSET:  3a

FAILURE_BUCKET_ID:  0x139_3_CORRUPT_LIST_ENTRY_MY_DRIVER!common_sync::SafeGuardedMutex::SafeGuardedMutex

BUCKET_ID:  0x139_3_CORRUPT_LIST_ENTRY_MY_DRIVER!common_sync::SafeGuardedMutex::SafeGuardedMutex

PRIMARY_PROBLEM_CLASS:  0x139_3_CORRUPT_LIST_ENTRY_MY_DRIVER!common_sync::SafeGuardedMutex::SafeGuardedMutex

TARGET_TIME:  2021-08-02T06:26:36.000Z

OSBUILD:  17763

OSSERVICEPACK:  0

SERVICEPACK_NUMBER: 0

OS_REVISION: 0

SUITE_MASK:  272

PRODUCT_TYPE:  1

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

OSEDITION:  Windows 10 WinNt TerminalServer SingleUserTS

OS_LOCALE:  

USER_LCID:  0

OSBUILD_TIMESTAMP:  1994-09-30 08:21:45

BUILDDATESTAMP_STR:  180914-1434

BUILDLAB_STR:  rs5_release

BUILDOSVER_STR:  10.0.17763.1.amd64fre.rs5_release.180914-1434

ANALYSIS_SESSION_ELAPSED_TIME:  1f8a

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:0x139_3_corrupt_list_entry_MY_DRIVER!common_sync::safeguardedmutex::safeguardedmutex

FAILURE_ID_HASH:  {448c980e-7da2-7ef1-26cc-7d050d422df6}

Followup:     MachineOwner
---------

only occasionally calling KeAcquireGuardedMutex will give a BSOD

I don’t understand why it appears: A LIST_ENTRY has been corrupted, I have never modified KGUARDED_MUTEX, and it is a synchronous function and should not be released twice

@beforeyouknow said:
I don’t understand why it appears: A LIST_ENTRY has been corrupted, I have never modified KGUARDED_MUTEX, and it is a synchronous function and should not be released twice

automatically released by the c++ destructor

You are making a COPY of the mutex structure. That’s very much a no-no. Your class should be accepting a PKGUARDED_MUTEX and tracking that pointer, not taking a KGUARDED_MUTEX& and making a copy. By making a copy, you will have two structures with the same linked list pointers.

@Tim_Roberts said:
You are making a COPY of the mutex structure. That’s very much a no-no. Your class should be accepting a PKGUARDED_MUTEX and tracking that pointer, not taking a KGUARDED_MUTEX& and making a copy. By making a copy, you will have two structures with the same linked list pointers.

If there is no error in my understanding of C++, the reference should not be copied, it is essentially a pointer (but it can prevent the error of pointer being 0)


  • I made a minimal code example
// class
class MyClass {
public:
    MyClass()  = default;
    ~MyClass() = default;

private:
};

class SafeGuardedMutex {
public:
    SafeGuardedMutex(MyClass& guardedMutex): m_guardedMutex{guardedMutex} {
        printf("guardedMutex: %p,m_guardedMutex: %p\n", &guardedMutex, &m_guardedMutex);
    }
    virtual ~SafeGuardedMutex() {
        printf("m_guardedMutex: %p\n", &m_guardedMutex);
    }

private:
    MyClass& m_guardedMutex;
};

static MyClass mmmMyClass;
void           test_guard() {
    printf("mmmMyClass: %p\n", &mmmMyClass);
    SafeGuardedMutex safeGuardedMutex(mmmMyClass);
}

int main() {
    test_guard();
}

  • outputs
mmmMyClass: 00007FF7ABF44678
guardedMutex: 00007FF7ABF44678,m_guardedMutex: 00007FF7ABF44678
m_guardedMutex: 00007FF7ABF44678

In fact they point to the same memory

1 Like

Not quite, @Tim_Roberts is correct … you’re passing by reference rather than by pointer [https://www.geeksforgeeks.org/passing-by-pointer-vs-passing-by-reference-in-c/], in your code and initializing a new copy of the KGUARDED_MUTEX which then gets its copy constructor called, resulting in a duplication of the pointer backing that object …

class SafeGuardedMutex {
13: public:
14: SafeGuardedMutex(KGUARDED_MUTEX& guardedMutex): m_guardedMutex{guardedMutex} {
15: KeAcquireGuardedMutex(&m_guardedMutex);

16: }

17:         virtual ~SafeGuardedMutex() {
18:             KeReleaseGuardedMutex(&m_guardedMutex);
19:         }
20: 
21:     private

in the class rather than m_guardedMutex be allocated in the ctor instead have that be a pointer to a KGUARDED_MUTEX and in the ctor take the address of the passed in object and set the m_guardedMutex * to that value, that will avoid the copy constructor being called for your m_guardedMutex object and getting double freed …

At least that’s what it looks like to me … :slight_smile:

@craig_howard

in MyClass i added the copy constructor but it was never called.

class MyClass {
public:
    MyClass()  = default;
    ~MyClass() = default;

    MyClass(const MyClass& c) {
        printf("!!!!!! called copy constructor\n");
    }

private:
};

If we look at the assembly instructions, it is still a pointer and has not been copied.

  • test_guard
    image

  • SafeGuardedMutex::SafeGuardedMutex(MyClass &)

image

  • SafeGuardedMutex::~SafeGuardedMutex(void):
    image

I added the reference count.

class SafeGuardedMutex222 {
public:
    SafeGuardedMutex222(KGUARDED_MUTEX& guardedMutex): m_guardedMutex{guardedMutex} {
        InterlockedIncrement64(&m_addcalledCount);
        KeAcquireGuardedMutex(&m_guardedMutex);
    }
    virtual ~SafeGuardedMutex222() {
        InterlockedIncrement64(&m_delcalledCount);
        KeReleaseGuardedMutex(&m_guardedMutex);
    }

private:
    static inline LONG64 volatile m_delcalledCount = 0;
    static inline LONG64 volatile m_addcalledCount = 0;
    KGUARDED_MUTEX& m_guardedMutex;
};

image

m_addcalledCount and m_delcalledCount counts are the same, but crash in the latest call of KeAcquireGuardedMutex

Using reference arguments instead of pointer arguments when the use is
pointer is just obfuscated nonsense. It doesn’t protect against bad pointer
values, it just obscures them.

Your code would be more readable if you just changed your class KGUARDED_MUTEX&
m_guardedMutex to PKGUARDED_MUTEX m_guardedMutex;

So all that said, your existing code for your SafeGuardedMutex is likely
not the problem. But there obviously is a problem with this mutex. So where
did you allocate it? How did you initialize it? Where else is it used?

@Mark_Roddy

  • minimal code example
// not in page seciton
class Worker
{
public:
    Worker() {
        KeInitializeGuardedMutex(m_guardedMutex);
    }
    virtual  ~Worker() = default;
public:

    void do_something() {
        // Sometimes crash here
        SafeGuardedMutex safeGuardedMutex(m_guardedMutex);

        // do something
        // If I comment the function `helloWork`, the BSOD will no longer trigger.
        // I don't understand why, and it is impossible to modify the structure of `m_guardedMutex`
        helloWork();
    }

    void helloWork() {
        // no system api called
        // Just some containers to hold data
    }

private:
    KGUARDED_MUTEX m_guardedMutex{};
};

static Worker g_Worker;

int main() {
    g_Worker.do_something();
}

I’m sure that KeInitializeGuardedMutex has initialized m_guardedMutex

So that is obviously not your kernel code.

There are a few theories that could explain your crash:

  1. your safeguardedmutex class has a bug.
  2. the users of your safeguardedmutex class have bugs that break
    safeguardedmutex.
  3. the windows kernel implementation of guarded mutexes is broken.

I’m tossing out (3) as vanishingly unlikely, for obvious reasons. If you
presented all of your safeguardedmutex code, it does not appear to be
broken, ruling out (1). That leaves (2). If you can’t share your code that
is the likely source of your crash, this forum is unlikely to be of much
help.

Mark Roddy

because I can’t find the reason, i have chosen other ways to avoid this BSOD.