LIST_ENTRY

In ntdef.h there is the doubly linked list def for LIST_ENTRY and the kernel mode macros for maintaining and iterating the list.

How can I create such a list in user mode, and pass to the driver using an IRP?
Which header file would I include and which macros would I use?

Thanks

That would be a very bad idea. There are a lot of problems playing with
user mode addresses in a driver, as well as a lot of overhead. Take a look
at the various discussions on METHOD_NEITHER, your scheme is creating all
those problems for every entry in the list. Why do you think you need
something like this?


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

wrote in message news:xxxxx@ntdev…
> In ntdef.h there is the doubly linked list def for LIST_ENTRY and the
> kernel mode macros for maintaining and iterating the list.
>
> How can I create such a list in user mode, and pass to the driver using an
> IRP?
> Which header file would I include and which macros would I use?
>
> Thanks
>

Why do you think that you need to do this?

Passing linked lists to kernel mode from user mode is going to be major pain for proper and secure capture of the data without opening serious security holes.

You should really avoid non-contiguous data structures in user mode to kernel mode communication, and especially data structures that are not bounded in size.

I strongly recommended choosing some other format to indicate your data up to your driver.

  • S

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.co.uk
Sent: Thursday, September 11, 2008 11:24 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] LIST_ENTRY

In ntdef.h there is the doubly linked list def for LIST_ENTRY and the kernel mode macros for maintaining and iterating the list.

How can I create such a list in user mode, and pass to the driver using an IRP?
Which header file would I include and which macros would I use?

Thanks


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

OK heres the lowdown. I have written a basic firewall using WFP. I need to load into the driver a rules table. Initially I wanted two lists stored in the registry, one for inbound allowed ports and one for outbound. In theory I could just load the strings, parse the strings and populate the list. In reality the safe string functions are limited and this was a real headache. Someone on here said I should be passing the list in from user mode using an IRP, hence the question. I am spinning around in small circles on this one, have a firewall all ready to test just can’t get its parameters to it.

need a list of structs like

typedef struct portrules{
int port;
int inboundallowed;
int outbountallowed;
}

so in the driver I can iterate through the list to get the entry for port 80 say, and then do something like

if (portrule.inboundallowed){
//let packet pass
}
else
{
//drop packet
}

Is there any reason that you can’t just format this as a contiguous array when you communicate it to the driver? This is much more preferable to a linked list for validation purposes, and you can in fact just use the standard system buffered IOCTL types for that as well.

  • S

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.co.uk
Sent: Thursday, September 11, 2008 11:38 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] LIST_ENTRY

OK heres the lowdown. I have written a basic firewall using WFP. I need to load into the driver a rules table. Initially I wanted two lists stored in the registry, one for inbound allowed ports and one for outbound. In theory I could just load the strings, parse the strings and populate the list. In reality the safe string functions are limited and this was a real headache. Someone on here said I should be passing the list in from user mode using an IRP, hence the question. I am spinning around in small circles on this one, have a firewall all ready to test just can’t get its parameters to it.

need a list of structs like

typedef struct portrules{
int port;
int inboundallowed;
int outbountallowed;
}

so in the driver I can iterate through the list to get the entry for port 80 say, and then do something like

if (portrule.inboundallowed){
//let packet pass
}
else
{
//drop packet
}


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

Adding some more (emphatic no) to what Skywing has said.

The data structure used by your usermode management tool and by your driver
do not necessarily (nor should they necessarily) be the same. They might
be, they might not be.

However, the data structure used to ‘marshal’ and communicate each ‘row’ in
your table of rules needs to be defined such that it can move across the
user-mode/kernel-mode boundary without address information (pointers).

The suggestion to pack the ‘rule’ table rows into a contiguous, variable
length, self-describing linear buffer is a very good solution.

Consider what happens if you go down the path you are suggesting otherwise
and you suddenly decide that support on 64-bit systems would be nice. Well,
you can avoid a whole lot of headache by having the IOCTL interface be
‘bit-width’ agnostic (meaning you explicitly control the field size of every
field) so that your 32-bit usermode control program can work on either x86
or x64 platforms without change and can compile for ia64 without change.

