DeviceIoControl, how to access user space pointer in kernel?

I need to write an IOCTL, For input I want to pass a structure which contains an embedded user-space pointer(memory is allocated in user space) . In Kernel space I want to use the same buffer to copy the response as well.

This is how I want to use, how can I get access to “mystruct.p” in kernel?
I tried using “METHOD_BUFFERED”, when I access “mystruct.p” system crashes.

Application :

char cmd[256]= {some data};

struct mystruct {
char *p;
int length;
}mystruct_t;

mystruct_t *ms = NULL;
ms = alloc();
ms->p = cmd;
ms->len = 256;

DeviceIoControl(…, ms, sizeof(struct(ms)),…); //BUFFERRED_IO
}

Kernel:

p = (mystruct_t *) PtrIrp->AssociatedIrp.SystemBuffer;
buf = (unsigned char *) p->cmd;

for (i=0; i < p->length; i++)
DbgPrint("0x%02x : ", buf[i]); <== this lines crashes.

One more doubt: DbgPrint by default prints “\n” (without specifying it) how can I avoid it?

For input I want to pass a structure which contains an embedded user-space pointer(memory is allocated in user space)

That is a very bad design, in almost all cases. Simply don’t do this.

Peter

Use METHOD_IN_DIRECT, pass the pointer as buffer 2 and provide the length in the ioctl call. That’s the RIGHT way to do this. Depending on how you got there, by the time you get to your driver code, you could be running as part of a different process, where that address is garbage. So,

DeviceIoControl( ..., ms->p, ms->length, ...);
1 Like

Thanks Peter & Tim.
Basically I have to send more than one buffer to driver so I am using a structure.

Here is my use case:
An application layer sends me a command and buffer(cmd-buffer) to store the response (response-buffer, could be more than one)to my code (Hardware abstraction layer) where I do an IOCTL to driver by passing the cmd-buffer and response-buffer pointers.

Driver will read the command take the necessary action and copy the response to the response-buffer.

So I need to pass these application supplied buffer pointers to Driver as is through IOCTL to avoid any buffer copy.

In Linux, I can do a copy_from_user() to each of these buffer pointers…not sure how to do this in Windows…

I am new to Windows…everything looks so confusing here…

DeviceIoControl lets you pass two buffers. The I/O manager will handle all of the details for you to ensure they are properly locked into kernel mode. USE THEM. Don’t pass pointers. Linux makes guarantees about the process context that don’t exist in Windows.

everything looks so confusing here

And when I work in Linux, I am in a perpetual state of befuddlement. How ‘bout that, huh? :wink:

What Tim says. Linux guarantees your driver will be called with the user’s address space mapped. Windows, typically, does not. Regardless, however, even if you WERE being called in the requester’s context… trying to retrieve and validate those pointers would be a bad idea. Trust those of us who’ve been doing this “a while.” You can’t just take your Linux code and map it to Windows… it just doesn’t work that way.

Peter

Thanks Tim & Peter.