Beware the shiny light that is MmIsAddressValid


This came up on NTDEV today and has come up in the past (both in the community and internally on the KMDF team).  MmIsAddressValid appears to be a great function given its name.  You pass in a kernel virtual address (VA from now on) and it returns TRUE is the pointer is valid and FALSE otherwise.  It appears that you can use to validate a pointer before accessing it, a function similar to the user mode APIs IsBadReadPtr and IsBadWritePtr.  Unfortunately, this function does nothing of the sort.


So what does it do?  It tells you if a dereference of the VA will result in a page fault or not.  It does not tell you if the VA is valid or not.  MmIsAddressValid will blindly dereference the VA when determining the return value, so the implementation itself does not validate the address (like all other kernel functions).  On some versions of Windows, PagedPool lie within a specific range of addresses, so MmIsAddressvalid can theoritically make a simple value comparison of the VA against that range and return TRUe (this is a drastic simplification, the actual implementation is much more complicated).


What if this function did return whether the VA was valid?  Woudl it still be useful?  The answer is no and for the same reasons that IsBadReadPtr and friends are not useful.  The answer is transitory.  As soon as it returns the result, another thread can execute and free the address (as MSDN states for the user mode APIs).


In conclusion, you need to know the validity of your pointers a priori.  Of course you must validate any user mode pointers you recieve in your driver, but you cannot take a random kernel address and test it for validity.  Like Raymond says, “programming is hard,” and you must be 100% in your code or else BSOD the machine.

Comments (8)

  1. JeffCurless says:

    I’ve always wondered why these functions still exist.  Is there really a valid reason for their use?  Since you can’t trust them anyway, they are pretty worthless.

    -Jeff

  2. doronh says:

    That’s a good question and I poked around. It is used internally in the kernel for checking the state of allocatoins that the kernel owns.  For instance, there is a check to see if the a driver image has been paged out or not.  The value of this function to driver writers is debatable though, but IMO, like many kernel specific functions, they were exported to drivers and the scenario for their use outside the kernel was never clearly defined.

  3. TAG says:

    It’s probably can be also used to fail faster on invalid inputs and give some hints on cause (to user or application).

    Catching access violation exception over large chunck of code and returning it as error code is last resort.

    MmIsAddressValid simply add additonal try/catch for smaller blocks with minimal memory access functionality.

  4. strik says:

    Isn’t MmProbeAndLockPages (http://msdn.microsoft.com/library/en-us/Kernel_r/hh/Kernel_r/k106_ccfec34d-c0f9-4826-81e3-ee967da40677.xml.asp) (with an appropriate try/except block) the function people might want to have used when they call MmIsAddressValid?

  5. doronh says:

    TAG, no you cannot use MmIsAddressValid to validate input.  If you are going to validate a user buffer, you need to use MmProbeAndLockPages.  If you touch an invalid kernel pointer, you will bugcheck regardless of SEH surrounding that access.  Wrapping each pointer access with SEH will also just suppress the error until some other point in time in the driver (and throw out any chance for the compiler to optimize the code around the SEH block).

    strik, yes to validate a user buffer, MmProbeAndLockPages is the right API to call.  My point is that folks get a random KM pointer and want to validate it and MmIsAddressValid does not do that.  

    I think it would be clearer if you think of MmIsAddressValid as MmWillAddressCauseAPageFaultWhenAccessed.

  6. Alex says:

    I that possible to implement  IsBadReadPtr for kernel mode?

  7. doronh says:

    IsBadRead/WritePtr is tricky subject.

    In user mode, both of these APIs should NEVER ever be used. they mask errors and cause corruption very quickly.  

    In kernel mode, there is no such APIs, but when a driver is getting a user mode pointer (as through a METHOD_NEITHER IOCTL or an embedded pointer in an IOCTL input buffer), it must always validate the pointer through a probe call. typically you probe and lock and map the buffer to a kernel mode virtual address so you can use the buffer later outside of the context of the app. at the very least if the driver is going to touch the user mode address directly (in the context of the app only!), the driver needs to access the buffer in a structured exception block (ie SEH, __try / __except) to catch access to an invalid memory address.

    In kernel mode, for kernel mode pointers, you should always know if the pointer is valid or not and never access the kernel address under a SEH block.

    d

  8. Vassili Gorshkov says:

    From what we see MmProbeAndLockPages() will BSOD if used with invalid address too.  So this approach is not good either.