Moreover, the best form for manipulating the ‘rules’ in the usermode
management code might not be the most efficient form for storing them (and
making search/match/test) in kernel mode. The management tool and the
policy enforcement point (the driver) have completely different goals and
access patterns. It is unlikely that these two separate roles will
‘benefit’ from being tied to each other by a single database structure.

Good Luck,
Dave Cattley
Consulting Engineer
Systems Software Development

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Skywing
Sent: Thursday, September 11, 2008 11:33 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] LIST_ENTRY

Why do you think that you need to do this?

Passing linked lists to kernel mode from user mode is going to be major pain
for proper and secure capture of the data without opening serious security
holes.

You should really avoid non-contiguous data structures in user mode to
kernel mode communication, and especially data structures that are not
bounded in size.

I strongly recommended choosing some other format to indicate your data up
to your driver.

  • S

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.co.uk
Sent: Thursday, September 11, 2008 11:24 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] LIST_ENTRY

In ntdef.h there is the doubly linked list def for LIST_ENTRY and the kernel
mode macros for maintaining and iterating the list.

How can I create such a list in user mode, and pass to the driver using an
IRP?
Which header file would I include and which macros would I use?

Thanks


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

xxxxx@yahoo.co.uk wrote:

In ntdef.h there is the doubly linked list def for LIST_ENTRY and the kernel mode macros for maintaining and iterating the list.

How can I create such a list in user mode, and pass to the driver using an IRP?
Which header file would I include and which macros would I use?

I’ve hesitated long and hard about posting this, because I’m about to
commit a crime that I have often accused others of: answering the
literal question instead of addressing the problem itself. Don and
Skywing are quite correct in pointing out why your proposed architecture
is a bad idea. However, it’s useful enough that I’m going to go ahead.

If you look in the DDK include files, you’ll see that most of the linked
list functions are macros. They don’t rely on any particular kernel
magic. It is quite possible to cut that whole section from wdm.h and
paste it into a user-mode application.

In the typical C++ application, it’s better to use stl::list, but if
that isn’t an option, the LIST_ENTRY macros will work.


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

TCP/UDP port numbers are in the range 0-65535. I would just dynamically
allocate an array of 65536 bytes (or larger datatype if required), one for
each port, that’s not a lot of memory. Especially if used in a critical
path, looking up the settings for a specific port will be much faster (and
much more easy) than iterating through a linked list.

//Daniel

wrote in message news:xxxxx@ntdev…
> In ntdef.h there is the doubly linked list def for LIST_ENTRY and the
> kernel mode macros for maintaining and iterating the list.
>
> How can I create such a list in user mode, and pass to the driver using an
> IRP?
> Which header file would I include and which macros would I use?
>
> Thanks
>

Well yes but the OP asked how he could pass such a list from user mode
to kernel mode, not how he could implement such a list in user mode. The
answer to the literal question is “please don’t do this”.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Thursday, September 11, 2008 1:07 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] LIST_ENTRY

xxxxx@yahoo.co.uk wrote:

In ntdef.h there is the doubly linked list def for LIST_ENTRY and the
kernel mode macros for maintaining and iterating the list.

How can I create such a list in user mode, and pass to the driver
using an IRP?
Which header file would I include and which macros would I use?

I’ve hesitated long and hard about posting this, because I’m about to
commit a crime that I have often accused others of: answering the
literal question instead of addressing the problem itself. Don and
Skywing are quite correct in pointing out why your proposed architecture
is a bad idea. However, it’s useful enough that I’m going to go ahead.

If you look in the DDK include files, you’ll see that most of the linked
list functions are macros. They don’t rely on any particular kernel
magic. It is quite possible to cut that whole section from wdm.h and
paste it into a user-mode application.

In the typical C++ application, it’s better to use stl::list, but if
that isn’t an option, the LIST_ENTRY macros will work.


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


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

The answers are good, but I could really use something more concrete. In my original posts I put code snippets to put my point across. Not wishing to sound ungrateful but the description of a self describing linear buffer is vague to me. That notwithstanding this does sound like string manipulation and as I said in the original post the safe string functions are not ideal for recreating functions such as strtok. I could really use a good shove in the right direction with some code scribbles please. Thanks in advance.

