Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

BSOD:KERNEL_SECURITY_CHECK_FAILURE

beforeyouknowbeforeyouknow Member Posts: 10
  • 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

Comments

  • beforeyouknowbeforeyouknow Member Posts: 10
    • 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

  • beforeyouknowbeforeyouknow Member Posts: 10

    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

  • beforeyouknowbeforeyouknow Member Posts: 10

    @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

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,093

    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, [email protected]
    Providenza & Boekelheide, Inc.

  • beforeyouknowbeforeyouknow Member Posts: 10
    edited August 3

    @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

  • craig_howardcraig_howard Member Posts: 182
    edited August 3

    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 ... :)

  • beforeyouknowbeforeyouknow Member Posts: 10

    @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:
    };
    
    
    
  • beforeyouknowbeforeyouknow Member Posts: 10

    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
  • beforeyouknowbeforeyouknow Member Posts: 10
    edited August 3

    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

  • Mark_RoddyMark_Roddy Member - All Emails Posts: 4,445
    via Email
    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?
  • beforeyouknowbeforeyouknow Member Posts: 10
    edited August 3

    @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

  • Mark_RoddyMark_Roddy Member - All Emails Posts: 4,445
    via Email
    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
  • beforeyouknowbeforeyouknow Member Posts: 10

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

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Internals & Software Drivers 15 November 2021 Live, Online
Writing WDF Drivers TBD Live, Online
Developing Minifilters 7 February 2022 Live, Online
Kernel Debugging 21 March 2022 Live, Online