{"id":183,"date":"2010-04-18T00:17:31","date_gmt":"2010-04-18T09:17:31","guid":{"rendered":"\/blog\/?p=183"},"modified":"2023-09-21T09:39:13","modified_gmt":"2023-09-21T00:39:13","slug":"ddk-bug-check-0x50-page_fault_in_nonpaged_area-%ec%b6%94%ec%a0%81%eb%b0%a9%eb%b2%95","status":"publish","type":"post","link":"https:\/\/hasu0707.duckdns.org\/blog\/?p=183","title":{"rendered":"[DDK] Bug check 0x50 PAGE_FAULT_IN_NONPAGED_AREA \ucd94\uc801\ubc29\ubc95"},"content":{"rendered":"\n<p><font size=\"2\" face=\"Arial\">What Happened?<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">To understand this bugcheck code, it's first \nnecessary to understand what a \"page fault\" is. If you're not completely sure \nyou understand this concept, read the article <i><a class=\"con_link\" href=\"http:\/\/www.osronline.com\/article.cfm?article=222\" target=\"_blank\" rel=\"noopener\">So, \nExactly What Is A Page Fault<\/a> <\/i>here at OSR Online.<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">The Windows Memory Manager reserves pre-defined \nranges of kernel virtual address space for specific uses. Because the Windows \noperating system utilizes virtual memory, the Memory Manager does not \nnecessarily assign physical memory to every possible kernel virtual address \nwithin its pre-defined ranges. The Memory Manager knows that some of its kernel \nvirtual address ranges are used for pageable memory, and other ranges are used \nfor non-pageable memory. For example, the kernel virtual address space that is \nreserved for use by the non-paged pool is (obviously) part of one of the Memory \nManager's non-pageable address spaces.<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">Whenever the Memory Manager detects a page fault \n(that is, a failure to translate a kernel virtual address to a physical address) \nin one of its pre-assigned address ranges in which the memory is supposed to be \nnon-pageable, it halts system execution with a <b>PAGE_FAULT_IN_NONPAGED_AREA \n<\/b>bugcheck.<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">The only thing that can cause one of these page \nfaults is an inadvertent reference by a kernel mode component to an invalid \nmemory address that just happens to correspond to one of the Memory Manager's \npre-assigned non-pageable address ranges. The most common reason for this \nbugcheck is a driver de-referencing a bad pointer.<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">There are basically innumerable things that can \nhappen that can lead to an invalid memory access, so tracking down these \nbugchecks can sometimes be particularly difficult. Some of the most common \nreasons for these bugchecks are buffer overruns and underruns, or accessing of a \ncompletely bogus address.<\/font><\/p><b>\n<p><font size=\"2\" face=\"Arial\">Who Did It?<\/font><\/p><\/b>\n<p><font size=\"2\" face=\"Arial\">When analyzing these crash dumps, it is either \nimmediately obvious who caused the problem or it can take some serious detective \nwork. The bugcheck parameters for this particular code are the invalid address \nthat was accessed, whether the access was a read or a write, and the address of \nthe instruction that caused the invalid access. Here are some things to think \nabout when analyzing these dumps:<\/font><\/p>\n<blockquote style=\"margin-right: 0px;\" dir=\"ltr\">\n<p><font size=\"2\" face=\"Arial\">1) Why is the address bad? <\/font><\/p>\n<blockquote style=\"margin-right: 0px;\" dir=\"ltr\">\n<p><font size=\"2\" face=\"Arial\">a) Was it previously freed? The <b>!pool <\/b>WinDBG \ncommand can be helpful in determining this. <\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">b) Is this potentially a buffer underrun? A buffer \noverrun? To determine this, you will need to look at how the address is being \nused. If, for example, the address is being used in a copy operation, starting \nyour analysis believing it to be a buffer overrun might not be a bad assumption \n(but just don't forget that it might not be the right assumption!).<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">c) Is the address just completely bogus? The <b>!pool \n<\/b>command is also useful here, as is the <b>!pte \n<\/b>command<\/font><\/p><\/blockquote>\n<p dir=\"ltr\"><font size=\"2\" face=\"Arial\">2) Where did the address being accessed come \nfrom?<\/font><\/p>\n<p dir=\"ltr\"><font size=\"2\" face=\"Arial\">3) At which point did the address become bad? \nWas it previously used successfully by another \ncomponent?<\/font><\/p><\/blockquote>\n<p><font size=\"2\" face=\"Arial\">Using the information gathered from the above steps \nyou can usually begin to get a better idea as to where things went \nwrong.<\/font><\/p><b>\n<p><font size=\"2\" face=\"Arial\">How Should I Fix It?<\/font><\/p><\/b>\n<p><font size=\"2\" face=\"Arial\">Using Driver Verifier and the checked build of \nWindows should allow you to better pinpoint the offending driver in the system. \nIf the driver is not a driver that you have any control over, the only available \noption is disabling the driver until a fixed version is available.<\/font><\/p><b>\n<\/b><p><b><font size=\"2\" face=\"Arial\">Related WinDBG Commands<\/font><\/b><\/p>\n<dir>\n<dir>\n<p><font face=\"Arial\"><font size=\"2\">\u00b7 <\/font><b><font size=\"2\">!pte<\/font><\/b><\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">\u00b7 <\/font><b><font size=\"2\" face=\"Arial\">!pool<\/font><\/b><\/p><\/dir><\/dir>\n<p><b><font size=\"2\" face=\"Arial\">Related Windows O\/S Variables<\/font><\/b><\/p>\n<dir>\n<dir>\n<p><font face=\"Arial\"><font size=\"2\">\u00b7 <\/font><b><font size=\"2\">nt!MmPagedPoolStart \n<\/font><\/b><\/font><\/p>\n<p><font face=\"Arial\"><font size=\"2\">\u00b7 <\/font><b><font size=\"2\">nt!MmPagedPoolEnd \n<\/font><\/b><\/font><\/p>\n<p><font face=\"Arial\"><font size=\"2\">\u00b7 <\/font><b><font size=\"2\">nt!MmNonPagedPoolStart \n<\/font><\/b><\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">\u00b7 <\/font><b><font size=\"2\" face=\"Arial\">nt!MmNonPagedPoolEnd<\/font><\/b><\/p><\/dir><\/dir>\n<p><b><font size=\"2\" face=\"Arial\">An Example<\/font><\/b><\/p>\n<p><font size=\"2\" face=\"Arial\">Here's an example that puts the above guidelines to \nuse and tracks down a misbehaving driver. For clarity, the WinDBG output in this \nexample has been stripped down to the parts important to our \ndiscussion.<\/font><\/p><font size=\"1\" face=\"Courier\">\n<p>PAGE_FAULT_IN_NONPAGED_AREA (50)<\/p>\n<p>Invalid system memory was referenced. This cannot be protected by \ntry-except,<\/p>\n<p>it must be protected by a Probe. Typically the address is just plain bad or \nit<\/p>\n<p>is pointing at freed memory.<\/p>\n<p>Arguments:<\/p>\n<p>Arg1: <b>ff8b6000<\/b>, memory referenced.<\/p>\n<p>Arg2: 00000000, value 0 = read operation, 1 = write operation.<\/p>\n<p>Arg3: 804238fd, If non-zero, the instruction address which referenced the bad \nmemory address.<\/p>\n<p>Arg4: 00000000, (reserved)<\/p>\n<p>...<\/p>\n<p>READ_ADDRESS: <b>ff8b6000 Nonpaged pool<\/b><\/p>\n<p>FAULTING_IP: <\/p>\n<p>nt!IopCompleteRequest+ab<\/p>\n<p>804238fd f3a5 <b>rep movsd<\/b><\/p>\n<p>...<\/p>\n<p>STACK_TEXT: <\/p><b>\n<\/b><p><b>bed4ec7c<\/b> 804b06e7 811bba08 bed4ecc4 bed4ecb8 \nnt!IopCompleteRequest+0xab<\/p>\n<p>bed4eca4 804ac360 8143e4d0 80000005 81158f88 \nnt!IopSynchronousServiceTail+0x8f<\/p>\n<p>bed4ed48 80466389 0000084c 0155f8c8 0155f8b0 \nnt!NtQueryVolumeInformationFile+0x320<\/p>\n<p>bed4ed48 77f8e593 0000084c 0155f8c8 0155f8b0 nt!KiSystemService+0xc9<\/p>\n<p>0155f870 767ebb9f 0000084c 0155f8c8 0155f8b0 \nntdll!ZwQueryVolumeInformationFile+0xb<\/p><\/font>\n<p>OK, so our system bugchecked because we tried to read address 0xFF8B6000, \npresumably while trying to complete an IRP_MJ_QUERY_VOLUME_INFORMATION IRP. The \naddress looks reasonable and the bugcheck info is telling me that the address is \nin the nonpaged address space, so let's see what the debugger says about the \naddress:<\/p><font size=\"1\" face=\"Courier\">\n<p>0: kd&gt; !pool ff8b6000<\/p>\n<p>ff8b6000: Unable to get contents of pool block<\/p><\/font>\n<p><font size=\"2\" face=\"Arial\">That wasn't much help, but because the <b>!pool \n<\/b>command didn't tell me that the address had been freed, I'm going to assume \nthat we're not dealing with a memory access to freed pool. This may be a \ncompletely invalid assumption, but it allows me to move on for the \nmoment.<\/font><\/p><font size=\"1\" face=\"Courier\">\n<p>0: kd&gt; !pte ff8b6000<\/p>\n<p>FF8B6000 - PDE at C0300FF8 PTE at C03FE2D8<\/p>\n<p>contains 01036963 contains 7F8BD000<\/p>\n<p>pfn 1036 G-DA--KWV <b>not valid<\/b><\/p>\n<p>PageFile 0<\/p>\n<p>Offset 7f8bd<\/p>\n<p>Protect: 0<\/p><\/font>\n<p><font size=\"2\" face=\"Arial\">The page table entry for the nonpaged address that we \naccessed is invalid, which is why the system bugchecked. The faulting IP from \nthe bugcheck info is a <b>rep movsd <\/b>instruction, which is a copy instruction \non the x86. So, I'm going to assume for the time being that this bugcheck \noccurred because of a buffer overrun. With that info in hand, I can move on to \nstep two and figure out where the address came from.<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">Looking in the DDK documentation, I see that \nIRP_MJ_QUERY_VOLUME_INFORMATION IRPs all use METHOD_BUFFERED. Therefore, when I \nfind the IRP that is being completed here, its data buffer is going to be at \n<b>Irp-&gt;AssociatedIrp.SystemBuffer<\/b>. Now, unfortunately, the last two \ncalls on the call stack that I've been given aren't documented. This means that \nI have no idea what their parameters are and so I have no idea where to find the \nIRP. Because of that, I have to find the IRP the hard way. Dumping all of the \nmemory contents starting at the last frame's EBP (0xBED4EC7C) and executing the \n<b>!irp <\/b>command on anything that looks like an IRP eventually leads to \nsuccess:<\/font><\/p><font size=\"1\" face=\"Courier\">\n<p>0: kd&gt; !irp 811bb9c8<\/p>\n<p>Irp is active with 1 stacks 3 is current (= 0x811bba80)<\/p>\n<p>No Mdl <b>System buffer =<\/b> <b>ff8b5fe8<\/b> Thread 813ad980: Irp is \ncompleted. <\/p>\n<p>cmd flg cl Device File Completion-Context<\/p>\n<p>[ a, 0] 0 0 8143e4d0 00000000 00000000-00000000 <\/p>\n<p>\\Driver\\<\/p>\n<p>Args: 00000000 00000000 00000000 00000000<\/p><\/font>\n<p><font size=\"2\" face=\"Arial\">That system buffer address looks awfully suspect in \nterms of the address that generated the blue screen, so let's see what we can \nfind out about it:<\/font><\/p><font size=\"1\" face=\"Courier\">\n<p>0: kd&gt; !pool ff8b5fe8 <\/p>\n<p>...<\/p>\n<p>*ff8b5fe0 size: 20 previous size: 20 (Allocated) Process: 81457020<\/p>\n<p>0: kd&gt; ? ff8b5fe0+0x20<\/p>\n<p>Evaluate expression: -7643136 = ff8b6000<\/p><\/font>\n<p><font size=\"2\" face=\"Arial\">I can see here that the allocation that the system \nbuffer address lies in is valid from 0xFF8B5FE0 up to but not including \n0xFF8B6000, the address that killed us. Taking a look at the completion status \nof the IRP:<\/font><\/p><font size=\"1\" face=\"Courier\">\n<p>0: kd&gt; dt nt!_IRP 811bb9c8 \u2013r<\/p>\n<p>...<\/p>\n<p>+0x018 IoStatus : <\/p>\n<p>+0x000 Status : 0x80000005<\/p>\n<p>+0x000 Pointer : 0x80000005 <\/p>\n<p>+0x004 Information : 0x1c<\/p>\n<p>...<\/p><\/font>\n<p><font size=\"2\" face=\"Arial\">Aha! The offending driver in this case has returned \nSTATUS_BUFFER_OVERFLOW with the <b>Information<\/b> field set to the number of \nbytes needed to complete this request. Unfortunately, what this driver writer \ndidn't realize was that STATUS_BUFFER_OVERFLOW is simply an informational \nmessage and the I\/O Manager will go ahead and copy the number of bytes specified \nby <b>Information <\/b>out of the system buffer and into the user's buffer \n(remember, these IRPs are all METHOD_BUFFERED). Note that these are <i>not<\/i> \nthe same semantics that you get when returning the error code \nSTATUS_BUFFER_TOO_SMALL, which is what the developer meant to return. If a \ndriver completes an IRP with that code, the user is returned the number of bytes \nneeded to complete the request but no data is copied. <\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">So, because of this mishap, when the IRP was \ncompleted with <b>IoCompleteRequest<\/b> the I\/O Manager attempted to copy 0x1C \nbytes of data starting at address 0xFF8B5FE8 into the user's buffer, which led \nto a buffer overrun and a <b>PAGE_FAULT_IN_NONPAGED_AREA<\/b> \nbugcheck.<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\"><br \/>&nbsp;<\/font><\/p>\n<p><font size=\"2\" face=\"Arial\">\ucd9c\ucc98 : <a class=\"con_link\" href=\"http:\/\/ssmhz.tistory.com\/170\" target=\"_blank\" rel=\"noopener\">http:\/\/ssmhz.tistory.com\/170\n<\/a><\/font><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What Happened? To understand this bugcheck code, it&#8217;s first necessary to understand what a &#8220;page fault&#8221; is. If you&#8217;re not completely sure you understand this concept, read the article So, Exactly What Is A Page Fault here at OSR Online. The Windows Memory Manager reserves pre-defined ranges of kernel virtual address space for specific uses. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[24],"tags":[],"class_list":["post-183","post","type-post","status-publish","format-standard","hentry","category-development_winddk"],"_links":{"self":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/183","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=183"}],"version-history":[{"count":0,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/183\/revisions"}],"wp:attachment":[{"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=183"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=183"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hasu0707.duckdns.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}