Maxim
Thu Aug 11 20:12:40 CDT 2005
> But just for my knowledge, what is exactly the meaning of "previous" in
> ExGetPreviousMode? The concept is a bit loose in this context.
The mode in which the processor was running before entering the current code
via syscall.
You see - any thread running inside the kernel is either a) system thread, for
which ExGetPreviousMode() == KernelMode and b) user process's thread, which
originated in user mode and entered the kernel code via syscall, page fault or
such.
In this latter case usually ExGetPreviousMode() == UserMode.
But! Note that Windows allows kernel syscalls - i.e. re-entering the kernel
recursively from the kernel mode code by one of the ZwXxx routines, which
generate the trap. Also Windows kernel is partly pageable - can do page faults.
So, in the kernel page fault path, and in the kernel syscall path,
ExGetPreviousMode() == KernelMode.
The practical sense of it is that the kernel syscall caller can specify
kernel-mode pointers and kernel handles to the call, while user mode code
cannot. So, your validation code (if any - most usual IO syscall arguments are
validated by the IO manager itself, but not all - for instance, pointers and
handles inside the IOCTL input buffer are not validated, and your code must do
it itself) must notice this previous mode.
If ExGetPreviousMode() == KernelMode, then you must do NOT do any pointer
validation, and pass KernelMode to MmProbeAndLockPages if you lock this
pointer.
Otherwise, you must do ProbeForRead/Write, and pass UserMode to
MmProbeAndLockPages.
As about the handle validation - pass ExGetPreviousMode result to
ObReferenceObjectByHandle.
Note that in any IRP handling contexts, you must use Irp->RequestorMode instead
of ExGetPreviousMode. It is assigned as:
Irp->RequestorMode = ExGetPreviousMode();
in NtXxxFile functions where the IRP is created.
So, the whole song is - to provide the ability for kernel modules to notice and
reject the case when a user mode code is passing a kernel space pointer to the
syscall. This must be rejected, while the same thing for a kernel mode caller -
must not.
Internally, ExGetPreviousMode is implemented by finding the last trap frame on
the kernel stack and examining the CS segment selector - whether it is
KERNEL_CS constant or USER_CS.
The notion of previous mode is very old, predates Windows at all and is
originated at PDP-11 and RSX-11 OS - later migrated to VAX and VMS (which looks
like direct descendant of RSX-11) without any significant changes. These CPUs
supported this value as hardware flags in the flag register (x86 only exposes
current mode this way, not previous mode).
--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com