Skip to content

Commit 528c675

Browse files
IrqlFloatStateMismatch: CodeQL port of C28111 (#161)
* WIP port of C28111 * add sarif diff file * Codeql port of C28111 * updates from review
1 parent 9d62d31 commit 528c675

File tree

5 files changed

+529
-0
lines changed

5 files changed

+529
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
2+
<qhelp>
3+
<overview>
4+
<p>
5+
The IRQL where the floating-point state was saved does not match the current IRQL (for this restore operation).
6+
</p>
7+
</overview>
8+
<recommendation>
9+
<p>
10+
The IRQL at which the driver is executing when it restores a floating-point state is different than the IRQL at which it was executing when it saved the floating-point state.
11+
Because the IRQL at which the driver runs determines how the floating-point state is saved, the driver must be executing at the same IRQL when it calls the functions to save and to restore the floating-point state.
12+
</p>
13+
</recommendation>
14+
<example>
15+
<p>
16+
Example of incorrect code. Floating point state was saved at APC_LEVEL but restored at PASSIVE_LEVEL
17+
</p>
18+
<sample language="c"> <![CDATA[
19+
_IRQL_requires_(PASSIVE_LEVEL)
20+
void driver_utility_bad(void)
21+
{
22+
KIRQL oldIRQL;
23+
KeRaiseIrql(APC_LEVEL, &oldIRQL);
24+
// running at APC level
25+
KFLOATING_SAVE FloatBuf;
26+
if (KeSaveFloatingPointState(&FloatBuf))
27+
{
28+
KeLowerIrql(oldIRQL); // lower back to PASSIVE_LEVEL
29+
// ...
30+
KeRestoreFloatingPointState(&FloatBuf);
31+
}
32+
}
33+
34+
}]]>
35+
</sample>
36+
<p>
37+
Correct example
38+
</p>
39+
<sample language="c"> <![CDATA[
40+
_IRQL_requires_(PASSIVE_LEVEL)
41+
void driver_utility_good(void)
42+
{
43+
// running at APC level
44+
KFLOATING_SAVE FloatBuf;
45+
KIRQL oldIRQL;
46+
KeRaiseIrql(APC_LEVEL, &oldIRQL);
47+
48+
if (KeSaveFloatingPointState(&FloatBuf))
49+
{
50+
KeLowerIrql(oldIRQL);
51+
// ...
52+
KeRaiseIrql(APC_LEVEL, &oldIRQL);
53+
KeRestoreFloatingPointState(&FloatBuf);
54+
}
55+
}
56+
}]]>
57+
</sample>
58+
</example>
59+
<semmleNotes>
60+
<p>
61+
TODO notes
62+
</p>
63+
</semmleNotes>
64+
<references>
65+
<li>
66+
<a href="example.com">
67+
Example link
68+
</a>
69+
</li>
70+
</references>
71+
</qhelp>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
/**
4+
* @id cpp/drivers/irql-float-state-mismatch
5+
* @kind problem
6+
* @name Irql Float State Mismatch
7+
* @description The IRQL where the floating-point state was saved does not match the current IRQL (for this restore operation).
8+
* @platform Desktop
9+
* @feature.area Multiple
10+
* @impact Insecure Coding Practice
11+
* @repro.text The IRQL at which the driver is executing when it restores a floating-point state is different than the IRQL at which it was executing when it saved the floating-point state.
12+
* Because the IRQL at which the driver runs determines how the floating-point state is saved, the driver must be executing at the same IRQL when it calls the functions to save and to restore the floating-point state.
13+
* @owner.email: [email protected]
14+
* @opaqueid CQLD-C28111
15+
* @problem.severity warning
16+
* @precision medium
17+
* @tags correctness
18+
* @scope domainspecific
19+
* @query-version v1
20+
*/
21+
22+
import cpp
23+
import drivers.libraries.Irql
24+
import semmle.code.cpp.dataflow.new.DataFlow
25+
26+
module FloatStateFlowConfig implements DataFlow::ConfigSig {
27+
predicate isSource(DataFlow::Node source) {
28+
exists(FunctionCall fc |
29+
fc.getTarget().getName().matches("KeSaveFloatingPointState") and
30+
source.asIndirectExpr() = fc.getArgument(0)
31+
)
32+
}
33+
34+
predicate isSink(DataFlow::Node sink) {
35+
exists(FunctionCall fc |
36+
fc.getTarget().getName().matches("KeRestoreFloatingPointState") and
37+
sink.asIndirectExpr() = fc.getArgument(0)
38+
)
39+
}
40+
}
41+
42+
module FloatStateFlow = DataFlow::Global<FloatStateFlowConfig>;
43+
44+
from DataFlow::Node source, DataFlow::Node sink, int irqlSink, int irqlSource
45+
where
46+
FloatStateFlow::flow(source, sink) and
47+
irqlSource = getPotentialExitIrqlAtCfn(source.asIndirectExpr()) and
48+
irqlSink = getPotentialExitIrqlAtCfn(sink.asIndirectExpr()) and
49+
irqlSink != irqlSource
50+
select sink.asIndirectExpr(),
51+
"The irql level where the floating-point state was saved (" + irqlSource +
52+
") does not match the irql level for the restore operation (" + irqlSink + ")."

0 commit comments

Comments
 (0)