Ioctl question

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver (originally it’s a binary file).

Thank you,

Andrew

----- Original Message -----
From: Andrey Kamchatnikov
To: Windows System Software Devs Interest List
Sent: Wednesday, August 01, 2007 11:41 PM
Subject: [ntdev] Ioctl question

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver (originally it’s a binary file).

Technically, yes. In practice, no. You are basically passing a user level pointer to a driver, and you are not even passing the length of the buffer pointed by Data. You DON’T want to do that, because you would need to validate the pointer in the driver.

If you need to pass a buffer to the driver with an ioctl, pass it directly (with METHOD_BUFFERED), without the use of a structure containing a pointer.

In user mode you would do something like

char mybuffer[256]; //sample buffer, your binary file?
DWORD buffer_length = 256;
DWORD written_bytes;

DeviceIoControl(handle, IOCTL_CODE_XYZ, mybuffer, buffer_length, NULL, 0, &written_bytes, NULL);

Hope it helps
GV


Gianluca Varenni, Windows DDK MVP

CACE Technologies
http://www.cacetech.com

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hello Gianluca,

Thank you for your respond.

I send also the the size of the bin file to the driver
in my struct

typedef struct{

unsigned char * Data;
int DataSize;

}myStruct, *PmyStruct;

In this case it should work, right?

----- Original Message -----
From: Gianluca Varenni
To: Windows System Software Devs Interest List
Sent: Thursday, August 02, 2007 9:03 AM
Subject: Re: [ntdev] Ioctl question

----- Original Message -----
From: Andrey Kamchatnikov
To: Windows System Software Devs Interest List
Sent: Wednesday, August 01, 2007 11:41 PM
Subject: [ntdev] Ioctl question

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver (originally it’s a binary file).

Technically, yes. In practice, no. You are basically passing a user level pointer to a driver, and you are not even passing the length of the buffer pointed by Data. You DON’T want to do that, because you would need to validate the pointer in the driver.

If you need to pass a buffer to the driver with an ioctl, pass it directly (with METHOD_BUFFERED), without the use of a structure containing a pointer.

In user mode you would do something like

char mybuffer[256]; //sample buffer, your binary file?
DWORD buffer_length = 256;
DWORD written_bytes;

DeviceIoControl(handle, IOCTL_CODE_XYZ, mybuffer, buffer_length, NULL, 0, &written_bytes, NULL);

Hope it helps
GV


Gianluca Varenni, Windows DDK MVP

CACE Technologies
http://www.cacetech.com

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Bad idea.

  1. No length parameter means you can’t safely validate the data. Can
    cause overruns and be susceptible to easy attack
  2. Complications for 64-bit.

Since you say its a file, why not pass the filename down instead and
have the kernel process it directly ? Alternative, pass the file
handle from user mode if you don’t want to do the file open in kernel
mode. Another solution might be to memory map the file.

If it’s only simple processing on a small file, send the contents of
the file in the Ioctl as a char array. This is the easiest of them
all to handle in kernel mode.

So many better and safer ways than what you are proposing.

Mark.

At 07:41 AM 8/2/2007, Andrey Kamchatnikov wrote:

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the
driver (originally it’s a binary file).

Thank you,

Andrew

Just to clarify a little bit, the problem is that you are passing a
pointer, whether or not you include the length. This is a problem
because the kernel does not have any way to know how to go about locking
down the memory to which it points. Actually, to be precise, it has no
idea that it is a pointer in the first place. This all assumes that you
are using METHOD_BUFFERED. There are ways to pass pointers like this,
but they are more complicated and you have to do the validation and
locking. For what you are doing, these would probably be overkill and
more work. The best solution to this, in my opinion, is what Mark
suggested last: flatten everything out in to an array. That is, say
your file is 512 bytes long, pass it as char[512]. This poses a problem
in C, as one can not declare arrays dynamically like this directly.
Instead, the common but unattractive work around is to do something like
this:

struct

{

int length;

.

.

.

char data[1];

} TEMP;

char * buffer = new char[sizeof(TEMP) + sizeOfFile];

TEMP * info = (TEMP *) buffer;

