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

Home NTDEV

Before Posting...

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

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/


Is MmIsAddressValid trigger Page Faults exceptions if a memory is paged out ?

HacksignHacksign Member Posts: 5

Hi there

Summary

I've met some 'strange' problem when access a memory gaining information, sometime target memory contains data I want and sometime it's not.

And it may be caused by pagefile.sys by my investigation.

Proves & Logs

  • Sometime the address is valid and have content I want :

OK STATUS IMAGE

(NOTE: If you can not see the picture, it's here: https://ibb.co/hWPXB50)

As you can see, target memory 0xffff80013141dfc0 is a valid memory.

  • But sometime same address (I have a virtual machine snapshot) is not valid, I thought this memory is paged out to disk:

FAIL STATUS IMAGE

(NOTE: If you can not see the picture, it's here: https://ibb.co/StYh0Y9)

As you can see, target memory 0xffff80013141dfc0 is NOT a valid memory and the !pte output showed a pagefile keyword.

Questions

  1. I have a check statements before accessing this memory, is MmIsAddressValid causing Page Faults exceptions (I need the "memory" actually exists in memory) ?
if (Node->Name.Buffer && MmIsAddressValid(Node->Name.Buffer))
  1. How can I ensure this "memory" is not paged out when I access it ?

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    How can I ensure this "memory" is not paged out when I access it ?

    If you are at PASSIVE_LEVEL, then it doesn't matter. When you access it, it will be paged in.

    If you are at DISPATCH_LEVEL, then you can't safely access it. You need to use MmProbeAndLockPages, which can only be done at PASSIVE_LEVEL. You simply cannot play with paged memory at a raised IRQL.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • HacksignHacksign Member Posts: 5
    edited May 17

    If you are at PASSIVE_LEVEL, then it doesn't matter. When you access it, it will be paged in.

    I'm in PASSIVE_LEVEL, but this logic is an universal logic, so I dont know whether this memory is a illegale memory or it's a paged out memory. Any solutions to detect it ?

    If you are at DISPATCH_LEVEL, then you can't safely access it. You need to use MmProbeAndLockPages, which can only be done at PASSIVE_LEVEL. You simply cannot play with paged memory at a raised IRQL.

    So, below code:

    _OBJECT_TYPE *Node = some_exists_object;
    
    if (Node->Name.Buffer && MmIsAddressValid(Node->Name.Buffer))
    {
        // Position 1
    }
    

    Where Position 1 code will not be execute if Node->Name.Buffer paged out, because MmIsAddressValid(Node->Name.Buffer) will not trigger page in action ?

    According to your solution, I tried lock it, problem seems solved:

    PMDL Mdl = NULL;
    if (Node->Name.Buffer && !MmIsAddressValid(Node->Name.Buffer))
    {
        Mdl = IoAllocateMdl(Node->Name.Buffer, Node->Name.Length, FALSE, FALSE, NULL);
        if (Mdl) MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess);
        // For debug reason, 0xffff80013141dfc0 is fixed
        if (0xffff80013141dfc0 == Node->Name.Buffer)
            DbgPrint("Buffer Invalid: %I64X Mdl: %I64X\r\n", Node->Name.Buffer, Mdl);
    }
    if (Node->Name.Buffer && MmIsAddressValid(Node->Name.Buffer))
    {
        // Do the logic
    }
    if (Mdl)
    {
        MmUnlockPages(Mdl);
        IoFreeMdl(Mdl);
    }
    
  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    As was pointed out to me by the owner if the Memory Manager many years ago, the function MmIsAddressValid is effectively useless in most scenarios. Even if the memory is paged in when it checks, by the time you return the memory could have been paged out. Hence, the functions SHOULD have been called MmWasAddressValidWhenIChecked... which isn't that very useful, right?

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    Repeating myself, if you are at PASSIVE_LEVEL, which you said you are, then paging is totally irrelevant. The behavior is exactly the same as in user-mode. If you touch a page that is paged out, it will be brought in for you, silently. You don't need to worry about it, and you don't need to call ProbeAndLock.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • HacksignHacksign Member Posts: 5

    @Peter_Viscarola_(OSR) said:
    As was pointed out to me by the owner if the Memory Manager many years ago, the function MmIsAddressValid is effectively useless in most scenarios. Even if the memory is paged in when it checks, by the time you return the memory could have been paged out. Hence, the functions SHOULD have been called MmWasAddressValidWhenIChecked... which isn't that very useful, right?

    Peter

    I've tested, when the memory is paged out, MmIsAddressValid will return FALSE, and this function do not trigger PAGE FAULT exception, so the memory will NOT paged back.

  • HacksignHacksign Member Posts: 5
    edited May 18

    @Tim_Roberts said:
    Repeating myself, if you are at PASSIVE_LEVEL, which you said you are, then paging is totally irrelevant. The behavior is exactly the same as in user-mode. If you touch a page that is paged out, it will be brought in for you, silently. You don't need to worry about it, and you don't need to call ProbeAndLock.

    Well, I'm sure I'm in PASSIVE_LEVEL, but this is not the point.

    The point is, I have to check an arbitrary kernel space memory, so before I read data from this arbitrary memory, I have to ensure read operation will not cause BSOD. (I know interrupts comes anytime, memory can be released after check in interrupts, this is not my concern)

    As I said above, MmIsAddressValid do the memory check job, but this function can not trigger PAGE FAULT exception, and it returns FALSE if a memory is paged out.

    The solution, as above described, call MmProbeAndLockPages if a target address seems like an effective kernel space address and MmIsAddressValid returns FALSE in case this memory is a paged out memory.

    I'm sure this thread could be marked as CLOSED (or SOLVED), but I cant find how to do it .....

  • MBond2MBond2 Member Posts: 565

    clearly we have somewhat of a language barrier, but let me see if I can help

    Peter's point is that MmIsAddressValid is a useless function. It does not do what you want, and what it does do is completely useless.

    Tim's point is that if you are at passive level, then you don't need to know if memory is physically resident. If it is not, when you access the memory, a page fault will happen and it will become physically resident. It is only when you are running at IRQL levels that prevent page faults from being handled that you need to ensure memory is physically resident. And that's when you probe and lock it before raising the IRQL from passive to something higher. Probing and locking provides a guarantee that those pages remain resident until unlocked sometime later

    The last part is the most concerning. You cannot safely read data from arbitrary KM memory. It has to be memory that you own in some way. If not, then the real owner can do stuff with it that will cause you to BSOD. If you do own it, then the rules are easy to follow. If not, then nothing you do can be made to be completely safe

  • HacksignHacksign Member Posts: 5

    Peter's point is that MmIsAddressValid is a useless function. It does not do what you want, and what it does do is completely useless.

    Emmm, I've use this function solved numbers of BSOD problems, so it‘s not that useless LOL ~

    The last part is the most concerning. You cannot safely read data from arbitrary KM memory

    This is an ARK module, BSOD is acceptable(I have to access un-documented structures, event if it's not exists in PDB file), what I have to do is try do not trigger BSOD as much as possible.

    Any way, thanks for your summarize~

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,590
    MmIsAddressValid returns false if dereferencing the address would cause a page fault. That’s it. And, given that you don’t own the virtual memory tables, you have the TOCTU problem.

    So, sure, by calling this you avoid crashes caused by dereferencing kernel virtual addresses that are invalid both in hardware and software (I.e. unallocated virtual addresses). But you also avoid dereferencing kernel virtual addresses that are invalid in hardware but logically valid (I.e. a paged out virtual address). That’s by design and why the API is, generally speaking, worthless.

    Use MmCopyMemory instead. I’ve never personally used it but it’s there for what you’re trying to do.

    (Ps: I have no idea what an ARK module is. I did a significant amount of due diligence by asking ChatGPT and it doesn’t know either)

    -scott
    OSR

  • Mark_RoddyMark_Roddy Member - All Emails Posts: 4,628

    MmCopyMemory was and perhaps still is used by hardware platforms that do memory mirroring for fault tolerance.

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,590
    > @Mark_Roddy said:
    > MmCopyMemory was and perhaps still is used by hardware platforms that do memory mirroring for fault tolerance.

    MmCopyMemory or MmDuplicateMemory?

    -scott
    OSR

  • Mark_RoddyMark_Roddy Member - All Emails Posts: 4,628

    Yeah, my mistake - that's mmduplicatememory.

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 19-23 June 2023 Live, Online
Writing WDF Drivers 10-14 July 2023 Live, Online
Kernel Debugging 16-20 October 2023 Live, Online
Developing Minifilters 13-17 November 2023 Live, Online