Skip to content

Commit 6ac9d3a

Browse files
committed
Add rendered .qhelp files as .md files.
1 parent 5bada31 commit 6ac9d3a

87 files changed

Lines changed: 3375 additions & 11 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# UnsafeCallInGlobalInit
2+
When using a DLL, it is frequently the case that any static construtors are called from DllMain. There are a number of constraints that apply to calling other functions from DllMain. In particular, it is possible to create memory leaks if the DLL is loaded and unloaded dynamically. SysAllocString is an example of a function that, in this case, could cause a memory leak.
3+
4+
5+
## Recommendation
6+
The ideal DllMain would be just an empty stub. However, given the complexity of many applications, this is generally too restrictive. A good rule of thumb for DllMain is to postpone as much initialization as possible. Lazy initialization increases robustness of the application because this initialization is not performed while the loader lock is held. Also, lazy initialization enables you to safely use much more of the Windows API.
7+
8+
9+
## Example
10+
DLLMain function
11+
12+
```c
13+
14+
BOOL WINAPI DllMain(
15+
HINSTANCE hinstDLL, // handle to DLL module
16+
DWORD fdwReason, // reason for calling function
17+
LPVOID lpvReserved ) // reserved
18+
{
19+
// Perform actions based on the reason for calling.
20+
switch( fdwReason )
21+
{
22+
case DLL_PROCESS_ATTACH:
23+
// Initialize once for each new process.
24+
// Return FALSE to fail DLL load.
25+
break;
26+
27+
case DLL_THREAD_ATTACH:
28+
// Do thread-specific initialization.
29+
break;
30+
31+
case DLL_THREAD_DETACH:
32+
// Do thread-specific cleanup.
33+
break;
34+
35+
case DLL_PROCESS_DETACH:
36+
37+
if (lpvReserved != nullptr)
38+
{
39+
break; // do not do cleanup if process termination scenario
40+
}
41+
42+
// Perform any necessary cleanup.
43+
break;
44+
}
45+
return TRUE; // Successful DLL_PROCESS_ATTACH.
46+
}
47+
}
48+
```
49+
50+
## Semmle-specific notes
51+
52+
53+
54+
## References
55+
* [ C28637 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28637-calling-function-in-a-global-initializer-is-unsafe)