Declaring data as having one member satisfies the compiler, and the
casting of the correct size buffer allows you to use the structure
definition.

You don’t want to process the file in kernel mode unless you have
another good reason to do so; doing it just to get around the pointer
issue is, in my opinion, a very bad idea.

Good luck,

mm


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark S. Edwards
Sent: Thursday, August 02, 2007 03:54
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl question

Bad idea.

  1. No length parameter means you can’t safely validate the data. Can
    cause overruns and be susceptible to easy attack
  2. Complications for 64-bit.

Since you say its a file, why not pass the filename down instead and
have the kernel process it directly ? Alternative, pass the file handle
from user mode if you don’t want to do the file open in kernel mode.
Another solution might be to memory map the file.

If it’s only simple processing on a small file, send the contents of the
file in the Ioctl as a char array. This is the easiest of them all to
handle in kernel mode.

So many better and safer ways than what you are proposing.

Mark.

At 07:41 AM 8/2/2007, Andrey Kamchatnikov wrote:

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver
(originally it’s a binary file).

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Something I forgot to mention: Strictly speaking, the expression “new
char[sizeof(TEMP) + sizeOfFile]” is not correct, because it fails to
account for the overlap caused by “char data[1].” In the interest of
simplifying the expression, I left it out the adjustment.

mm


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Martin O’Brien
Sent: Thursday, August 02, 2007 06:56
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Ioctl question

Just to clarify a little bit, the problem is that you are passing a
pointer, whether or not you include the length. This is a problem
because the kernel does not have any way to know how to go about locking
down the memory to which it points. Actually, to be precise, it has no
idea that it is a pointer in the first place. This all assumes that you
are using METHOD_BUFFERED. There are ways to pass pointers like this,
but they are more complicated and you have to do the validation and
locking. For what you are doing, these would probably be overkill and
more work. The best solution to this, in my opinion, is what Mark
suggested last: flatten everything out in to an array. That is, say
your file is 512 bytes long, pass it as char[512]. This poses a problem
in C, as one can not declare arrays dynamically like this directly.
Instead, the common but unattractive work around is to do something like
this:

struct

{

int length;

.

.

.

char data[1];

} TEMP;

char * buffer = new char[sizeof(TEMP) + sizeOfFile];

TEMP * info = (TEMP *) buffer;

Declaring data as having one member satisfies the compiler, and the
casting of the correct size buffer allows you to use the structure
definition.

You don’t want to process the file in kernel mode unless you have
another good reason to do so; doing it just to get around the pointer
issue is, in my opinion, a very bad idea.

Good luck,

mm


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark S. Edwards
Sent: Thursday, August 02, 2007 03:54
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl question

Bad idea.

  1. No length parameter means you can’t safely validate the data. Can
    cause overruns and be susceptible to easy attack
  2. Complications for 64-bit.

Since you say its a file, why not pass the filename down instead and
have the kernel process it directly ? Alternative, pass the file handle
from user mode if you don’t want to do the file open in kernel mode.
Another solution might be to memory map the file.

If it’s only simple processing on a small file, send the contents of the
file in the Ioctl as a char array. This is the easiest of them all to
handle in kernel mode.

So many better and safer ways than what you are proposing.

Mark.

At 07:41 AM 8/2/2007, Andrey Kamchatnikov wrote:

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver
(originally it’s a binary file).

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hi Martin,

Thank you for your explanation.

But how to handle it in driver?

----- Original Message -----
From: Martin O’Brien
To: Windows System Software Devs Interest List
Sent: Thursday, August 02, 2007 12:56 PM
Subject: RE: [ntdev] Ioctl question

Just to clarify a little bit, the problem is that you are passing a pointer, whether or not you include the length. This is a problem because the kernel does not have any way to know how to go about locking down the memory to which it points. Actually, to be precise, it has no idea that it is a pointer in the first place. This all assumes that you are using METHOD_BUFFERED. There are ways to pass pointers like this, but they are more complicated and you have to do the validation and locking. For what you are doing, these would probably be overkill and more work. The best solution to this, in my opinion, is what Mark suggested last: flatten everything out in to an array. That is, say your file is 512 bytes long, pass it as char[512]. This poses a problem in C, as one can not declare arrays dynamically like this directly. Instead, the common but unattractive work around is to do something like this:

