首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >IRQL_UNEXPECTED_VALUE BSOD后NdisFIndicateReceiveNetBufferLists?

IRQL_UNEXPECTED_VALUE BSOD后NdisFIndicateReceiveNetBufferLists?
EN

Stack Overflow用户
提问于 2022-02-20 12:54:59
回答 1查看 162关注 0票数 1

我们有一个NDIS驱动程序,只有在很少的系统上,我们在IRQL_UNEXPECTED_VALUE上得到了NdisFIndicateReceiveNetBufferLists,但是在代码的任何部分我们没有提高或降低IRQL,而NdisFIndicateReceiveNetBufferListsirp_mj_device_control回调中被调用。我们还检查了IRQL,如果它的分派,我们将最后一个参数设置为NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL,否则,这会是问题吗?

我还发现这篇文章:

https://knowledge.broadcom.com/external/article/164146/crash-with-bug-check-0xc8-after-installi.html

他们也有类似的问题,问题似乎是有另一个NDIS驱动程序将IRQL提高到DISPATCH_LEVEL,而忘记降低它吗?但我还是不确定这是否适用于我们的问题?这是否也是我们的问题呢?

代码语言:javascript
运行
复制
IRQL_UNEXPECTED_VALUE (c8)
The processor's IRQL is not what it should be at this time.  This is
usually caused by a lower level routine changing IRQL for some period
and not restoring IRQL at the end of that period (eg acquires spinlock
but doesn't release it).
Arguments:
Arg1: 0000000000020002, (Current IRQL << 16) | (Expected IRQL << 8) | UniqueValue
Arg2: fffff82621a444f0, Depends on UniqueValue:
    If UniqueValue is 0 or 1: APC->KernelRoutine.
    If UniqueValue is 2: the callout routine
    If UniqueValue is 3: the interrupt's ServiceRoutine
    If UniqueValue is 0xfe: 1 iff APCs are disabled
Arg3: ffff950cf4dccff0, Depends on UniqueValue:
    If UniqueValue is 0 or 1: APC
    If UniqueValue is 2: the callout's parameter
    If UniqueValue is 3: KINTERRUPT
Arg4: 0000000000000000, Depends on UniqueValue:
    If UniqueValue is 0 or 1: APC->NormalRoutine

呼叫堆栈:

代码语言:javascript
运行
复制
nt!KeBugCheckEx
nt!KeExpandKernelStackAndCalloutInternal
nt!KeExpandKernelStackAndCalloutEx
ndis!ndisInvokeNextReceiveHandler
ndis!ndisFilterIndicateReceiveNetBufferLists
ndis!NdisFIndicateReceiveNetBufferLists
OurNdis

第二个参数是标注例程(基于唯一值),是ndis!ndisDataPathExpandStackCallback

Edit1:

我做了更多的研究,实际上,似乎ndisDataPathExpandStackCallback实际上只是调用了ndisCallReceiveHandler (它没有出现在堆栈中)。我想这只是指示NBL到其他NDIS驱动程序?无论如何,ndisDataPathExpandStackCallback是通过KeExpandKernelStackAndCalloutInternal调用的,后者存储IRQL,并在调用后检查IRQL,如果它不匹配,就会引发错误检查,宾果!

但是,现在我的问题是,我如何才能找到有问题的司机?我能以某种方式使用ndiskd扩展来帮助我哪个NDIS驱动程序调用了KeExpandKernelStackAndCalloutInternal,这样我就可以证明并找到错误的驱动程序了吗?

虽然通过对堆栈的研究,我确实找到了pacer!PcFilterReceiveNetBufferLists,但我怀疑这是一个错误的驱动程序,考虑到它是一个windows驱动程序,对吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-20 20:13:20

他们也有类似的问题,问题似乎是有另一个NDIS驱动程序将IRQL提升到DISPATCH_LEVEL,而忘记降低它呢?但我还是不确定这是否适用于我们的问题?这是否也是我们的问题呢?

这个特别的错误意味着有人在已经解除堆栈的代码中泄漏了IRQL。KeExpandKernelStackAndCalloutInternal正在做这样的事情:

代码语言:javascript
运行
复制
oldIrql = KeGetCurrentIrql();
(*callback)(...);
newIrql = KeGetCurrentIrql();

if (oldIrql != newIrql) {
    KeBugCheckEx(IRQL_UNEXPECTED_VALUE, (newIrql << 16) | (oldIrql << 8) | 2, ...);
}

解码第一个参数,这意味着IRQL在输入时为PASSIVE_LEVEL,在退出时为DISPATCH_LEVEL。

不幸的是,这样做的代码已经运行完--这个错误只是确认他们离开房间之前没有清理过这个地方。通过查看!ndiskd.miniport中的过滤器驱动程序堆栈,您可以对可能运行的代码进行合理的猜测。但这只是给您一个起点:取决于哪些数据包来自网络,网络堆栈可以调用到各种驱动程序中。例如,如果网络指示了一个SMB3数据包,那么执行实际上就会在文件系统堆栈中一直向上走。因此,列出所有可能运行的驱动程序并不容易。

但是,要检查的一件事是,您正确地使用了NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL标志。只有在确定IRQL当前为DISPATCH_LEVEL时,才允许设置标志。如果该标志使用不当,您可能会欺骗其他驱动程序使其与IRQL不匹配。例如,假设的司机可能有:

代码语言:javascript
运行
复制
void FilterReceiveNbls(..., ULONG ReceiveFlags) {
    KIRQL oldIrql;
    KeRaiseCurrentIrql(DISPATCH_LEVEL, &oldIrql);

    . . . do stuff at dispatch level . . .

    if (0 == (ReceiveFlags & NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL)) {
        KeLowerCurrentIrql(oldIrql);
    }
}

我并不是很肯定地说这正是发生的事。我只是在寻找您可以在您的驱动程序中审计的东西,正确使用NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL就是其中之一。请注意,不将此标志添加到ReceiveFlags总是正确的。(事实上,如果您看到其他人设置了该标志,那么清除它甚至是正确的--该标志的唯一好处是非常微小的perf优化。)所以如果你有疑问,就别再加旗子了。

如果启用NDIS/WIFI选项,Windows 11可以严格验证此标志。最简单的方法是在所有驱动程序上启用DV,但是如果运行太慢,您可以选择每个单独的网络驱动程序。在Windows 11上,当使用NDIS/WIFI选项启用DV时,如果任何驱动程序误用任何NDIS_XXX_DISPATCH_LEVEL标志,您将在错误所在的位置得到即时错误检查。

(DV目前并不能验证驱动程序是否将IRQL返回到原来的水平-这是未来的一个好主意。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71194617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档