src/drivers/apps/queries/experimental/UnsafeCallInGlobalInit/UnsafeCallInGlobalInit.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
return TRUE; // Successful DLL_PROCESS_ATTACH.
5050
}
5151
}]]>
52-
52+
</sample>
5353
</example>
5454
<semmleNotes>
5555
<p>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Driver alert suppression
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Current function type not correct (C28101)
2+
This function appears to be an unannotated DriverEntry function
3+
4+
5+
## Recommendation
6+
DriverEntry functions should be declared using the DRIVER_INITIALIZE function typedef.
7+
8+
9+
## References
10+
* [ C28101 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28101-wrong-function-type)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Use of default pool tag in memory allocation (C28147)
2+
Memory should not be allocated with the default tags of ' mdW' or ' kdD'.
3+
4+
5+
## Recommendation
6+
The driver is specifying a default pool tag. Because the system tracks pool use by pool tag, only those drivers that use a unique pool tag can identify and distinguish their pool use.
7+
8+
9+
## Example
10+
In this example, the driver allocates memory with the default tag:
11+
12+
```c
13+
14+
PVOID InternalNonPagedAllocator(SIZE_T size) {
15+
return ExAllocatePool3(POOL_FLAG_NON_PAGED, size, ' mdW');
16+
}
17+
18+
```
19+
The driver should use a custom tag instead:
20+
21+
```c
22+
23+
PVOID InternalNonPagedAllocator(SIZE_T size) {
24+
return ExAllocatePool3(POOL_FLAG_NON_PAGED, size, 'vdxE');
25+
}
26+
27+
```
28+
29+
## References
30+
* [ C28147 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28147-improper-use-of-default-pool-tag)
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Driver Entry Save Buffer
2+
The DriverEntry routine should save a copy of the argument, not the pointer, because the I/O Manager frees the buffer
3+
4+
5+
## Recommendation
6+
The driver's DriverEntry routine is saving a copy of the pointer to the buffer instead of saving a copy of the buffer. Because the buffer is freed when the DriverEntry routine returns, the pointer to the buffer will soon be invalid.
7+
8+
9+
## Example
10+
11+
```c
12+
// Copyright (c) Microsoft Corporation.
13+
// Licensed under the MIT license.
14+
//
15+
// driver_snippet.c
16+
//
17+
#include "ntstrsafe.h"
18+
19+
#define SET_DISPATCH 1
20+
// Template. Not called in this test.
21+
void top_level_call() {}
22+
23+
PUNICODE_STRING g_RP1;
24+
25+
NTSTATUS
26+
DriverEntryBad(
27+
PDRIVER_OBJECT DriverObject,
28+
PUNICODE_STRING RegistryPath
29+
)
30+
{
31+
g_RP1 = RegistryPath;
32+
return 0;
33+
}
34+
35+
36+
UNICODE_STRING g_RP2;
37+
38+
NTSTATUS
39+
DriverEntryGood(
40+
PDRIVER_OBJECT DriverObject,
41+
PUNICODE_STRING RegistryPath
42+
)
43+
{
44+
return RtlUnicodeStringCopy(&g_RP2,RegistryPath);
45+
}
46+
47+
48+
UNICODE_STRING g_RP3;
49+
50+
NTSTATUS
51+
DriverEntryGood2(
52+
PDRIVER_OBJECT DriverObject,
53+
PUNICODE_STRING RegistryPath
54+
)
55+
{
56+
g_RP3 = *RegistryPath;
57+
return 0;
58+
}
59+
60+
typedef struct _test_struct {
61+
int a;
62+
PUNICODE_STRING g_RP4;
63+
char b;
64+
} test_struct;
65+
66+
test_struct g_test_struct;
67+
68+
NTSTATUS
69+
DriverEntryBad2(
70+
PDRIVER_OBJECT DriverObject,
71+
PUNICODE_STRING RegistryPath
72+
)
73+
{
74+
test_struct* localPtr = &g_test_struct;
75+
localPtr->g_RP4 = RegistryPath;
76+
return 0;
77+
}
78+
```
79+
80+
## References
81+
* [ C28131 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28131-driverentry-saving-pointer-to-buffer)
82+
83+
## Semmle-specific notes
84+
This rule reports a false positive when the registry path pointer is saved for use in functions such as HidRegisterMinidriver
85+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Return value not examined (C28193)
2+
This warning indicates that the calling function is not checking the value of the specified variable, which was supplied by a function.
3+
4+
5+
## Recommendation
6+
Make sure to check the result of the function that is annotated with _Check_result_ or _Must_check_result.
7+
8+
9+
## Example
10+
In this example, the driver tries to acquire a mutex but does not check the return value. This can cause a concurrency bug.
11+
12+
```c
13+
14+
KeTryToAcquireGuardedMutex(&sharedMutex);
15+
DoDriverWork();
16+
17+
18+
```
19+
The driver should check if the mutex was successfully acquired before using it:
20+
21+
```c
22+
23+
if(KeTryToAcquireGuardedMutex(&sharedMutex))
24+
{
25+
DoDriverWork();
26+
}
27+
else
28+
{
29+
// ...
30+
}
31+
32+
33+
```
34+
35+
## References
36+
* [ Warning C28193 | Microsoft Learn ](https://docs.microsoft.com/en-us/cpp/code-quality/c28193)
37+
38+
## Semmle-specific notes
39+
To reduce noise, this rule only reports violations if more than 75% of the other calls to this function have their return values checked.
40+
41+
Note that this will still report issues if the value is only checked via ASSERTs that are compiled away at release time.
42+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Use of deprecated function or macro (C28719, C28726, C28735, C28750)
2+
Deprecated, insecure APIs should not be used.
3+
4+
5+
## Recommendation
6+
Instead of using deprecated APIs, driver developers should refer to the output of the rule and replace any calls to deprecated APIs with the recommended replacements. These recommendations are based on the MSDN articles for Code Analysis rules C28719, C28726, C28735, and C28750, as linked in the references section below. If no recommended replacement is provided, developers should investigate alternate code or APIs for attaining the same functionality.
7+
8+
Auto-generated WPP TMH headers are likely to flag this rule due to use of tracing APIs that are no longer meant for public use but are safely used in autogenerated code. These results can be ignored.
9+
10+
11+
## Example
12+
The driver attempts to call a deprecated string function:
13+
14+
```c
15+
16+
void example_func(PSTR src)
17+
{
18+
char dst[100];
19+
strcpy(dst, src);
20+
}
21+
22+
23+
```
24+
The driver should use a supported newer function:
25+
26+
```c
27+
28+
void example_func(PSTR src)
29+
{
30+
char dst[100];
31+
strcpy_s(dst, sizeof(dst), src);
32+
}
33+
34+
35+
```
36+
37+
## References
38+
* [ C28719 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28719-banned-api-usage-use-updated-function-replacement)
39+
* [ C28726 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28726-banned-api-usage-use-updated-function-replacement)
40+
* [ C28735 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28735-banned-crimson-api-usage)
41+
* [ C28750 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28750-banned-istrlen-usage)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Float Hardware State Protection
2+
Drivers must protect floating-point hardware state.
3+
4+
5+
## Recommendation
6+
This warning is only applicable in kernel mode. The driver is attempting to use a variable or constant of a float type when the code is not protected by KeSaveFloatingPointState and KeRestoreFloatingPointState, or EngSaveFloatingPointState and EngRestoreFloatingPointState. Display drivers should use EngSaveFloatingPointState and EngRestoreFloatingPointState.
7+
8+
9+
## Example
10+
Function that uses float without protecting floating-point hardware state
11+
12+
```c
13+
14+
void float_used_bad()
15+
{
16+
float f = 0.0f;
17+
f = f + 1.0f;
18+
}
19+
}
20+
21+
```
22+
Function that uses float with protected floating-point hardware state
23+
24+
```c
25+
26+
KFLOATING_SAVE saveData;
27+
NTSTATUS status;
28+
float f = 0.0f;
29+
status = KeSaveFloatingPointState(&saveData);
30+
for (int i = 0; i < 100; i++)
31+
{
32+
f = f + 1.0f;
33+
}
34+
KeRestoreFloatingPointState(&saveData);
35+
}
36+
37+
```
38+
39+
## Semmle-specific notes
40+
41+
42+
43+
## References
44+
* [ Warning C28110 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28110-floating-point-hardware-protect)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Irp stack entry copy
2+
Copying a whole IRP stack entry leaves certain fields initialized that should be cleared or updated
3+
4+
5+
## Recommendation
6+
The driver is copying an IRP improperly. Improperly copying an IRP can cause serious problems with a driver, including loss of data and system crashes. If an IRP must be copied and IoCopyCurrentIrpStackLocationToNext does not suffice, then certain members of the IRP should not be copied or should be zeroed after copying.
7+
8+
9+
## Example
10+
11+
```c
12+
// Copyright (c) Microsoft Corporation.
13+
// Licensed under the MIT license.
14+
//
15+
// driver_snippet.c
16+
//
17+
18+
#define SET_DISPATCH 1
19+
// Template. Not called in this test.
20+
void top_level_call() {}
21+
22+
void bad_irp_copy(
23+
PIRP irp)
24+
{
25+
PIO_STACK_LOCATION irpSp;
26+
PIO_STACK_LOCATION nextIrpSp;
27+
irpSp = IoGetCurrentIrpStackLocation(irp);
28+
nextIrpSp = IoGetNextIrpStackLocation(irp);
29+
RtlCopyMemory(nextIrpSp, irpSp, 0x24);
30+
nextIrpSp->Control = 0;
31+
}
32+
void bad_irp_copy2(
33+
PIRP irp)
34+
{
35+
PIO_STACK_LOCATION irpSp;
36+
PIO_STACK_LOCATION nextIrpSp;
37+
irpSp = IoGetCurrentIrpStackLocation(irp);
38+
nextIrpSp = IoGetNextIrpStackLocation(irp);
39+
RtlCopyMemory(nextIrpSp+4, irpSp+4, FIELD_OFFSET(IO_STACK_LOCATION, DeviceObject)-4);
40+
nextIrpSp->Control = 0;
41+
}
42+
void good_irp_copy(
43+
PIRP irp)
44+
{
45+
IoCopyCurrentIrpStackLocationToNext(irp);
46+
}
47+
48+
```
49+
50+
## References
51+
* [ C28114 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28114-improper-irp-stack-copy)

0 commit comments

Comments
 (0)