struct

{

int length;

.

.

.

char data[1];

} TEMP;

char * buffer = new char[sizeof(TEMP) + sizeOfFile];

TEMP * info = (TEMP *) buffer;

Declaring data as having one member satisfies the compiler, and the casting of the correct size buffer allows you to use the structure definition.

You don’t want to process the file in kernel mode unless you have another good reason to do so; doing it just to get around the pointer issue is, in my opinion, a very bad idea.

Good luck,

mm


From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Mark S. Edwards
Sent: Thursday, August 02, 2007 03:54
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl question

Bad idea.

  1. No length parameter means you can’t safely validate the data. Can cause overruns and be susceptible to easy attack
  2. Complications for 64-bit.

Since you say its a file, why not pass the filename down instead and have the kernel process it directly ? Alternative, pass the file handle from user mode if you don’t want to do the file open in kernel mode. Another solution might be to memory map the file.

If it’s only simple processing on a small file, send the contents of the file in the Ioctl as a char array. This is the easiest of them all to handle in kernel mode.

So many better and safer ways than what you are proposing.

Mark.

At 07:41 AM 8/2/2007, Andrey Kamchatnikov wrote:

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver (originally it’s a binary file).

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

If you are asking the question how to handle the structure Martin suggested
in the driver, this is easy you will get a pointer to the structure and a
length so you can easily access the elements of the array.

If you are asking how to handle the “C” style string as your original
posting, there is no easy safe way to do this. This is the nightmare case
of METHOD_NEITHER argument, and most people cannot get that calling
mechanism right even for non-variable size items. You can do this, but the
odds are you will create a security hole and a maintenance nightmare if you
try.

If you really have to pass this as a pointer, create a user mode DLL that
wraps the call to convert the string to the structure Martin suggested.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

“Andrey Kamchatnikov” wrote in message
news:xxxxx@ntdev…
Hi Martin,

Thank you for your explanation.

But how to handle it in driver?

----- Original Message -----
From: Martin O’Brien
To: Windows System Software Devs Interest List
Sent: Thursday, August 02, 2007 12:56 PM
Subject: RE: [ntdev] Ioctl question

Just to clarify a little bit, the problem is that you are passing a
pointer, whether or not you include the length. This is a problem because
the kernel does not have any way to know how to go about locking down the
memory to which it points. Actually, to be precise, it has no idea that it
is a pointer in the first place. This all assumes that you are using
METHOD_BUFFERED. There are ways to pass pointers like this, but they are
more complicated and you have to do the validation and locking. For what
you are doing, these would probably be overkill and more work. The best
solution to this, in my opinion, is what Mark suggested last: flatten
everything out in to an array. That is, say your file is 512 bytes long,
pass it as char[512]. This poses a problem in C, as one can not declare
arrays dynamically like this directly. Instead, the common but
unattractive work around is to do something like this:

struct

{

int length;

.

.

.

char data[1];

} TEMP;

char * buffer = new char[sizeof(TEMP) + sizeOfFile];

TEMP * info = (TEMP *) buffer;

Declaring data as having one member satisfies the compiler, and the
casting of the correct size buffer allows you to use the structure
definition.

You don’t want to process the file in kernel mode unless you have another
good reason to do so; doing it just to get around the pointer issue is, in
my opinion, a very bad idea.

Good luck,

mm

------------------------------------------------------------------------------

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark S. Edwards
Sent: Thursday, August 02, 2007 03:54
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl question

Bad idea.

1) No length parameter means you can’t safely validate the data. Can
cause overruns and be susceptible to easy attack
2) Complications for 64-bit.

Since you say its a file, why not pass the filename down instead and have
the kernel process it directly ? Alternative, pass the file handle from
user mode if you don’t want to do the file open in kernel mode. Another
solution might be to memory map the file.

If it’s only simple processing on a small file, send the contents of the
file in the Ioctl as a char array. This is the easiest of them all to
handle in kernel mode.

So many better and safer ways than what you are proposing.

