Access Checking for Windows Embedded CE 6.0 Driver Migration

1/6/2010

In Windows CE 5.0 and earlier, MapCallerPtr was used to validate a region of memory pointed to by a pointer parameter. MapCallerPtr was used in the I/O controls (IOCTLs) for a driver to validate a pointer parameter passed by a calling process. Device drivers in Windows CE 5.0 ran with a relatively high privilege, and had adequate access to memory. MapCallerPtr was used to verify both pointer parameters as well as embedded pointers.

In Windows CE 5.0 and earlier, MapPtrToProcess was used by a device driver to gain access to the data in the address space of an application.

In Windows Embedded CE 6.0, the kernel performs a full access check on buffer pointer parameters. This takes the responsibility for pointer parameter validation away from a device driver. However, a driver still must verify that the caller has access to memory addressed by embedded pointers.

It is possible for a malicious application to pass an embedded pointer to a kernel address space and have a driver read or write to the buffer, potentially modifying the kernel. A driver must use the CeOpenCallerBuffer and CeCloseCallerBuffer functions to verify that the caller has access to the memory that is pointed to by embedded pointers.

CeOpenCallerBuffer can be called with the ForceDuplicate parameter set to TRUE. This allocates a temporary heap buffer in the current process. If you choose to copy an input buffer for security purposes, and use CeOpenCallerBuffer for access checking, you can set ForceDuplicate to TRUE. This allows you to perform both the input buffer copy and the access check with one function call.

The following code example shows some of the code changes associated with access checking.

struct MyStruct {
UCHAR *pEmbedded;
DWORD dwSize;
};
// Pre-Windows Embedded CE 6.0
// In XXX_IOControl() Function of the Stream Interface Driver
g_pMappedEmbedded = MapCallerPtr(pInput->pEmbedded, dwSize);
// Fail if g_pMappedEmbedded == NULL
// Now in Windows Embedded CE 6.0
HRESULT hr = E_WASNEVERSET;
hr = CeOpenCallerBuffer((PVOID*) &g_pMappedEmbedded, pInput->pEmbedded, pInput->dwSize, ARG_I_PTR, FALSE);
// Fail if FAILED(hr) == true
// When done with pointer
hr = CeCloseCallerBuffer((PVOID)  g_pMappedEmbedded,   pInput->pEmbedded, pInput->dwSize, ARG_I_PTR);

See Also

Other Resources

Migrating a Windows Embedded CE Driver to Windows Embedded CE 6.0
MapCallerPtr