Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# UnsafeCallInGlobalInit
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.


## Recommendation
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.


## Example
DLLMain function

```c

BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;

case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;

case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;

case DLL_PROCESS_DETACH:

if (lpvReserved != nullptr)
{
break; // do not do cleanup if process termination scenario
}

// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}

```

## References
* [ C28637 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28637-calling-function-in-a-global-initializer-is-unsafe)
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,9 @@
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
}]]>

</sample>
</example>
<semmleNotes>
<p>

</p>
</semmleNotes>
<references>
<li>
<a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28637-calling-function-in-a-global-initializer-is-unsafe">
Expand Down
1 change: 1 addition & 0 deletions src/drivers/general/DriverAlertSuppression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Driver alert suppression
44 changes: 44 additions & 0 deletions src/drivers/general/queries/AnnotationSyntax/AnnotationSyntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Annotation syntax error
A syntax error in the annotations was found for the property in the function.


## Recommendation
This warning indicates an error in the annotations, not in the code that is being analyzed.


## Example
_IRQL_saves_global_ not applied to entire function

```c

// FAIL
VOID test1(
_IRQL_saves_global_(OldIrql, *Irql) PKIRQL Irql)
{
// ...
;
}

```
_Kernel_clear_do_init_ not used with either "yes" or "no"

```c

// FAIL
_Function_class_(DRIVER_ADD_DEVICE)
_IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
_Kernel_clear_do_init_(IRP_MJ_CREATE)
NTSTATUS
test4(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PDEVICE_OBJECT PhysicalDeviceObject)

{
; // do nothing
}

```

## References
* [ C28266 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28266-function-property-syntax-error)
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
{
// ...
;
}
}]]>
</sample>
<p>
Expand All @@ -40,14 +39,9 @@

{
; // do nothing
}
}]]>
</sample>
</example>
<semmleNotes>
<p>
</p>
</semmleNotes>
<references>
<li>
<a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28266-function-property-syntax-error">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Current function type not correct (C28101)
This function appears to be an unannotated DriverEntry function


## Recommendation
DriverEntry functions should be declared using the DRIVER_INITIALIZE function typedef.


## References
* [ C28101 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28101-wrong-function-type)
30 changes: 30 additions & 0 deletions src/drivers/general/queries/DefaultPoolTag/DefaultPoolTag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Use of default pool tag in memory allocation (C28147)
Memory should not be allocated with the default tags of ' mdW' or ' kdD'.


## Recommendation
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.


## Example
In this example, the driver allocates memory with the default tag:

```c

PVOID InternalNonPagedAllocator(SIZE_T size) {
return ExAllocatePool3(POOL_FLAG_NON_PAGED, size, ' mdW');
}

```
The driver should use a custom tag instead:

```c

PVOID InternalNonPagedAllocator(SIZE_T size) {
return ExAllocatePool3(POOL_FLAG_NON_PAGED, size, 'vdxE');
}

```

## References
* [ C28147 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28147-improper-use-of-default-pool-tag)
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Driver Entry Save Buffer
The DriverEntry routine should save a copy of the argument, not the pointer, because the I/O Manager frees the buffer


## Recommendation
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.


## Example

```c
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// driver_snippet.c
//
#include "ntstrsafe.h"

#define SET_DISPATCH 1
// Template. Not called in this test.
void top_level_call() {}

PUNICODE_STRING g_RP1;

NTSTATUS
DriverEntryBad(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
g_RP1 = RegistryPath;
return 0;
}


UNICODE_STRING g_RP2;

NTSTATUS
DriverEntryGood(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
return RtlUnicodeStringCopy(&g_RP2,RegistryPath);
}


UNICODE_STRING g_RP3;

NTSTATUS
DriverEntryGood2(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
g_RP3 = *RegistryPath;
return 0;
}

typedef struct _test_struct {
int a;
PUNICODE_STRING g_RP4;
char b;
} test_struct;

test_struct g_test_struct;

NTSTATUS
DriverEntryBad2(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
test_struct* localPtr = &g_test_struct;
localPtr->g_RP4 = RegistryPath;
return 0;
}
```

## References
* [ C28131 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28131-driverentry-saving-pointer-to-buffer)

## Semmle-specific notes
This rule reports a false positive when the registry path pointer is saved for use in functions such as HidRegisterMinidriver

42 changes: 42 additions & 0 deletions src/drivers/general/queries/ExaminedValue/ExaminedValue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Return value not examined (C28193)
This warning indicates that the calling function is not checking the value of the specified variable, which was supplied by a function.


## Recommendation
Make sure to check the result of the function that is annotated with _Check_result_ or _Must_check_result.


## Example
In this example, the driver tries to acquire a mutex but does not check the return value. This can cause a concurrency bug.

```c

KeTryToAcquireGuardedMutex(&sharedMutex);
DoDriverWork();


```
The driver should check if the mutex was successfully acquired before using it:

```c

if(KeTryToAcquireGuardedMutex(&sharedMutex))
{
DoDriverWork();
}
else
{
// ...
}


```

## References
* [ Warning C28193 | Microsoft Learn ](https://docs.microsoft.com/en-us/cpp/code-quality/c28193)

## Semmle-specific notes
To reduce noise, this rule only reports violations if more than 75% of the other calls to this function have their return values checked.

Note that this will still report issues if the value is only checked via ASSERTs that are compiled away at release time.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Use of deprecated function or macro (C28719, C28726, C28735, C28750)
Deprecated, insecure APIs should not be used.


## Recommendation
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.

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.


## Example
The driver attempts to call a deprecated string function:

```c

void example_func(PSTR src)
{
char dst[100];
strcpy(dst, src);
}


```
The driver should use a supported newer function:

```c

void example_func(PSTR src)
{
char dst[100];
strcpy_s(dst, sizeof(dst), src);
}


```

## References
* [ C28719 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28719-banned-api-usage-use-updated-function-replacement)
* [ C28726 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28726-banned-api-usage-use-updated-function-replacement)
* [ C28735 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28735-banned-crimson-api-usage)
* [ C28750 warning - Windows Drivers ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28750-banned-istrlen-usage)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Float Hardware State Protection
Drivers must protect floating-point hardware state.


## Recommendation
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.


## Example
Function that uses float without protecting floating-point hardware state

```c

void float_used_bad()
{
float f = 0.0f;
f = f + 1.0f;
}

```
Function that uses float with protected floating-point hardware state

```c

KFLOATING_SAVE saveData;
NTSTATUS status;
float f = 0.0f;
status = KeSaveFloatingPointState(&saveData);
for (int i = 0; i < 100; i++)
{
f = f + 1.0f;
}
KeRestoreFloatingPointState(&saveData);

```

## References
* [ Warning C28110 ](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/28110-floating-point-hardware-protect)
Loading
Loading