“Peter Viscarola” wrote in message news:xxxxx@ntdev…
>
>
> “Phil Barila” wrote in message
> news:xxxxx@ntdev…
> >
>
> This is really very useful. I’m sure SNoone is taking it all in for his
> article in the upcoming issue of The NT Insider which will cover precisely
> this topic.
Nice to be good for something…
OK, I’ll try again, I think I’m getting closer.
1. UM create, pass handle:
Several, including some inside MSFT, have said that this works well. This
is the recommended approach in MSKB:Q228785. I haven’t seen any statements
that prescribe how to ensure that the ObReferenceObjectByHandle call is done
in the context of your own UM app. If it can be done, the reference to the
object keeps it from going away with the app, so my previous post was just
wrong on that point. At least one admitted that the caller assumes app
context because it is top level driver. So for drivers below top level, it
appears that you either need to create your own control DO, which makes you
a top-level driver, or you just hope. The latter will obviously bite you
eventually, so it’s really not viable. Or use an alternative, such as the
inverted IOCTL method?
2. UM create named, KM open named:
Looking back at the archive, the most serious drawback of using named events
for app-driver sync is that the UM app has to eventually close the handle to
the event, and when it does, the event is torn down, even when it is created
by the driver. However, with proper care, it seems one can avoid crashing
the driver, though it appears to be very hard to acheive proper care. If
you can avoid crashing while the event is gone, since the UM app is the
creator, when the app restarts, the event is recreated, and things move on.
3. KM create named, UM open named:
Same problem as above, with the additional issue that you must create the
event in the context of the UM app, or the app can’t open it, unless it’s
run with admin priv. It’s also limited to UM app read-only, the app can’t
twiddle the event. Prior to .NET, your driver has to immediately convert
the process-specific handle to a KM handle, while in .NET and later, it
comes back as a KM handle.
4 KM create, pass handle to UM:
Don’t go there. You still have to create in the UM app context, then you
still need to get the reference, or the event is torn down when you close
the handle in app, and the app is still limited to read-only.
> Finally, I would add that NarG isn’t someone with whom I would normally
> disagree. When it comes to matters of the I/O subsystem, he is THE
ultimate
> authority. Thus, it’s possible that even in this case there is some
subtle
> issue he’s thinking about that I’m not seeing.
Well, NarG disagrees with the KB article on this subject, so it will be
interesting to see if he has some additional comment on this thread. It’s
been very enlightening at this end!
I guess I’ll repeat the question buried in the discussion of option 1. Is
there any way to assure you are in UM app context aside from creating a DO
for control purposes, thereby making yourself a top-level driver?
Thanks,
Phil
–
Philip D. Barila
Seagate Technology, LLC
(720) 684-1842
----- Original Message -----
From: “Phil Barila”
Newsgroups: ntdev
To: “NT Developers Interest List”
Sent: Wednesday, September 04, 2002 11:33 AM
Subject: [ntdev] Re: Passing event notification from driver to application
> “Peter Viscarola” wrote in message news:xxxxx@ntdev…
> >
> >
> > “Phil Barila” wrote in message
> > news:xxxxx@ntdev…
> > >
> > > Is it not true that the dispatch entry points are called in the user
app
> > > context, unless the dispatch is called from a system thread?
> >
> > Absolutely not.
>
> Told you I’d drown.
>
> >
> > Any driver that is in a device stack below another driver must only
expect
> > to be called in an arbitrary thread context.
> >
> > Consider a filter above the disk port driver… Is there some reason to
> > expect it will be called in the context of the thread that requested the
> I/O
> > that it is processing?
> >
> > > Is it not also
> > > true that an event created in the user app context will always be
> > visible
> > > to the user app?
> >
> > Always? Well, with some limitations on the meaning of always and
> > barring the metaphysically absurd, I s’pose that’d be hard to debate.
>
> Well yes, but since the first point was bogus, then this point is, more or
> less, irrelevant in this context.
>
> >
> > > Does it not therefore follow that creating the event as a
> > > repsonse to a call from the user app, say an
> > IOCTL_CREATE_MY_PRIVATE_EVENT,
> > > would give your user app an event they can always see?
> > >
> >
> > Well, maybe. You have to ask yourself one question: “Do I feel lucky?”
> > Sure, there “should be no reason” that
> > - the file system that receives that IRP and forwards it to the
> > volume manager,
> > - who forwards it to the disk class driver,
> > - who forwards it to the partition manager,
> > - who forwards it to the disk class driver,
> > - who forwards it to your filter driver…
> >
> > would change context. Then again, there’s nothing that I am aware of
that
> > would prohibit them from doing so.
>
> Of course. I really missed the whole ballpark on this one. That’s why
this
> list is such a cool resource, discussions like this enable learning when
> it’s most effective. Thanks.
>
> >
> > Basing a design on this would make me sort of nervous.
> >
> > Not to mention that in the general case, which was what I was speaking
> about
> > in my previous answer, the driver wasn’t restricted to creating the
event
> in
> > response to an IOCTL. You might choose to create the event in, for
> example,
> > your AddDevice routine… or your Disptach Start Device processing
> function.
> > As Mr. Roddy has pointed out on numerous occaisions, that can lead to
the
> > access issues that SNoone mentioned.
> >
> > Of course, any arbitrary driver could create an added Device Object
(maybe
> > using IoCreateDeviceSecure with a unique GUID) for control use. And,
> > indeed, if that Device Object is directly opened by the application,
there
> > should be no reason the driver’s dispatch routine for that Device Object
> > will not be called in the context of the requesting thread.
> >
> > Hope that makes what I was thinking more clear (that’s one of the
problems
> > with following-up week-old posts… we all kinda lose context).
>
> So here’s how I understand the different options for sync’ing between user
> app and driver. They all seem to have some trade-offs between utility,
> security, and reliability.
>
> 1. Create event in user-mode, pass handle to kernel. David Craig says
this
> works great for him, and the OP in this thread started with this method.
> The downside is that this handle is process specific, and it can be
> troublesome to get a kernel handle to the same event that is valid in an
> arbitrary context. Maybe? the event goes away when the app does, so
driver
> needs to guard against that? Or am I confusing that with another UM->KM
> interaction? Is there another security or stability hole that I missed?
>
The event is passed directly to a symbolic name that is only used for this
communication. The drive letter access to the media is not used for this.
We expect and require that no one put themselves on the symbolic name and
change the context. Could never see any reason someone would want to do
that, but if they did the same rules as apply to a file system filter would
apply to them. They are correct in that if anyone can change the context of
the Ioctl used to pass the event handle, we would fail to get a valid
context free kernal mode handle. I am fond of creating a special device
object just for private communication. It does solve many problems.
Accessing media in drives, HD, floppy, USB, etc. via the normal exported
symbolic links, e.g. A:, B;, etc., works fine, but other special
communications that are more driver wide instead of just a drive letter,
need a special channel. Only Microsoft can put something like this in as in
WMI and other Ioctls we use, but when we try one, something somewhere will
find a way to mess us up.
> 2. Create named event in user-mode, open same named event in kernel mode.
> PGV’s personal preference, if I’m reading the archive right. Really not a
> good idea to pass a name into the driver, lots of pitfalls there.
Downside
> of creating named event in UM is that named events are a security hole
that
> haven’t been patched? I’m not sure about this one.
>
> 3. Create named event in KM, open it in UM. This appears to be
xxxxx@MSFT’s
> preferred method. No apparent security hole, but until .NET server, this
> resulted in process specific handles, which led to the possibility
> (probability?) of creating the event in the system context, which then
> resulted in ACCESS_DENIED when attempting to open in in the UM app, as
> pointed out by SNoone and reinforced by PGV.
>
> 4 Create event in KM, pass handle to UM. Nobody has advocated it, I think
> it’s because the KM address of the event will be off-limits to the UM app
by
> definition? Maybe you could put the event memory in a mapping or some
such
> memory sharing technique, but this seems like it creates a lot more
problems
> than it solves.
>
> So if I’m reading the archive correctly, MS recommends creating named
event
> in KM, opening same event in UM. OSR suggests the reverse. However, as
has
> been discussed before, and repeated by Michal and Mark, named events are a
> potential security hole that is only closed by using PGV’s favorite
> undocumented kernel API.
>
> Am I getting close now?
>
> If I have misrepresented anyone, I am profoundly sorry.
>
> Thanks,
>
> Phil
> –
> Philip D. Barila
> Seagate Technology, LLC
> (720) 684-1842
>
>
>
>
> —
> You are currently subscribed to ntdev as: xxxxx@yoshimuni.com
> To unsubscribe send a blank email to %%email.unsub%%
>
“Phil Barila” wrote in message
news:xxxxx@ntdev…
>
> OK, I’ll try again, I think I’m getting closer.
>
I don’t know, Phil. I think you’re making this wwwwaaaaayyyy harder than it
is.
Events are just standard kernel mode objects. All the normal rules for such
objects apply. There are no special rules. It’s not a mystery. You can
have a handle to an object – Handles are process specific, unless they are
distinguished with OBJ_KERNEL_HANDLE when they are created. They then are
good in kernel mode only and usable in an arbitrary process context. When
you have a handle to an object, that counts as one handle reference.
You may also have a pointer to an object. That counts as one (pointer)
reference. See Mark Cariddi’s GOBJDIR utility, for download on www.osr.com,
for a utility that will show you the handle and pointer reference counts on
any kernel object.
The object doesn’t go away until the reference count is zero.
Again, this is true for ANY sort of kernel object: File objects, Device
objects, and event objects… it’s all the same to the system.
To your summary:
> 1. UM create, pass handle:
All correct. Note that the KB article was written some time before folks
got more “religion” on security-related issues.
>
> 2. UM create named, KM open named:
> Looking back at the archive, the most serious drawback of using named
events
> for app-driver sync is that the UM app has to eventually close the handle
to
> the event, and when it does, the event is torn down, even when it is
created
> by the driver.
>
No, that’s just plain wrong. If the driver opens the event, it’s OPEN.
It’s referenced and it ain’t goin’ away until the ref count goes to zero, no
matter if the user app closes the handle.
> 3. KM create named, UM open named:
> Same problem as above, with the additional issue that you must create the
> event in the context of the UM app, or the app can’t open it, unless it’s
> run with admin priv. It’s also limited to UM app read-only, the app can’t
> twiddle the event.
>
No, the user-mode app is not limited to read-only. Where’s that idea coming
from?
> Prior to .NET, your driver has to immediately convert
> the process-specific handle to a KM handle, while in .NET and later, it
> comes back as a KM handle.
>
> 4 KM create, pass handle to UM:
>
yes.
>
> I guess I’ll repeat the question buried in the discussion of option 1. Is
> there any way to assure you are in UM app context aside from creating a DO
> for control purposes, thereby making yourself a top-level driver?
>
Well, yes. Several. Just apply the “normal” rules for context: “How can I
get myself into the context of a specific thread or process?” Use a worker
thread, previously created in that process context, use KeStackAttachProcess
(file systems), etc, etc. But how much complexity and overhead are you
willing to tolerate to acheive this goal?
Understand, too, that as long as the option chosen is works for use
intended, and that it’s safe from a security perspective, different equally
competent engineers may differ on their preferred implementation. While
some of the approaches are not as good as others, most of them (including
passing a handle from user-mode to kernel-mode) CAN be made to work,
provided you’re clever enough and willing to write enough code.
Peter
OSR
“Peter Viscarola” wrote in message news:xxxxx@ntdev…
>
>
> “Phil Barila” wrote in message
> news:xxxxx@ntdev…
> >
> > OK, I’ll try again, I think I’m getting closer.
> >
>
> I don’t know, Phil. I think you’re making this wwwwaaaaayyyy harder than
it
> is.
Maybe so. Maybe it’s harder because there is some (lots, apparently)
misinformation out there. I haven’t done KM->UM sync before, in fact, I
haven’t had to worry about sync at all, because I did SCSI miniports
exclusively until recently. When you are sync’ed at DIRQL all the time,
this is mostly academic.
Now that I’m expanding my universe, there are more issues to watch, and this
is one that caught my attention. I’m really in favor of the “hanging IOCTL”
approach, since I haven’t yet run into a situation where I would need the
event, but I want to get my head wrapped around it so if I do need it, I’ve
got a reasonable grasp of it. And as you say below, an event is an event,
so it’s good exposure to the event mechanism in general (for me, anyway).
Maybe having the ability to conveniently read everything since OSR took over
the list isn’t always a good thing, but the NNTP interface allows me to
download and keep for an arbitrary length of time everything on the OSR
server, so it’s very convenient for me to search and read the complete
archives, far more than the web search interface.
>
> Events are just standard kernel mode objects. All the normal rules for
such
> objects apply. There are no special rules. It’s not a mystery. You can
> have a handle to an object – Handles are process specific, unless they
are
> distinguished with OBJ_KERNEL_HANDLE when they are created. They then are
> good in kernel mode only and usable in an arbitrary process context. When
> you have a handle to an object, that counts as one handle reference.
>
> You may also have a pointer to an object. That counts as one (pointer)
> reference. See Mark Cariddi’s GOBJDIR utility, for download on
www.osr.com,
> for a utility that will show you the handle and pointer reference counts
on
> any kernel object.
>
> The object doesn’t go away until the reference count is zero.
OK, I buy that until my personal experience says otherwise. Several
messages in the archive state explicitly that their experience is otherwise,
but I don’t know enough to conclusively say that it was an issue of failing
to get the extra ref from the driver so the refcount doesn’t go to zero, or
what.
>
> Again, this is true for ANY sort of kernel object: File objects, Device
> objects, and event objects… it’s all the same to the system.
>
> To your summary:
>
> > 1. UM create, pass handle:
>
> All correct. Note that the KB article was written some time before folks
> got more “religion” on security-related issues.
It would be nice if Microsoft would rewrite or supersede the article with a
new one with current security-driven thinking.
>
> >
> > 2. UM create named, KM open named:
> > Looking back at the archive, the most serious drawback of using named
> events
> > for app-driver sync is that the UM app has to eventually close the
handle
> to
> > the event, and when it does, the event is torn down, even when it is
> created
> > by the driver.
> >
>
> No, that’s just plain wrong. If the driver opens the event, it’s OPEN.
> It’s referenced and it ain’t goin’ away until the ref count goes to zero,
no
> matter if the user app closes the handle.
Several articles in this archive, including some by Bill McKenzie before he
joined OSR, say that when the UM process in which the event was created goes
away, so do all the named events created in that context. If those
articles are wrong, it will be nice to see SNoone’s article clarify all
this.
>
> > 3. KM create named, UM open named:
> > Same problem as above, with the additional issue that you must create
the
> > event in the context of the UM app, or the app can’t open it, unless
it’s
> > run with admin priv. It’s also limited to UM app read-only, the app
can’t
> > twiddle the event.
> >
>
> No, the user-mode app is not limited to read-only. Where’s that idea
coming
> from?
Among other places, that previously referenced KB article says so
explicitly.
>
> > Prior to .NET, your driver has to immediately convert
> > the process-specific handle to a KM handle, while in .NET and later, it
> > comes back as a KM handle.
> >
> > 4 KM create, pass handle to UM:
> >
> yes.
>
> >
> > I guess I’ll repeat the question buried in the discussion of option 1.
Is
> > there any way to assure you are in UM app context aside from creating a
DO
> > for control purposes, thereby making yourself a top-level driver?
> >
>
> Well, yes. Several. Just apply the “normal” rules for context: “How can
I
> get myself into the context of a specific thread or process?” Use a
worker
> thread, previously created in that process context, use
KeStackAttachProcess
> (file systems), etc, etc. But how much complexity and overhead are you
> willing to tolerate to acheive this goal?
OK, sure. I haven’t had to think in such terms, so this is all great
exposure to new stuff for me.
>
> Understand, too, that as long as the option chosen is works for use
> intended, and that it’s safe from a security perspective, different
equally
> competent engineers may differ on their preferred implementation. While
> some of the approaches are not as good as others, most of them (including
> passing a handle from user-mode to kernel-mode) CAN be made to work,
> provided you’re clever enough and willing to write enough code.
I’m not trying to prescribe a single “Everybody do it this way, it’s
best.” I’m trying to sound out the options available in a way that gives
experts an opportunity to correct my thinking, and simultaneously gives some
unknown developer down the road a record the current state of the art (that
you all are willing to reveal, anyway).
Thanks!
Phil
–
Philip D. Barila
Seagate Technology, LLC
(720) 684-1842