xxxxx@yahoo.co.uk wrote:

The answers are good, but I could really use something more concrete. In my original posts I put code snippets to put my point across. Not wishing to sound ungrateful but the description of a self describing linear buffer is vague to me. That notwithstanding this does sound like string manipulation and as I said in the original post the safe string functions are not ideal for recreating functions such as strtok. I could really use a good shove in the right direction with some code scribbles please. Thanks in advance.

OK, you had written this:

typedef struct portrules{
int port;
int inboundallowed;
int outbountallowed;
}

I presume you were actually thinking of this:

typedef struct portrules{
struct portrules* link;
int port;
int inboundallowed;
int outbountallowed;
}

You can keep that kind of structure in your user-mode app, but when you
send this to kernel, just build it into an array:

struct portrules{
struct portrules* link;
int port;
int inboundallowed;
int outbountallowed;
};

struct portrules_K {
unsigned short port;
unsigned char inboundallowed;
unsigned char outboundallowed;
};

void SendToKernel( struct portrules * head )
{
// Count the number of entries.

int iTotal;
for( portrules * ptr = head; *ptr->link; ptr = *ptr->link )
iTotal++;

// Allocate a structure large enough.

portrules_K * bfr = new portrules_K[iTotal];

// Copy.

int i = 0;
for( portrules * ptr = head; *ptr->link; ptr = *ptr->link, i++ )
{
bfr[i].port = ptr->port;
bfr[i].inboundallowed = ptr->inboundallowed;
bfr[i].outboundallowed = ptr->outboundallowed;
}

// Send.

DeviceIoControl( handle,
IOCTL_SEND_FIREWALL_RULES,
bfr, iTotal * sizeof(portrules_K),

);

delete bfr;
}


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

self describing linear buffer == TLV (Tag, Length, Value)

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.co.uk
Sent: Thursday, September 11, 2008 2:23 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] LIST_ENTRY

The answers are good, but I could really use something more concrete. In
my original posts I put code snippets to put my point across. Not
wishing to sound ungrateful but the description of a self describing
linear buffer is vague to me. That notwithstanding this does sound like
string manipulation and as I said in the original post the safe string
functions are not ideal for recreating functions such as strtok. I could
really use a good shove in the right direction with some code scribbles
please. Thanks in advance.


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

Tim Roberts wrote:


struct portrules{
struct portrules* link;
int port;
int inboundallowed;
int outbountallowed;
};

struct portrules_K {
unsigned short port;
unsigned char inboundallowed;
unsigned char outboundallowed;
};

void SendToKernel( struct portrules * head )
{
// Count the number of entries.

int iTotal;
for( portrules * ptr = head; *ptr->link; ptr = *ptr->link )

Whoops, there are too many stars in that show:
for( portrules * ptr = head; ptr->link; ptr = ptr->link )

iTotal++;

// Allocate a structure large enough.

portrules_K * bfr = new portrules_K[iTotal];

// Copy.

int i = 0;
for( portrules * ptr = head; *ptr->link; ptr = *ptr->link, i++ )

Same thing here.
for( portrules * ptr = head; ptr->link; ptr = ptr->link, i++ )


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

Fair enough. I suggest you look at how the IP Helper routines pass buffers
of information about interfaces, etc. as an example. Or how TDI passes
arrays of addresses. There are lots of examples where well thought out
‘information’ marshalling is demonstrated in the Windows APIs.

Most of the time you will find that:

  1. Everything has a specific bit-width. No ‘compiler knows best’ types
    like ‘int’. INT32 would be better.

  2. Structures always have a length field to identify the ‘version’ of the
    structure. Field addition in future versions is always at the ‘end’ of the
    structure.

  3. Reserved bits (fields, etc.) are well documented and have semantics like
    “if it was reserved, ignore it on read and set it to zero on write”.

  4. Tables (arrays) of fixed length structures (where all structures are the
    same length but you might not know a priori what the length is) are
    described by a structure as a header (which has a ‘length too’), a count of
    elements, and a ‘variable length’ array of elements.

  5. Tables (arrays) of variable length structures (where the structures
    might be differing lengths) are packed together (often with alignment
    padding) by having a field in each structure specify the ‘offset’ to the
    next structure in bytes. It should be clear that this offset is necessary
    and distinct from the ‘length’ field which describes only the size of the
    fixed portion of the structure. That and possible alignment round-up
    requires that a separate ‘offset to next’ field be present.

  6. Structures which themselves logically include variable length data (like
    a UNICODE_STRING) often marshal that to the IO buffer as an offset/length
    pair (or offset/length/maximumLength triple). The offset is typically from
    the start of the structure but can be from most any base you want. Again,
    special care (padding) is often used to ensure correct alignment.

Good Luck,
-dave

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.co.uk
Sent: Thursday, September 11, 2008 2:23 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] LIST_ENTRY

