Re: How to check if a spin lock has been freed or released?



Barry <gubaoqiang@xxxxxxx> wrote:
> Hi, all,
>
> Since all the four functions NdisAcpuireSpinLock, NdisAllocateSpinLock,
> NdisReleaseSpinLock and NdisFreeSpinLock return VOID, how do I know if a
> spin lock has been freed or released in a NDIS protocol driver?
>
> In other words, what will happen if I call NdisAllocateSpinLock after
> NdisFreeSpinLock in DriverUnload routine? Cause a deadlock or BSOD? or maybe
> the driver could just run without any problem?

For the record, here is how the NDIS spinlock functions map to Windows
kernel spinlock functions:

NdisAllocateSpinLock() -> KeInitializeSpinLock() (initialize lock)
NdisAcquireSpinLock() -> KeAcquireSpinLock() (obtain lock)
NdisReleaseSpinLock() -> KeReleaseSpinLock() (release lock)
NdisFreeSpinLock() -> (nothing -- function is a no-op)

Now, a spinlock is really just an int. And all KeInitializeSpinLock()
does is set it to 0. In reality, NdisAllocateSpinLock() does not allocate
anything. It's up to you to allocate storage for the NDIS_SPIN_LOCK,
and all NdisAllocateSpinLock() does is initialize the structure. And
NdisFreeSpinLock() doesn't do anything.

So, even though it's an incorrect use of the API, you can technically
call NdisFreeSpinLock() any time you like, and it won't have any effect
at all. How do I know this? Because when I implemented the NDIS emulator
for FreeBSD, I struggled for a while to come up with a spinlock
implementation that duplicated the semantics of Windows spinlocks
(without conflicting with FreeBSD's own locking primitives), and I ran
across at least one driver that called NdisFreeSpinLock() incorrectly.
The driver for the ADMtek 802.11b chipset (which was rebadged and sold
by 3Com for a while) would do the following in its MiniportHalt()
handler:

NdisFreeMemory(pAdapter);
NdisFreeSpinLock(pAdapter->mySpinLock);

This is bogus: pAdapter has already been released, so all members of the
pAdapter structure are now invalid, including the spinlock storage. This
is technically a 'touch-after-free' bug. But because NdisFreeSpinLock()
is a no-op in Windows, the bug ends up having no effect. In fact, I suspect
the Microsoft NDIS tester doesn't catch this error (otherwise it would
have shown up before ADMtek released the driver).

At the time, my implementation of NdisFreeSpinLock() actually touched the
spinlock that was passed to it, so in FreeBSD, if you ran a development
kernel with debugging enabled and loaded the ADMtek driver, you'd get a
trap as soon as the MiniportHalt() routine was called. Eventually I
created a spinlock implementation that imitated Windows closely enough
that I could make NdisFreeSpinLock() into a no-op just like it is in
Windows.

So if NdisFreeSpinLock() doesn't do anything, why is it there? To fill
out the API in case someone implements NDIS on an OS where the locking
primitives are different.

In any case, you can mistakenly call NdisFreeSpinLock() any time you
want and it won't break anything. If you call NdisAllocateSpinLock()
at the wrong time, you can break things: it will reset the spinlock
to 0 regardless if someone's already holding it. If you call
NdisAcquireSpinLock() twice in the same thread, the thread will deadlock.

-Bill

--
=============================================================================
-Bill Paul (510) 749-2329 | Senior Engineer, Master of Unix-Fu
wpaul@xxxxxxxxxxxxxxxxxxxxx | Wind River Systems
=============================================================================
<adamw> you're just BEGGING to face the moose
=============================================================================
.



Relevant Pages

  • Re: buildkernel is broken in if_ndis
    ... KeInitializeSpinLock() does is set spinlock = 0. ... Now, the NDIS API has NdisAllocateSpinLock() and NdisFreeSpinLock(), ... NdisAllocateSpinLock() doesn't really allocate anything: ...
    (freebsd-current)
  • Re: How to check if a spin lock has been freed or released?
    ... > Maybe MS should issue some analog of Driver Verifier for ACPI BIOSes ... > lessen the number of hardware able to run Windows). ... >> bugs like NdisFreeSpinLock() misuse would show up immediately during ...
    (microsoft.public.development.device.drivers)
  • Re: How to check if a spin lock has been freed or released?
    ... >> your unload routine you have a crash that is waiting to happen. ... I think there would be no problem to acquire and release spinlock ... >in unload routine as long as I call NdisFreeSpinLock at the end of unload ... observed harmful consequences in acquiring a previously freed spinlock ...
    (microsoft.public.development.device.drivers)
  • Re: How to check if a spin lock has been freed or released?
    ... lessen the number of hardware able to run Windows). ... For Linux and FreeBSD, this can be ... > bugs like NdisFreeSpinLock() misuse would show up immediately during ... KeRaise/LowerIrql, as it is done in uniprocessor NT kernels, but the spinlock ...
    (microsoft.public.development.device.drivers)
  • Re: How to check if a spin lock has been freed or released?
    ... Since all the four functions NdisAcpuireSpinLock, NdisAllocateSpinLock, ... spin lock has been freed or released in a NDIS protocol driver? ... NdisFreeSpinLock in DriverUnload routine? ...
    (microsoft.public.development.device.drivers)