Mark.

At 07:41 AM 8/2/2007, Andrey Kamchatnikov wrote:

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to the driver
(originally it’s a binary file).

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I’m not sure what you are asking.


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Andrey
Kamchatnikov
Sent: Thursday, August 02, 2007 12:16
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl question

Hi Martin,

Thank you for your explanation.

But how to handle it in driver?

----- Original Message -----

From: Martin O’Brien mailto:xxxxx

To: Windows System Software Devs Interest List
mailto:xxxxx

Sent: Thursday, August 02, 2007 12:56 PM

Subject: RE: [ntdev] Ioctl question

Just to clarify a little bit, the problem is that you are
passing a pointer, whether or not you include the length. This is a
problem because the kernel does not have any way to know how to go about
locking down the memory to which it points. Actually, to be precise, it
has no idea that it is a pointer in the first place. This all assumes
that you are using METHOD_BUFFERED. There are ways to pass pointers
like this, but they are more complicated and you have to do the
validation and locking. For what you are doing, these would probably be
overkill and more work. The best solution to this, in my opinion, is
what Mark suggested last: flatten everything out in to an array. That
is, say your file is 512 bytes long, pass it as char[512]. This poses a
problem in C, as one can not declare arrays dynamically like this
directly. Instead, the common but unattractive work around is to do
something like this:

struct

{

int length;

.

.

.

char data[1];

} TEMP;

char * buffer = new char[sizeof(TEMP) + sizeOfFile];

TEMP * info = (TEMP *) buffer;

Declaring data as having one member satisfies the compiler, and
the casting of the correct size buffer allows you to use the structure
definition.

You don’t want to process the file in kernel mode unless you
have another good reason to do so; doing it just to get around the
pointer issue is, in my opinion, a very bad idea.

Good luck,

mm

________________________________

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Mark S. Edwards
Sent: Thursday, August 02, 2007 03:54
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl question

Bad idea.

1) No length parameter means you can’t safely validate the data.
Can cause overruns and be susceptible to easy attack
2) Complications for 64-bit.

Since you say its a file, why not pass the filename down instead
and have the kernel process it directly ? Alternative, pass the file
handle from user mode if you don’t want to do the file open in kernel
mode. Another solution might be to memory map the file.

If it’s only simple processing on a small file, send the
contents of the file in the Ioctl as a char array. This is the easiest
of them all to handle in kernel mode.

So many better and safer ways than what you are proposing.

Mark.

At 07:41 AM 8/2/2007, Andrey Kamchatnikov wrote:

Hi,

I have one question regarding Ioctl.

I have a structure:

typedef struct{

unsigned char * Data;

}myStruct, *PmyStruct;

Question: can I use (unsigned char * Data) type to send it to
the driver (originally it’s a binary file).

Thank you,

Andrew


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars
visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars
visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

I recommend you use Martin’s idea of variable-length structures.

Explained in detail on Chen’s blog:
http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx
where he points out that this pattern (while ugly and misleading to those unfamiliar with it) does take care of all alignment issues.

Also, the use of variable-length structures specifically in an ioctl was covered in detail on Doron’s blog:
http://blogs.msdn.com/doronh/archive/2006/12/12/how-to-return-the-number-of-bytes-required-for-a-subsequent-operation.aspx
(although he is focused on getting variable-length data *from* the driver; passing variable-length data *to* the driver is much easier).

-Steve

Andrey Kamchatnikov wrote:

Hi Martin,

Thank you for your explanation.

But how to handle it in driver?

Just like any other ioctl. If you do as others have suggested and pass
the pointer and length as the second buffer parameter to
DeviceIoControl, then it will be passed to the driver as the output
buffer (although it can be used for input as well), in a state that is
safe for the driver to use.

If you pass your own structure with your own pointer, then your driver
will have to lock the pages in memory and convert the user-mode address
to kernel-mode. It is much more error-prone.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

At 05:15 PM 8/2/2007, Andrey Kamchatnikov wrote:

Hi Martin,

Thank you for your explanation.

But how to handle it in driver?

Suggest you study the sample in the WDK, src\general\ioctl, it’s very useful.

Mark.