The answers are good, but I could really use something more concrete. In my
original posts I put code snippets to put my point across. Not wishing to
sound ungrateful but the description of a self describing linear buffer is
vague to me. That notwithstanding this does sound like string manipulation
and as I said in the original post the safe string functions are not ideal
for recreating functions such as strtok. I could really use a good shove in
the right direction with some code scribbles please. Thanks in advance.


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

The way I would typically do this would perhaps be like so (error handling omitted):

typedef struct _ENTRY_STRUC
{
ULONG32 Port;
ULONG32 InboundAllowed;
ULONG32 OutboundAllowed;
} ENTRY_STRUC, * PENTRY_STRUC;

typedef const struct _ENTRY_STRUC * PENTRY_STRUC;

typedef struct _MY_STRUC
{
ULONG32 NumEntries;

ENTRY_STRUC Entries[1]; // Variable length based on ``Entries’’
} MY_STRUC, * PMY_STRUC;

typedef const struct _MY_STRUC * PCMY_STRUC;

PMY_STRUC Struc = (PMY_STRUC)new unsigned char[sizeof( MY_STRUC ) - sizeof( ENTRY_STRUC ) + NumEntries * sizeof( ENTRY_STRUC )];

Struc->NumEntries = NumEntries;

for (ULONG32 i = 0; i < NumEntries; i++)
{
memcpy( &Struc->Entries[i], Something, sizeof( ENTRY_STRUC ) );

// Advance ‘Something’ ptr as appropriate
}

//
// Transmit ‘Struc’ to the driver.
// Make sure to size the input buffer length as was done for operator new
//

DeviceIoControl(…);

delete (unsigned char *)Struc;

In your IOCTL handler, you’ll want to verify that MY_STRUC::NumEntries is a valid count of entries given the input buffer length. After that, you can just iterate through each entry in the array. (Assuming you use a buffered type IOCTL, otherwise you need to perform the usual buffer probing and locking with a try/except.)

  • S

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.co.uk
Sent: Thursday, September 11, 2008 2:23 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] LIST_ENTRY

The answers are good, but I could really use something more concrete. In my original posts I put code snippets to put my point across. Not wishing to sound ungrateful but the description of a self describing linear buffer is vague to me. That notwithstanding this does sound like string manipulation and as I said in the original post the safe string functions are not ideal for recreating functions such as strtok. I could really use a good shove in the right direction with some code scribbles please. Thanks in advance.


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 all your firewall needs to do is allow or block traffic based on the port, you don’t even need a driver. You can use the WFP API from user-mode to create filters that take care of that. A driver would be necessary if, for example, you need to look at the payload.

Not sure about that. The WFP functions are in the DDK. I do need to inspect the payload ultimately as I will be reading DNS requests and so forth. Also, I need to use the packet (re)injection functions

The WFP Management functions are defined in user and kernel mode. Take a look at FwpmFilterAdd0 as an example. If you download the Vista Platform SDK, you will find it documented there and prototyped in one of the header files.

If I were designing a firewall from scratch, I would use the usermode API to implement the basic functionality and use a callout driver only for special cases, like the ones you mentioned.

Certainly would allow me to get the basics working wouldn’t it. Good idea. Off to download the SDK. Thanks for the suggestion. :slight_smile: