From f1b0cd2b2b8e066ce60a82181ba6d0e23c257a65 Mon Sep 17 00:00:00 2001 From: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:09:38 -0800 Subject: [PATCH] Role Types Correctly Used Query (#94) * Initial work at IRQL-checking * Significant extra IRQL work. * In-progress work * More puttering around with IRQL * Update to CodeQL 2.14.4 Update cpp-all to 0.9.2, cpp-queries to 0.7.4 * Commit more IRQL code. Needs cleanup. * Some cleanup and minor fixes to entry IRQL evaluation. * Replace old Irql high/low checks with new version and update library. Still needs cleanup. * Irql.qll cleanup * Get rid of old prototype version of IrqlTooLow * Update README.md * Clean up file names * Clean up queries. * Update test script for IRQL queries. * Update build-codeql.yaml Signed-off-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> * Update ported_driver_ca_checks.qls * Add IrqlSetTooHigh/IrqlSetTooLow queries. * Bugfix for IrqlTooHigh/IrqlTooLow The changes to Irql.qll needed for IrqlSetTooHigh, etc. means we are more likely to see IRQL evaluations that return -1. Update queries to exclude those numbers. * Fix test issues for several IRQL checks. * WIP unit tests for IrqlSetTooHigh and IrqlSetTooLow queries * WIP unit tests for IrqlSetTooHigh and IrqlSetTooLow queries * WIP more tests and comments * bug fixes * WIP updates to tests * WIP update tests * remove bad tests. Fix run script to run all tests again. run script now cleans first automatically. * update tests for IrqlSetTooHigh * WIP IrqlSetTooLow tests * Fix typo in Irql.qll * irqlSetTooHigh tests remove calls to KeGetCurrentIRQL as they are not needed * update IrqlSetTooLow tests * update tests. line 90 should be a failling test but isnt * fix IrqlLowerWithFunctionCall1 to call IrqlMinDispatchLowerIrql_fail1 * Revert"fix IrqlLowerWithFunctionCall1 to call IrqlMinDispatchLowerIrql_fail1" This reverts commit fd9084b7f74133647044a813a79fe668c8ee8f6b. * fix IrqlLowerWithFunctionCall1 to call IrqlMinDispatchLowerIrql_fail1 * add WDF function class and structure class * add kmdf callback functions * syntax updates * add comments * Expand WdmDrivers.qll. Add missing WDM Callback Routine types and Role Type class * WIP query to check role types * queries for implicit and explicit role types * move implicit role type query to library as a class * update wdmdrivers.qll * RoleTypeCorrectlyUsed query * WIP * update query * WIP updating wdmdrivers.qll to better define role type functions * update query message * adding KMDF support for role types * updates to role type query for kmdf and wdm * move wdm role type query to wdm folder * WIP library for NDIS * WIP NDIS role type query * WIP storport library * WIP storport query * add irql level to wdm role types * create generic RoleTypes library to include wdm, kmdf, ndis, and storport * generic role type query * add function annotation role types. Add extra role types from wdfroletypes.h * ignore c++ functions for now until codeql issue figured out * update role type query to remove double results * update role type query * update sarif results, diff, and test script * fix conflict in WdmDrivers.qll * remove irql level from role type library due to conflict * fix WdmDrivers.qll * fix wdmdrivers.qll * remove irql library from wdmdrivers.qll * remove old/unused role type queries * Update src/drivers/storport/libraries/StorportDrivers.qll Co-authored-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> Signed-off-by: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> * Update src/drivers/storport/libraries/StorportDrivers.qll Co-authored-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> Signed-off-by: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> * Update src/drivers/storport/libraries/StorportDrivers.qll Co-authored-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> Signed-off-by: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> * Update src/drivers/storport/libraries/StorportDrivers.qll Co-authored-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> Signed-off-by: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> * Update src/drivers/storport/libraries/StorportDrivers.qll Co-authored-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> Signed-off-by: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> * fix issue causing problems with diffs * changes for pull request --------- Signed-off-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> Signed-off-by: Jacob Ronstadt <147542405+jacob-ronstadt@users.noreply.github.com> Co-authored-by: NateD-MSFT <34494373+NateD-MSFT@users.noreply.github.com> --- .../RoleTypeCorrectlyUsed.ql | 39 + .../RoleTypeCorrectlyUsed.qlhelp | 28 + .../RoleTypeCorrectlyUsed.sarif | 172 +++ .../RoleTypeCorrectlyUsed/driver_snippet.c | 10 + .../IrqlSetTooHigh/IrqlSetTooHigh.sarif | 2 +- src/drivers/kmdf/libraries/KmdfDrivers.qll | 987 +++++++++++++++++- src/drivers/libraries/RoleTypes.qll | 222 ++++ src/drivers/ndis/libraries/NdisDrivers.qll | 847 +++++++++++++++ .../storport/libraries/StorportDrivers.qll | 251 +++++ .../test/build_create_analyze_test.cmd | 68 ++ src/drivers/test/diff/ExaminedValue.sarif | 40 +- .../test/diff/IllegalFieldAccess.sarif | 40 +- .../test/diff/IllegalFieldAccess2.sarif | 40 +- src/drivers/test/diff/IllegalFieldWrite.sarif | 40 +- src/drivers/test/diff/IrqlNotSaved.sarif | 40 +- src/drivers/test/diff/IrqlNotUsed.sarif | 40 +- src/drivers/test/diff/IrqlSetTooHigh.sarif | 40 +- src/drivers/test/diff/IrqlTooHigh.sarif | 40 +- src/drivers/test/diff/IrqlTooLow.sarif | 40 +- src/drivers/test/diff/KeWaitLocal.sarif | 40 +- src/drivers/test/diff/MultiplePagedCode.sarif | 40 +- src/drivers/test/diff/NoPagedCode.sarif | 40 +- src/drivers/test/diff/NoPagingSegment.sarif | 40 +- src/drivers/test/diff/OpaqueMdlUse.sarif | 40 +- src/drivers/test/diff/OpaqueMdlWrite.sarif | 40 +- .../test/diff/PendingStatusError.sarif | 40 +- .../test/diff/RoleTypeCorrectlyUsed.sarif | 21 + src/drivers/test/diff/StrSafe.sarif | 40 +- .../diff/WrongDispatchTableAssignment.sarif | 40 +- src/drivers/wdm/libraries/WdmDrivers.qll | 170 ++- 30 files changed, 3135 insertions(+), 402 deletions(-) create mode 100644 src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.ql create mode 100644 src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.qlhelp create mode 100644 src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.sarif create mode 100644 src/drivers/general/queries/RoleTypeCorrectlyUsed/driver_snippet.c create mode 100644 src/drivers/libraries/RoleTypes.qll create mode 100644 src/drivers/ndis/libraries/NdisDrivers.qll create mode 100644 src/drivers/storport/libraries/StorportDrivers.qll create mode 100644 src/drivers/test/build_create_analyze_test.cmd create mode 100644 src/drivers/test/diff/RoleTypeCorrectlyUsed.sarif diff --git a/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.ql b/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.ql new file mode 100644 index 00000000..aa6c5607 --- /dev/null +++ b/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.ql @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * @id cpp/drivers/role-type-correctly-used + * @kind problem + * @name Incorrect Role Type Use + * @description A function is declared with a role type but used as an argument in a function that expects a different role type for that argument. + * @platform Desktop + * @feature.area Multiple + * @impact Insecure Coding Practice + * @repro.text + * @owner.email: sdat@microsoft.com + * @opaqueid CQLD-C28147e + * @problem.severity warning + * @precision medium + * @tags correctness + * @scope domainspecific + * @query-version v1 + */ + +import cpp +import drivers.libraries.RoleTypes +import semmle.code.cpp.TypedefType + +from ImplicitRoleTypeFunction irtf, Function f, string rtActual, string rtExpected +where + irtf.getActualRoleTypeString() != irtf.getExpectedRoleTypeString() and + f = irtf.getFunctionUse().getTarget() and + ( + if f instanceof RoleTypeFunction + then rtActual = f.(RoleTypeFunction).getRoleTypeString() + else rtActual = "" + ) and + rtExpected = irtf.getExpectedRoleTypeString() and + not isEqualRoleTypes(rtExpected, rtActual) +select irtf.getFunctionUse(), + "Function " + f.toString() + " declared with role type " + rtActual + " but role type " + rtExpected + + " is expected." + diff --git a/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.qlhelp b/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.qlhelp new file mode 100644 index 00000000..2fb381b1 --- /dev/null +++ b/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.qlhelp @@ -0,0 +1,28 @@ + + + +

+ Driver entry point functions should be declared with a function role type. +

+
+ +

+ Make sure the role type of the function being used matches the expected role type. +

+
+ + + + +

+ C++ functions not currently supported. See https://github.com/github/codeql/issues/14869 +

+
+ +
  • + + C28158 warning - Windows Drivers + +
  • +
    +
    diff --git a/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.sarif b/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.sarif new file mode 100644 index 00000000..154f1248 --- /dev/null +++ b/src/drivers/general/queries/RoleTypeCorrectlyUsed/RoleTypeCorrectlyUsed.sarif @@ -0,0 +1,172 @@ +{ + "$schema" : "https://json.schemastore.org/sarif-2.1.0.json", + "version" : "2.1.0", + "runs" : [ { + "tool" : { + "driver" : { + "name" : "CodeQL", + "organization" : "GitHub", + "semanticVersion" : "2.14.6", + "notifications" : [ { + "id" : "cpp/baseline/expected-extracted-files", + "name" : "cpp/baseline/expected-extracted-files", + "shortDescription" : { + "text" : "Expected extracted files" + }, + "fullDescription" : { + "text" : "Files appearing in the source archive that are expected to be extracted." + }, + "defaultConfiguration" : { + "enabled" : true + }, + "properties" : { + "tags" : [ "expected-extracted-files", "telemetry" ] + } + } ], + "rules" : [ { + "id" : "cpp/drivers/role-type-correctly-used", + "name" : "cpp/drivers/role-type-correctly-used", + "shortDescription" : { + "text" : "Incorrect Role Type Use" + }, + "fullDescription" : { + "text" : "A function is declared with a role type but used as an argument in a function that expects a different role type for that argument." + }, + "defaultConfiguration" : { + "enabled" : true, + "level" : "warning" + }, + "properties" : { + "tags" : [ "correctness" ], + "description" : "A function is declared with a role type but used as an argument in a function that expects a different role type for that argument.", + "feature.area" : "Multiple", + "id" : "cpp/drivers/role-type-correctly-used", + "impact" : "Insecure Coding Practice", + "kind" : "problem", + "name" : "Incorrect Role Type Use", + "opaqueid" : "CQLD-C28147e", + "owner.email:" : "sdat@microsoft.com", + "platform" : "Desktop", + "precision" : "medium", + "problem.severity" : "warning", + "query-version" : "v1", + "repro.text" : "", + "scope" : "domainspecific" + } + } ] + }, + "extensions" : [ { + "name" : "microsoft/windows-drivers", + "semanticVersion" : "0.2.0+688db58415e76d66f8b04a2bb6931f3d56028174", + "locations" : [ { + "uri" : "file:///C:/codeql-home/Windows-Driver-Developer-Supplemental-Tools/src/", + "description" : { + "text" : "The QL pack root directory." + } + }, { + "uri" : "file:///C:/codeql-home/Windows-Driver-Developer-Supplemental-Tools/src/qlpack.yml", + "description" : { + "text" : "The QL pack definition file." + } + } ] + } ] + }, + "invocations" : [ { + "toolExecutionNotifications" : [ { + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "driver/fail_driver1.c", + "uriBaseId" : "%SRCROOT%", + "index" : 0 + } + } + } ], + "message" : { + "text" : "" + }, + "level" : "none", + "descriptor" : { + "id" : "cpp/baseline/expected-extracted-files", + "index" : 0 + }, + "properties" : { + "formattedMessage" : { + "text" : "" + } + } + }, { + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "driver/driver_snippet.c", + "uriBaseId" : "%SRCROOT%", + "index" : 1 + } + } + } ], + "message" : { + "text" : "" + }, + "level" : "none", + "descriptor" : { + "id" : "cpp/baseline/expected-extracted-files", + "index" : 0 + }, + "properties" : { + "formattedMessage" : { + "text" : "" + } + } + }, { + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "driver/fail_driver1.h", + "uriBaseId" : "%SRCROOT%", + "index" : 2 + } + } + } ], + "message" : { + "text" : "" + }, + "level" : "none", + "descriptor" : { + "id" : "cpp/baseline/expected-extracted-files", + "index" : 0 + }, + "properties" : { + "formattedMessage" : { + "text" : "" + } + } + } ], + "executionSuccessful" : true + } ], + "artifacts" : [ { + "location" : { + "uri" : "driver/fail_driver1.c", + "uriBaseId" : "%SRCROOT%", + "index" : 0 + } + }, { + "location" : { + "uri" : "driver/driver_snippet.c", + "uriBaseId" : "%SRCROOT%", + "index" : 1 + } + }, { + "location" : { + "uri" : "driver/fail_driver1.h", + "uriBaseId" : "%SRCROOT%", + "index" : 2 + } + } ], + "results" : [ ], + "columnKind" : "utf16CodeUnits", + "properties" : { + "semmle.formatSpecifier" : "sarifv2.1.0" + } + } ] +} \ No newline at end of file diff --git a/src/drivers/general/queries/RoleTypeCorrectlyUsed/driver_snippet.c b/src/drivers/general/queries/RoleTypeCorrectlyUsed/driver_snippet.c new file mode 100644 index 00000000..3d55c3ac --- /dev/null +++ b/src/drivers/general/queries/RoleTypeCorrectlyUsed/driver_snippet.c @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//Macros to enable or disable a code section that may or maynot conflict with this test. +#define SET_DISPATCH 1 + +//Template function. Not used for this test. +void top_level_call(){ +} + diff --git a/src/drivers/general/queries/experimental/IrqlSetTooHigh/IrqlSetTooHigh.sarif b/src/drivers/general/queries/experimental/IrqlSetTooHigh/IrqlSetTooHigh.sarif index 35ad3d14..8a73e61c 100644 --- a/src/drivers/general/queries/experimental/IrqlSetTooHigh/IrqlSetTooHigh.sarif +++ b/src/drivers/general/queries/experimental/IrqlSetTooHigh/IrqlSetTooHigh.sarif @@ -422,4 +422,4 @@ "semmle.formatSpecifier" : "sarifv2.1.0" } } ] -} \ No newline at end of file +} diff --git a/src/drivers/kmdf/libraries/KmdfDrivers.qll b/src/drivers/kmdf/libraries/KmdfDrivers.qll index 3aa6e830..0c47e2fd 100644 --- a/src/drivers/kmdf/libraries/KmdfDrivers.qll +++ b/src/drivers/kmdf/libraries/KmdfDrivers.qll @@ -2,21 +2,699 @@ // Licensed under the MIT license. import cpp -/** A typedef for standard KMDF callbacks. This class is incomplete. */ -class KmdfCallbackRoutineTypedef extends TypedefType { - KmdfCallbackRoutineTypedef() { - this.getName().matches("DRIVER_INITIALIZE") or - this.getName().matches("EVT_WDF_DRIVER_DEVICE_ADD") +/** + * A KMDF Typedef type. This class is incomplete. It is used to represent a TypedefType in the KMDF library. + */ +class KmdfRoleTypeType extends TypedefType { + /* Callbacks */ + KmdfRoleTypeType() { + + this.getName().matches("EVT_WDF_CHILD_LIST_CREATE_DEVICE") or + this.getName().matches("EVT_WDF_CHILD_LIST_SCAN_FOR_CHILDREN") or + this.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COPY") or + this.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE") or + this.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE") or + this.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP") or + this.getName().matches("EVT_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_COPY") or + this.getName().matches("EVT_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_DUPLICATE") or + this.getName().matches("EVT_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_CLEANUP") or + this.getName().matches("EVT_WDF_CHILD_LIST_DEVICE_REENUMERATED") or + this.getName().matches("EVT_WDF_DEVICE_SHUTDOWN_NOTIFICATION") or + this.getName().matches("EVT_WDF_DEVICE_FILE_CREATE") or + this.getName().matches("EVT_WDF_FILE_CLOSE") or + this.getName().matches("EVT_WDF_FILE_CLEANUP") or + this.getName().matches("EVT_WDF_DEVICE_PNP_STATE_CHANGE_NOTIFICATION") or + this.getName().matches("EVT_WDF_DEVICE_POWER_STATE_CHANGE_NOTIFICATION") or + this.getName().matches("EVT_WDF_DEVICE_POWER_POLICY_STATE_CHANGE_NOTIFICATION") or + this.getName().matches("EVT_WDF_DEVICE_D0_ENTRY") or + this.getName().matches("EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED") or + this.getName().matches("EVT_WDF_DEVICE_D0_ENTRY_POST_HARDWARE_ENABLED") or + this.getName().matches("EVT_WDF_DEVICE_D0_EXIT") or + this.getName().matches("EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED") or + this.getName().matches("EVT_WDF_DEVICE_D0_EXIT_PRE_HARDWARE_DISABLED") or + this.getName().matches("EVT_WDF_DEVICE_PREPARE_HARDWARE") or + this.getName().matches("EVT_WDF_DEVICE_RELEASE_HARDWARE") or + this.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP") or + this.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_FLUSH") or + this.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT") or + this.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND") or + this.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART") or + this.getName().matches("EVT_WDF_DEVICE_QUERY_STOP") or + this.getName().matches("EVT_WDF_DEVICE_QUERY_REMOVE") or + this.getName().matches("EVT_WDF_DEVICE_SURPRISE_REMOVAL") or + this.getName().matches("EVT_WDF_DEVICE_USAGE_NOTIFICATION") or + this.getName().matches("EVT_WDF_DEVICE_USAGE_NOTIFICATION_EX") or + this.getName().matches("EVT_WDF_DEVICE_RELATIONS_QUERY") or + this.getName().matches("EVT_WDF_DEVICE_ARM_WAKE_FROM_S0") or + this.getName().matches("EVT_WDF_DEVICE_ARM_WAKE_FROM_SX") or + this.getName().matches("EVT_WDF_DEVICE_ARM_WAKE_FROM_SX_WITH_REASON") or + this.getName().matches("EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0") or + this.getName().matches("EVT_WDF_DEVICE_DISARM_WAKE_FROM_SX") or + this.getName().matches("EVT_WDF_DEVICE_WAKE_FROM_S0_TRIGGERED") or + this.getName().matches("EVT_WDF_DEVICE_WAKE_FROM_SX_TRIGGERED") or + this.getName().matches("EVT_WDFDEVICE_WDM_IRP_PREPROCESS") or + this.getName().matches("EVT_WDFDEVICE_WDM_IRP_DISPATCH") or + this.getName().matches("EVT_WDF_IO_IN_CALLER_CONTEXT") or + this.getName().matches("EVT_WDFDEVICE_WDM_POST_PO_FX_REGISTER_DEVICE") or + this.getName().matches("EVT_WDFDEVICE_WDM_PRE_PO_FX_UNREGISTER_DEVICE") or + this.getName().matches("EVT_WDF_DMA_ENABLER_FILL") or + this.getName().matches("EVT_WDF_DMA_ENABLER_FLUSH") or + this.getName().matches("EVT_WDF_DMA_ENABLER_ENABLE") or + this.getName().matches("EVT_WDF_DMA_ENABLER_DISABLE") or + this.getName().matches("EVT_WDF_DMA_ENABLER_SELFMANAGED_IO_START") or + this.getName().matches("EVT_WDF_DMA_ENABLER_SELFMANAGED_IO_STOP") or + this.getName().matches("EVT_WDF_PROGRAM_DMA") or + this.getName().matches("EVT_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL") or + this.getName().matches("EVT_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE") or + this.getName().matches("EVT_WDF_RESERVE_DMA") or + this.getName().matches("EVT_WDF_DPC") or + this.getName().matches("EVT_WDF_DRIVER_DEVICE_ADD") or + this.getName().matches("EVT_WDF_DRIVER_UNLOAD") or + this.getName().matches("EVT_WDF_TRACE_CALLBACK") or + this.getName().matches("EVT_WDF_DEVICE_FILTER_RESOURCE_REQUIREMENTS") or + this.getName().matches("EVT_WDF_DEVICE_REMOVE_ADDED_RESOURCES") or + this.getName().matches("EVT_WDF_INTERRUPT_ISR") or + this.getName().matches("EVT_WDF_INTERRUPT_SYNCHRONIZE") or + this.getName().matches("EVT_WDF_INTERRUPT_DPC") or + this.getName().matches("EVT_WDF_INTERRUPT_WORKITEM") or + this.getName().matches("EVT_WDF_INTERRUPT_ENABLE") or + this.getName().matches("EVT_WDF_INTERRUPT_DISABLE") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_DEFAULT") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_STOP") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_RESUME") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_READ") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_WRITE") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL") or + this.getName().matches("EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE") or + this.getName().matches("EVT_WDF_IO_QUEUE_STATE") or + this.getName().matches("EVT_WDF_IO_ALLOCATE_RESOURCES_FOR_RESERVED_REQUEST") or + this.getName().matches("EVT_WDF_IO_ALLOCATE_REQUEST_RESOURCES") or + this.getName().matches("EVT_WDF_IO_WDM_IRP_FOR_FORWARD_PROGRESS") or + this.getName().matches("EVT_WDF_IO_TARGET_QUERY_REMOVE") or + this.getName().matches("EVT_WDF_IO_TARGET_REMOVE_CANCELED") or + this.getName().matches("EVT_WDF_IO_TARGET_REMOVE_COMPLETE") or + this.getName().matches("EVT_WDF_%_CONTEXT_CLEANUP%") or + this.getName().matches("EVT_WDF_%_CONTEXT_DESTROY%") or + this.getName().matches("EVT_WDF_DEVICE_RESOURCES_QUERY") or + this.getName().matches("EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY") or + this.getName().matches("EVT_WDF_DEVICE_EJECT") or + this.getName().matches("EVT_WDF_DEVICE_SET_LOCK") or + this.getName().matches("EVT_WDF_DEVICE_ENABLE_WAKE_AT_BUS") or + this.getName().matches("EVT_WDF_DEVICE_DISABLE_WAKE_AT_BUS") or + this.getName().matches("EVT_WDF_DEVICE_REPORTED_MISSING") or + this.getName().matches("EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST") or + this.getName().matches("EVT_WDF_REQUEST_CANCEL") or + this.getName().matches("EVT_WDF_REQUEST_COMPLETION_ROUTINE") or + this.getName().matches("EVT_WDF_TIMER") or + this.getName().matches("EVT_WDF_USB_READER_COMPLETION_ROUTINE") or + this.getName().matches("EVT_WDF_USB_READERS_FAILED") or + this.getName().matches("EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE") or + this.getName().matches("EVT_WDF_WMI_INSTANCE_SET_INSTANCE") or + this.getName().matches("EVT_WDF_WMI_INSTANCE_SET_ITEM") or + this.getName().matches("EVT_WDF_WMI_INSTANCE_EXECUTE_METHOD") or + this.getName().matches("EVT_WDF_WMI_PROVIDER_FUNCTION_CONTROL") or + this.getName().matches("EVT_WDF_WORKITEM") + + } +} + +class KmdfCallbackRoutineTypedef extends KmdfRoleTypeType { + KmdfCallbackRoutineTypedef() { this.getFile().getBaseName().matches("%wdf%.h") } +} + +/* Callbacks */ +class KmdfEVTWdfChildListCreateDevice extends KmdfCallbackRoutine { + KmdfEVTWdfChildListCreateDevice() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_CREATE_DEVICE") + } +} + +class KmdfEVTWdfChildListScanForChildren extends KmdfCallbackRoutine { + KmdfEVTWdfChildListScanForChildren() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_SCAN_FOR_CHILDREN") + } +} + +class KmdfEVTWdfChildListIdentificationDescriptionCopy extends KmdfCallbackRoutine { + KmdfEVTWdfChildListIdentificationDescriptionCopy() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COPY") + } +} + +class KmdfEVTWdfChildListIdentificationDescriptionDuplicate extends KmdfCallbackRoutine { + KmdfEVTWdfChildListIdentificationDescriptionDuplicate() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE") + } +} + +class KmdfEVTWdfChildListIdentificationDescriptionCompare extends KmdfCallbackRoutine { + KmdfEVTWdfChildListIdentificationDescriptionCompare() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE") + } +} + +class KmdfEVTWdfChildListIdentificationDescriptionCleanup extends KmdfCallbackRoutine { + KmdfEVTWdfChildListIdentificationDescriptionCleanup() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP") + } +} + +class KmdfEVTWdfChildListAddressDescriptionCopy extends KmdfCallbackRoutine { + KmdfEVTWdfChildListAddressDescriptionCopy() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_COPY") + } +} + +class KmdfEVTWdfChildListAddressDescriptionDuplicate extends KmdfCallbackRoutine { + KmdfEVTWdfChildListAddressDescriptionDuplicate() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_DUPLICATE") + } +} + +class KmdfEVTWdfChildListAddressDescriptionCleanup extends KmdfCallbackRoutine { + KmdfEVTWdfChildListAddressDescriptionCleanup() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_ADDRESS_DESCRIPTION_CLEANUP") + } +} + +class KmdfEVTWdfChildListDeviceReenumerated extends KmdfCallbackRoutine { + KmdfEVTWdfChildListDeviceReenumerated() { + callbackType.getName().matches("EVT_WDF_CHILD_LIST_DEVICE_REENUMERATED") + } +} + +class KmdfEVTWdfDeviceShutdownNotification extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceShutdownNotification() { + callbackType.getName().matches("EVT_WDF_DEVICE_SHUTDOWN_NOTIFICATION") + } +} + +class KmdfEVTWdfDeviceFileCreate extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceFileCreate() { callbackType.getName().matches("EVT_WDF_DEVICE_FILE_CREATE") } +} + +class KmdfEVTWdfFileClose extends KmdfCallbackRoutine { + KmdfEVTWdfFileClose() { callbackType.getName().matches("EVT_WDF_FILE_CLOSE") } +} + +class KmdfEVTWdfFileCleanup extends KmdfCallbackRoutine { + KmdfEVTWdfFileCleanup() { callbackType.getName().matches("EVT_WDF_FILE_CLEANUP") } +} + +class KmdfEVTWdfDevicePnpStateChangeNotification extends KmdfCallbackRoutine { + KmdfEVTWdfDevicePnpStateChangeNotification() { + callbackType.getName().matches("EVT_WDF_DEVICE_PNP_STATE_CHANGE_NOTIFICATION") + } +} + +class KmdfEVTWdfDevicePowerStateChangeNotification extends KmdfCallbackRoutine { + KmdfEVTWdfDevicePowerStateChangeNotification() { + callbackType.getName().matches("EVT_WDF_DEVICE_POWER_STATE_CHANGE_NOTIFICATION") + } +} + +class KmdfEVTWdfDevicePowerPolicyStateChangeNotification extends KmdfCallbackRoutine { + KmdfEVTWdfDevicePowerPolicyStateChangeNotification() { + callbackType.getName().matches("EVT_WDF_DEVICE_POWER_POLICY_STATE_CHANGE_NOTIFICATION") + } +} + +class KmdfEVTWdfDeviceD0Entry extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceD0Entry() { callbackType.getName().matches("EVT_WDF_DEVICE_D0_ENTRY") } +} + +class KmdfEVTWdfDeviceD0EntryPostInterruptsEnabled extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceD0EntryPostInterruptsEnabled() { + callbackType.getName().matches("EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED") + } +} + +class KmdfEVTWdfDeviceD0EntryPostHardwareEnabled extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceD0EntryPostHardwareEnabled() { + callbackType.getName().matches("EVT_WDF_DEVICE_D0_ENTRY_POST_HARDWARE_ENABLED") + } +} + +class KmdfEVTWdfDeviceD0Exit extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceD0Exit() { callbackType.getName().matches("EVT_WDF_DEVICE_D0_EXIT") } +} + +class KmdfEVTWdfDeviceD0ExitPreInterruptsDisabled extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceD0ExitPreInterruptsDisabled() { + callbackType.getName().matches("EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED") + } +} + +class KmdfEVTWdfDeviceD0ExitPreHardwareDisabled extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceD0ExitPreHardwareDisabled() { + callbackType.getName().matches("EVT_WDF_DEVICE_D0_EXIT_PRE_HARDWARE_DISABLED") + } +} + +class KmdfEVTWdfDevicePrepareHardware extends KmdfCallbackRoutine { + KmdfEVTWdfDevicePrepareHardware() { + callbackType.getName().matches("EVT_WDF_DEVICE_PREPARE_HARDWARE") + } +} + +class KmdfEVTWdfDeviceReleaseHardware extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceReleaseHardware() { + callbackType.getName().matches("EVT_WDF_DEVICE_RELEASE_HARDWARE") + } +} + +class KmdfEVTWdfDeviceSelfManagedIoCleanup extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSelfManagedIoCleanup() { + callbackType.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP") + } +} + +class KmdfEVTWdfDeviceSelfManagedIoFlush extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSelfManagedIoFlush() { + callbackType.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_FLUSH") + } +} + +class KmdfEVTWdfDeviceSelfManagedIoInit extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSelfManagedIoInit() { + callbackType.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT") + } +} + +class KmdfEVTWdfDeviceSelfManagedIoSuspend extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSelfManagedIoSuspend() { + callbackType.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND") + } +} + +class KmdfEVTWdfDeviceSelfManagedIoRestart extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSelfManagedIoRestart() { + callbackType.getName().matches("EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART") + } +} + +class KmdfEVTWdfDeviceQueryStop extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceQueryStop() { callbackType.getName().matches("EVT_WDF_DEVICE_QUERY_STOP") } +} + +class KmdfEVTWdfDeviceQueryRemove extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceQueryRemove() { callbackType.getName().matches("EVT_WDF_DEVICE_QUERY_REMOVE") } +} + +class KmdfEVTWdfDeviceSurpriseRemoval extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSurpriseRemoval() { + callbackType.getName().matches("EVT_WDF_DEVICE_SURPRISE_REMOVAL") + } +} + +class KmdfEVTWdfDeviceUsageNotification extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceUsageNotification() { + callbackType.getName().matches("EVT_WDF_DEVICE_USAGE_NOTIFICATION") + } +} + +class KmdfEVTWdfDeviceUsageNotificationEx extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceUsageNotificationEx() { + callbackType.getName().matches("EVT_WDF_DEVICE_USAGE_NOTIFICATION_EX") + } +} + +class KmdfEVTWdfDeviceRelationsQuery extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceRelationsQuery() { + callbackType.getName().matches("EVT_WDF_DEVICE_RELATIONS_QUERY") + } +} + +class KmdfEVTWdfDeviceArmWakeFromS0 extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceArmWakeFromS0() { + callbackType.getName().matches("EVT_WDF_DEVICE_ARM_WAKE_FROM_S0") + } +} + +class KmdfEVTWdfDeviceArmWakeFromSx extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceArmWakeFromSx() { + callbackType.getName().matches("EVT_WDF_DEVICE_ARM_WAKE_FROM_SX") + } +} + +class KmdfEVTWdfDeviceArmWakeFromSxWithReason extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceArmWakeFromSxWithReason() { + callbackType.getName().matches("EVT_WDF_DEVICE_ARM_WAKE_FROM_SX_WITH_REASON") + } +} + +class KmdfEVTWdfDeviceDisarmWakeFromS0 extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceDisarmWakeFromS0() { + callbackType.getName().matches("EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0") + } +} + +class KmdfEVTWdfDeviceDisarmWakeFromSx extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceDisarmWakeFromSx() { + callbackType.getName().matches("EVT_WDF_DEVICE_DISARM_WAKE_FROM_SX") + } +} + +class KmdfEVTWdfDeviceWakeFromS0Triggered extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceWakeFromS0Triggered() { + callbackType.getName().matches("EVT_WDF_DEVICE_WAKE_FROM_S0_TRIGGERED") + } +} + +class KmdfEVTWdfDeviceWakeFromSxTriggered extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceWakeFromSxTriggered() { + callbackType.getName().matches("EVT_WDF_DEVICE_WAKE_FROM_SX_TRIGGERED") + } +} + +class KmdfEVTWdfdeviceWdmIrpPreprocess extends KmdfCallbackRoutine { + KmdfEVTWdfdeviceWdmIrpPreprocess() { + callbackType.getName().matches("EVT_WDFDEVICE_WDM_IRP_PREPROCESS") + } +} + +class KmdfEVTWdfdeviceWdmIrpDispatch extends KmdfCallbackRoutine { + KmdfEVTWdfdeviceWdmIrpDispatch() { + callbackType.getName().matches("EVT_WDFDEVICE_WDM_IRP_DISPATCH") + } +} + +class KmdfEVTWdfIoInCallerContext extends KmdfCallbackRoutine { + KmdfEVTWdfIoInCallerContext() { callbackType.getName().matches("EVT_WDF_IO_IN_CALLER_CONTEXT") } +} + +class KmdfEVTWdfdeviceWdmPostPoFxRegisterDevice extends KmdfCallbackRoutine { + KmdfEVTWdfdeviceWdmPostPoFxRegisterDevice() { + callbackType.getName().matches("EVT_WDFDEVICE_WDM_POST_PO_FX_REGISTER_DEVICE") + } +} + +class KmdfEVTWdfdeviceWdmPrePoFxUnregisterDevice extends KmdfCallbackRoutine { + KmdfEVTWdfdeviceWdmPrePoFxUnregisterDevice() { + callbackType.getName().matches("EVT_WDFDEVICE_WDM_PRE_PO_FX_UNREGISTER_DEVICE") + } +} + +class KmdfEVTWdfDmaEnablerFill extends KmdfCallbackRoutine { + KmdfEVTWdfDmaEnablerFill() { callbackType.getName().matches("EVT_WDF_DMA_ENABLER_FILL") } +} + +class KmdfEVTWdfDmaEnablerFlush extends KmdfCallbackRoutine { + KmdfEVTWdfDmaEnablerFlush() { callbackType.getName().matches("EVT_WDF_DMA_ENABLER_FLUSH") } +} + +class KmdfEVTWdfDmaEnablerEnable extends KmdfCallbackRoutine { + KmdfEVTWdfDmaEnablerEnable() { callbackType.getName().matches("EVT_WDF_DMA_ENABLER_ENABLE") } +} + +class KmdfEVTWdfDmaEnablerDisable extends KmdfCallbackRoutine { + KmdfEVTWdfDmaEnablerDisable() { callbackType.getName().matches("EVT_WDF_DMA_ENABLER_DISABLE") } +} + +class KmdfEVTWdfDmaEnablerSelfmanagedIoStart extends KmdfCallbackRoutine { + KmdfEVTWdfDmaEnablerSelfmanagedIoStart() { + callbackType.getName().matches("EVT_WDF_DMA_ENABLER_SELFMANAGED_IO_START") + } +} + +class KmdfEVTWdfDmaEnablerSelfmanagedIoStop extends KmdfCallbackRoutine { + KmdfEVTWdfDmaEnablerSelfmanagedIoStop() { + callbackType.getName().matches("EVT_WDF_DMA_ENABLER_SELFMANAGED_IO_STOP") + } +} + +class KmdfEVTWdfProgramDma extends KmdfCallbackRoutine { + KmdfEVTWdfProgramDma() { callbackType.getName().matches("EVT_WDF_PROGRAM_DMA") } +} + +class KmdfEVTWdfDmaTransactionConfigureDmaChannel extends KmdfCallbackRoutine { + KmdfEVTWdfDmaTransactionConfigureDmaChannel() { + callbackType.getName().matches("EVT_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL") + } +} + +class KmdfEVTWdfDmaTransactionDmaTransferComplete extends KmdfCallbackRoutine { + KmdfEVTWdfDmaTransactionDmaTransferComplete() { + callbackType.getName().matches("EVT_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE") + } +} + +class KmdfEVTWdfReserveDma extends KmdfCallbackRoutine { + KmdfEVTWdfReserveDma() { callbackType.getName().matches("EVT_WDF_RESERVE_DMA") } +} + +class KmdfEVTWdfDpc extends KmdfCallbackRoutine { + KmdfEVTWdfDpc() { callbackType.getName().matches("EVT_WDF_DPC") } +} + +class KmdfEVTWdfDriverDeviceAdd extends KmdfCallbackRoutine { + KmdfEVTWdfDriverDeviceAdd() { callbackType.getName().matches("EVT_WDF_DRIVER_DEVICE_ADD") } +} + +class KmdfEVTWdfDriverUnload extends KmdfCallbackRoutine { + KmdfEVTWdfDriverUnload() { callbackType.getName().matches("EVT_WDF_DRIVER_UNLOAD") } +} + +class KmdfEVTWdfTraceCallback extends KmdfCallbackRoutine { + KmdfEVTWdfTraceCallback() { callbackType.getName().matches("EVT_WDF_TRACE_CALLBACK") } +} + +class KmdfEVTWdfDeviceFilterResourceRequirements extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceFilterResourceRequirements() { + callbackType.getName().matches("EVT_WDF_DEVICE_FILTER_RESOURCE_REQUIREMENTS") + } +} + +class KmdfEVTWdfDeviceRemoveAddedResources extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceRemoveAddedResources() { + callbackType.getName().matches("EVT_WDF_DEVICE_REMOVE_ADDED_RESOURCES") + } +} + +class KmdfEVTWdfInterruptIsr extends KmdfCallbackRoutine { + KmdfEVTWdfInterruptIsr() { callbackType.getName().matches("EVT_WDF_INTERRUPT_ISR") } +} + +class KmdfEVTWdfInterruptSynchronize extends KmdfCallbackRoutine { + KmdfEVTWdfInterruptSynchronize() { + callbackType.getName().matches("EVT_WDF_INTERRUPT_SYNCHRONIZE") + } +} + +class KmdfEVTWdfInterruptDpc extends KmdfCallbackRoutine { + KmdfEVTWdfInterruptDpc() { callbackType.getName().matches("EVT_WDF_INTERRUPT_DPC") } +} + +class KmdfEVTWdfInterruptWorkitem extends KmdfCallbackRoutine { + KmdfEVTWdfInterruptWorkitem() { callbackType.getName().matches("EVT_WDF_INTERRUPT_WORKITEM") } +} + +class KmdfEVTWdfInterruptEnable extends KmdfCallbackRoutine { + KmdfEVTWdfInterruptEnable() { callbackType.getName().matches("EVT_WDF_INTERRUPT_ENABLE") } +} + +class KmdfEVTWdfInterruptDisable extends KmdfCallbackRoutine { + KmdfEVTWdfInterruptDisable() { callbackType.getName().matches("EVT_WDF_INTERRUPT_DISABLE") } +} + +class KmdfEVTWdfIoQueueIoDefault extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoDefault() { callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_DEFAULT") } +} + +class KmdfEVTWdfIoQueueIoStop extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoStop() { callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_STOP") } +} + +class KmdfEVTWdfIoQueueIoResume extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoResume() { callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_RESUME") } +} + +class KmdfEVTWdfIoQueueIoRead extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoRead() { callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_READ") } +} + +class KmdfEVTWdfIoQueueIoWrite extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoWrite() { callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_WRITE") } +} + +class KmdfEVTWdfIoQueueIoDeviceControl extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoDeviceControl() { + callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL") + } +} + +class KmdfEVTWdfIoQueueIoInternalDeviceControl extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoInternalDeviceControl() { + callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL") + } +} + +class KmdfEVTWdfIoQueueIoCanceledOnQueue extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueIoCanceledOnQueue() { + callbackType.getName().matches("EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE") + } +} + +class KmdfEVTWdfIoQueueState extends KmdfCallbackRoutine { + KmdfEVTWdfIoQueueState() { callbackType.getName().matches("EVT_WDF_IO_QUEUE_STATE") } +} + +class KmdfEVTWdfIoAllocateResourcesForReservedRequest extends KmdfCallbackRoutine { + KmdfEVTWdfIoAllocateResourcesForReservedRequest() { + callbackType.getName().matches("EVT_WDF_IO_ALLOCATE_RESOURCES_FOR_RESERVED_REQUEST") + } +} + +class KmdfEVTWdfIoAllocateRequestResources extends KmdfCallbackRoutine { + KmdfEVTWdfIoAllocateRequestResources() { + callbackType.getName().matches("EVT_WDF_IO_ALLOCATE_REQUEST_RESOURCES") + } +} + +class KmdfEVTWdfIoWdmIrpForForwardProgress extends KmdfCallbackRoutine { + KmdfEVTWdfIoWdmIrpForForwardProgress() { + callbackType.getName().matches("EVT_WDF_IO_WDM_IRP_FOR_FORWARD_PROGRESS") + } +} + +class KmdfEVTWdfIoTargetQueryRemove extends KmdfCallbackRoutine { + KmdfEVTWdfIoTargetQueryRemove() { + callbackType.getName().matches("EVT_WDF_IO_TARGET_QUERY_REMOVE") + } +} + +class KmdfEVTWdfIoTargetRemoveCanceled extends KmdfCallbackRoutine { + KmdfEVTWdfIoTargetRemoveCanceled() { + callbackType.getName().matches("EVT_WDF_IO_TARGET_REMOVE_CANCELED") + } +} + +class KmdfEVTWdfIoTargetRemoveComplete extends KmdfCallbackRoutine { + KmdfEVTWdfIoTargetRemoveComplete() { + callbackType.getName().matches("EVT_WDF_IO_TARGET_REMOVE_COMPLETE") } } +class KmdfEVTWdfObjectContextCleanup extends KmdfCallbackRoutine { + KmdfEVTWdfObjectContextCleanup() { + callbackType.getName().matches("EVT_WDF_OBJECT_CONTEXT_CLEANUP") + } +} + +class KmdfEVTWdfObjectContextDestroy extends KmdfCallbackRoutine { + KmdfEVTWdfObjectContextDestroy() { + callbackType.getName().matches("EVT_WDF_OBJECT_CONTEXT_DESTROY") + } +} + +class KmdfEVTWdfDeviceResourcesQuery extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceResourcesQuery() { + callbackType.getName().matches("EVT_WDF_DEVICE_RESOURCES_QUERY") + } +} + +class KmdfEVTWdfDeviceResourceRequirementsQuery extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceResourceRequirementsQuery() { + callbackType.getName().matches("EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY") + } +} + +class KmdfEVTWdfDeviceEject extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceEject() { callbackType.getName().matches("EVT_WDF_DEVICE_EJECT") } +} + +class KmdfEVTWdfDeviceSetLock extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceSetLock() { callbackType.getName().matches("EVT_WDF_DEVICE_SET_LOCK") } +} + +class KmdfEVTWdfDeviceEnableWakeAtBus extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceEnableWakeAtBus() { + callbackType.getName().matches("EVT_WDF_DEVICE_ENABLE_WAKE_AT_BUS") + } +} + +class KmdfEVTWdfDeviceDisableWakeAtBus extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceDisableWakeAtBus() { + callbackType.getName().matches("EVT_WDF_DEVICE_DISABLE_WAKE_AT_BUS") + } +} + +class KmdfEVTWdfDeviceReportedMissing extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceReportedMissing() { + callbackType.getName().matches("EVT_WDF_DEVICE_REPORTED_MISSING") + } +} + +class KmdfEVTWdfDeviceProcessQueryInterfaceRequest extends KmdfCallbackRoutine { + KmdfEVTWdfDeviceProcessQueryInterfaceRequest() { + callbackType.getName().matches("EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST") + } +} + +class KmdfEVTWdfRequestCancel extends KmdfCallbackRoutine { + KmdfEVTWdfRequestCancel() { callbackType.getName().matches("EVT_WDF_REQUEST_CANCEL") } +} + +class KmdfEVTWdfRequestCompletionRoutine extends KmdfCallbackRoutine { + KmdfEVTWdfRequestCompletionRoutine() { + callbackType.getName().matches("EVT_WDF_REQUEST_COMPLETION_ROUTINE") + } +} + +class KmdfEVTWdfTimer extends KmdfCallbackRoutine { + KmdfEVTWdfTimer() { callbackType.getName().matches("EVT_WDF_TIMER") } +} + +class KmdfEVTWdfUsbReaderCompletionRoutine extends KmdfCallbackRoutine { + KmdfEVTWdfUsbReaderCompletionRoutine() { + callbackType.getName().matches("EVT_WDF_USB_READER_COMPLETION_ROUTINE") + } +} + +class KmdfEVTWdfUsbReadersFailed extends KmdfCallbackRoutine { + KmdfEVTWdfUsbReadersFailed() { callbackType.getName().matches("EVT_WDF_USB_READERS_FAILED") } +} + +class KmdfEVTWdfWmiInstanceQueryInstance extends KmdfCallbackRoutine { + KmdfEVTWdfWmiInstanceQueryInstance() { + callbackType.getName().matches("EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE") + } +} + +class KmdfEVTWdfWmiInstanceSetInstance extends KmdfCallbackRoutine { + KmdfEVTWdfWmiInstanceSetInstance() { + callbackType.getName().matches("EVT_WDF_WMI_INSTANCE_SET_INSTANCE") + } +} + +class KmdfEVTWdfWmiInstanceSetItem extends KmdfCallbackRoutine { + KmdfEVTWdfWmiInstanceSetItem() { callbackType.getName().matches("EVT_WDF_WMI_INSTANCE_SET_ITEM") } +} + +class KmdfEVTWdfWmiInstanceExecuteMethod extends KmdfCallbackRoutine { + KmdfEVTWdfWmiInstanceExecuteMethod() { + callbackType.getName().matches("EVT_WDF_WMI_INSTANCE_EXECUTE_METHOD") + } +} + +class KmdfEVTWdfWmiProviderFunctionControl extends KmdfCallbackRoutine { + KmdfEVTWdfWmiProviderFunctionControl() { + callbackType.getName().matches("EVT_WDF_WMI_PROVIDER_FUNCTION_CONTROL") + } +} + +class KmdfEVTWdfWorkitem extends KmdfCallbackRoutine { + KmdfEVTWdfWorkitem() { callbackType.getName().matches("EVT_WDF_WORKITEM") } +} + /** * A KMDF callback routine, defined by having a typedef in its definition * that matches the standard KMDF callbacks. */ class KmdfCallbackRoutine extends Function { /** The typedef representing what callback this is. */ - KmdfCallbackRoutineTypedef callbackType; + KmdfRoleTypeType callbackType; KmdfCallbackRoutine() { exists(FunctionDeclarationEntry fde | @@ -27,15 +705,298 @@ class KmdfCallbackRoutine extends Function { } } +/** The DeviceAdd callback. Its callback typedef is "EVT_WDF_DRIVER_DEVICE_ADD". */ +class KmdfEvtDriverDeviceAdd extends KmdfCallbackRoutine { + KmdfEvtDriverDeviceAdd() { callbackType.getName().matches("EVT_WDF_DRIVER_DEVICE_ADD") } +} + /** - * The KMDF DriverEntry function. KMDF enforces that the function is named DriverEntry. - * Additionally, the driver may use the DRIVER_INIRIALIZE typedef. + * A KMDF Function. This class is incomplete. It is used to represent a Function in the KMDF library. */ -class KmdfDriverEntry extends Function { - KmdfDriverEntry() { this.getName().matches("DriverEntry") } +class KmdfFunc extends Function { + KmdfFunc() { this.getFile().getBaseName().matches("wdf%.h") } } -/** The DeviceAdd callback. Its callback typedef is "EVT_WDF_DRIVER_DEVICE_ADD". */ -class KmdfEvtDriverDeviceAdd extends KmdfCallbackRoutine { - KmdfEvtDriverDeviceAdd() { callbackType.getName().matches("EVT_WDF_DRIVER_DEVICE_ADD") } +/** + * A KMDF Struct. This class is incomplete. It is used to represent a Struct in the KMDF library. + */ +class KmdfStruct extends Struct { + KmdfStruct() { this.getFile().getBaseName().matches("wdf%.h") } +} + +/* KMDF Structs */ +class KmdfWDFPowerRoutineTimedOutData extends KmdfStruct { + KmdfWDFPowerRoutineTimedOutData() { this.getName().matches("_WDF_POWER_ROUTINE_TIMED_OUT_DATA") } +} + +class KmdfWDFRequestFatalErrorInformationLengthMismatchData extends KmdfStruct { + KmdfWDFRequestFatalErrorInformationLengthMismatchData() { + this.getName().matches("_WDF_REQUEST_FATAL_ERROR_INFORMATION_LENGTH_MISMATCH_DATA") + } +} + +class KmdfWDFQueueFatalErrorData extends KmdfStruct { + KmdfWDFQueueFatalErrorData() { this.getName().matches("_WDF_QUEUE_FATAL_ERROR_DATA") } +} + +class KmdfWDFChildIdentificationDescriptionHeader extends KmdfStruct { + KmdfWDFChildIdentificationDescriptionHeader() { + this.getName().matches("_WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER") + } +} + +class KmdfWDFChildAddressDescriptionHeader extends KmdfStruct { + KmdfWDFChildAddressDescriptionHeader() { + this.getName().matches("_WDF_CHILD_ADDRESS_DESCRIPTION_HEADER") + } +} + +class KmdfWDFChildRetrieveInfo extends KmdfStruct { + KmdfWDFChildRetrieveInfo() { this.getName().matches("_WDF_CHILD_RETRIEVE_INFO") } +} + +class KmdfWDFChildListConfig extends KmdfStruct { + KmdfWDFChildListConfig() { this.getName().matches("_WDF_CHILD_LIST_CONFIG") } +} + +class KmdfWDFChildListIterator extends KmdfStruct { + KmdfWDFChildListIterator() { this.getName().matches("_WDF_CHILD_LIST_ITERATOR") } +} + +class KmdfWDFCommonBufferConfig extends KmdfStruct { + KmdfWDFCommonBufferConfig() { this.getName().matches("_WDF_COMMON_BUFFER_CONFIG") } +} + +class KmdfWDFTaskSendOptions extends KmdfStruct { + KmdfWDFTaskSendOptions() { this.getName().matches("_WDF_TASK_SEND_OPTIONS") } +} + +class KmdfWDFFileobjectConfig extends KmdfStruct { + KmdfWDFFileobjectConfig() { this.getName().matches("_WDF_FILEOBJECT_CONFIG") } +} + +class KmdfWDFDevicePnpNotificationData extends KmdfStruct { + KmdfWDFDevicePnpNotificationData() { this.getName().matches("_WDF_DEVICE_PNP_NOTIFICATION_DATA") } +} + +class KmdfWDFDevicePowerNotificationData extends KmdfStruct { + KmdfWDFDevicePowerNotificationData() { + this.getName().matches("_WDF_DEVICE_POWER_NOTIFICATION_DATA") + } +} + +class KmdfWDFDevicePowerPolicyNotificationData extends KmdfStruct { + KmdfWDFDevicePowerPolicyNotificationData() { + this.getName().matches("_WDF_DEVICE_POWER_POLICY_NOTIFICATION_DATA") + } +} + +class KmdfWDFPnppowerEventCallbacks extends KmdfStruct { + KmdfWDFPnppowerEventCallbacks() { this.getName().matches("_WDF_PNPPOWER_EVENT_CALLBACKS") } +} + +class KmdfWDFPowerPolicyEventCallbacks extends KmdfStruct { + KmdfWDFPowerPolicyEventCallbacks() { this.getName().matches("_WDF_POWER_POLICY_EVENT_CALLBACKS") } +} + +class KmdfWDFDevicePowerPolicyIdleSettings extends KmdfStruct { + KmdfWDFDevicePowerPolicyIdleSettings() { + this.getName().matches("_WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS") + } +} + +class KmdfWDFDevicePowerPolicyWakeSettings extends KmdfStruct { + KmdfWDFDevicePowerPolicyWakeSettings() { + this.getName().matches("_WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS") + } +} + +class KmdfWDFDeviceState extends KmdfStruct { + KmdfWDFDeviceState() { this.getName().matches("_WDF_DEVICE_STATE") } +} + +class KmdfWDFDevicePnpCapabilities extends KmdfStruct { + KmdfWDFDevicePnpCapabilities() { this.getName().matches("_WDF_DEVICE_PNP_CAPABILITIES") } +} + +class KmdfWDFDevicePowerCapabilities extends KmdfStruct { + KmdfWDFDevicePowerCapabilities() { this.getName().matches("_WDF_DEVICE_POWER_CAPABILITIES") } +} + +class KmdfWDFRemoveLockOptions extends KmdfStruct { + KmdfWDFRemoveLockOptions() { this.getName().matches("_WDF_REMOVE_LOCK_OPTIONS") } +} + +class KmdfWDFPowerFrameworkSettings extends KmdfStruct { + KmdfWDFPowerFrameworkSettings() { this.getName().matches("_WDF_POWER_FRAMEWORK_SETTINGS") } +} + +class KmdfWDFIoTypeConfig extends KmdfStruct { + KmdfWDFIoTypeConfig() { this.getName().matches("_WDF_IO_TYPE_CONFIG") } +} + +class KmdfWDFDevicePropertyData extends KmdfStruct { + KmdfWDFDevicePropertyData() { this.getName().matches("_WDF_DEVICE_PROPERTY_DATA") } +} + +class KmdfWDFDmaEnablerConfig extends KmdfStruct { + KmdfWDFDmaEnablerConfig() { this.getName().matches("_WDF_DMA_ENABLER_CONFIG") } +} + +class KmdfWDFDmaSystemProfileConfig extends KmdfStruct { + KmdfWDFDmaSystemProfileConfig() { this.getName().matches("_WDF_DMA_SYSTEM_PROFILE_CONFIG") } +} + +class KmdfWDFDpcConfig extends KmdfStruct { + KmdfWDFDpcConfig() { this.getName().matches("_WDF_DPC_CONFIG") } +} + +class KmdfWDFDriverConfig extends KmdfStruct { + KmdfWDFDriverConfig() { this.getName().matches("_WDF_DRIVER_CONFIG") } +} + +class KmdfWDFDriverVersionAvailableParams extends KmdfStruct { + KmdfWDFDriverVersionAvailableParams() { + this.getName().matches("_WDF_DRIVER_VERSION_AVAILABLE_PARAMS") + } +} + +class KmdfWDFFdoEventCallbacks extends KmdfStruct { + KmdfWDFFdoEventCallbacks() { this.getName().matches("_WDF_FDO_EVENT_CALLBACKS") } +} + +class KmdfWDFDriverGlobals extends KmdfStruct { + KmdfWDFDriverGlobals() { this.getName().matches("_WDF_DRIVER_GLOBALS") } +} + +class KmdfWDFCoinstallerInstallOptions extends KmdfStruct { + KmdfWDFCoinstallerInstallOptions() { this.getName().matches("_WDF_COINSTALLER_INSTALL_OPTIONS") } +} + +class KmdfWDFInterruptConfig extends KmdfStruct { + KmdfWDFInterruptConfig() { this.getName().matches("_WDF_INTERRUPT_CONFIG") } +} + +class KmdfWDFInterruptInfo extends KmdfStruct { + KmdfWDFInterruptInfo() { this.getName().matches("_WDF_INTERRUPT_INFO") } +} + +class KmdfWDFInterruptExtendedPolicy extends KmdfStruct { + KmdfWDFInterruptExtendedPolicy() { this.getName().matches("_WDF_INTERRUPT_EXTENDED_POLICY") } +} + +class KmdfWDFIoQueueConfig extends KmdfStruct { + KmdfWDFIoQueueConfig() { this.getName().matches("_WDF_IO_QUEUE_CONFIG") } +} + +class KmdfWDFIoQueueForwardProgressPolicy extends KmdfStruct { + KmdfWDFIoQueueForwardProgressPolicy() { + this.getName().matches("_WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY") + } +} + +class KmdfWDFIoTargetOpenParams extends KmdfStruct { + KmdfWDFIoTargetOpenParams() { this.getName().matches("_WDF_IO_TARGET_OPEN_PARAMS") } +} + +class KmdfWDFMEMORYOffset extends KmdfStruct { + KmdfWDFMEMORYOffset() { this.getName().matches("_WDFMEMORY_OFFSET") } +} + +class KmdfWDFMemoryDescriptor extends KmdfStruct { + KmdfWDFMemoryDescriptor() { this.getName().matches("_WDF_MEMORY_DESCRIPTOR") } +} + +class KmdfWDFObjectAttributes extends KmdfStruct { + KmdfWDFObjectAttributes() { this.getName().matches("_WDF_OBJECT_ATTRIBUTES") } +} + +class KmdfWDFObjectContextTypeInfo extends KmdfStruct { + KmdfWDFObjectContextTypeInfo() { this.getName().matches("_WDF_OBJECT_CONTEXT_TYPE_INFO") } +} + +class KmdfWDFCustomTypeContext extends KmdfStruct { + KmdfWDFCustomTypeContext() { this.getName().matches("_WDF_CUSTOM_TYPE_CONTEXT") } +} + +class KmdfWDFPdoEventCallbacks extends KmdfStruct { + KmdfWDFPdoEventCallbacks() { this.getName().matches("_WDF_PDO_EVENT_CALLBACKS") } +} + +class KmdfWDFQueryInterfaceConfig extends KmdfStruct { + KmdfWDFQueryInterfaceConfig() { this.getName().matches("_WDF_QUERY_INTERFACE_CONFIG") } +} + +class KmdfWDFRequestParameters extends KmdfStruct { + KmdfWDFRequestParameters() { this.getName().matches("_WDF_REQUEST_PARAMETERS") } +} + +class KmdfWDFRequestCompletionParams extends KmdfStruct { + KmdfWDFRequestCompletionParams() { this.getName().matches("_WDF_REQUEST_COMPLETION_PARAMS") } +} + +class KmdfWDFRequestReuseParams extends KmdfStruct { + KmdfWDFRequestReuseParams() { this.getName().matches("_WDF_REQUEST_REUSE_PARAMS") } +} + +class KmdfWDFRequestSendOptions extends KmdfStruct { + KmdfWDFRequestSendOptions() { this.getName().matches("_WDF_REQUEST_SEND_OPTIONS") } +} + +class KmdfWDFRequestForwardOptions extends KmdfStruct { + KmdfWDFRequestForwardOptions() { this.getName().matches("_WDF_REQUEST_FORWARD_OPTIONS") } +} + +class KmdfWDFTimerConfig extends KmdfStruct { + KmdfWDFTimerConfig() { this.getName().matches("_WDF_TIMER_CONFIG") } +} + +class KmdfWDFUsbRequestCompletionParams extends KmdfStruct { + KmdfWDFUsbRequestCompletionParams() { + this.getName().matches("_WDF_USB_REQUEST_COMPLETION_PARAMS") + } +} + +class KmdfWDFUsbContinuousReaderConfig extends KmdfStruct { + KmdfWDFUsbContinuousReaderConfig() { this.getName().matches("_WDF_USB_CONTINUOUS_READER_CONFIG") } +} + +class KmdfWDFUsbDeviceInformation extends KmdfStruct { + KmdfWDFUsbDeviceInformation() { this.getName().matches("_WDF_USB_DEVICE_INFORMATION") } +} + +class KmdfWDFUsbInterfaceSettingPair extends KmdfStruct { + KmdfWDFUsbInterfaceSettingPair() { this.getName().matches("_WDF_USB_INTERFACE_SETTING_PAIR") } +} + +class KmdfWDFUsbDeviceSelectConfigParams extends KmdfStruct { + KmdfWDFUsbDeviceSelectConfigParams() { + this.getName().matches("_WDF_USB_DEVICE_SELECT_CONFIG_PARAMS") + } +} + +class KmdfWDFUsbInterfaceSelectSettingParams extends KmdfStruct { + KmdfWDFUsbInterfaceSelectSettingParams() { + this.getName().matches("_WDF_USB_INTERFACE_SELECT_SETTING_PARAMS") + } +} + +class KmdfWDFUsbPipeInformation extends KmdfStruct { + KmdfWDFUsbPipeInformation() { this.getName().matches("_WDF_USB_PIPE_INFORMATION") } +} + +class KmdfWDFUsbDeviceCreateConfig extends KmdfStruct { + KmdfWDFUsbDeviceCreateConfig() { this.getName().matches("_WDF_USB_DEVICE_CREATE_CONFIG") } +} + +class KmdfWDFWmiProviderConfig extends KmdfStruct { + KmdfWDFWmiProviderConfig() { this.getName().matches("_WDF_WMI_PROVIDER_CONFIG") } +} + +class KmdfWDFWmiInstanceConfig extends KmdfStruct { + KmdfWDFWmiInstanceConfig() { this.getName().matches("_WDF_WMI_INSTANCE_CONFIG") } +} + +class KmdfWDFWorkitemConfig extends KmdfStruct { + KmdfWDFWorkitemConfig() { this.getName().matches("_WDF_WORKITEM_CONFIG") } } diff --git a/src/drivers/libraries/RoleTypes.qll b/src/drivers/libraries/RoleTypes.qll new file mode 100644 index 00000000..737e9c9f --- /dev/null +++ b/src/drivers/libraries/RoleTypes.qll @@ -0,0 +1,222 @@ +import cpp +import drivers.libraries.SAL +// import drivers.libraries.Irql // TODO: add this back in +import drivers.wdm.libraries.WdmDrivers +import drivers.kmdf.libraries.KmdfDrivers +import drivers.ndis.libraries.NdisDrivers +import drivers.storport.libraries.StorportDrivers + +/** + * Special case to check for RoleType equality for role types in wdfroletypes.h + */ +bindingset[rtt1, rtt2] +predicate isEqualRoleTypes(string rtt1, string rtt2) { + rtt1.matches("EVT_WDF_%_CONTEXT_DESTROY%") and + rtt2.matches("EVT_WDF_%_CONTEXT_DESTROY%") + or + rtt1.matches("EVT_WDF_%_CONTEXT_CLEANUP%") and + rtt2.matches("EVT_WDF_%_CONTEXT_CLEANUP%") + or + rtt1 = rtt2 +} + +/** + * Generic role type for WDM,KMDF, and others + */ +class RoleTypeType extends TypedefType { + RoleTypeType() { + this instanceof WdmRoleTypeType or + this instanceof KmdfRoleTypeType or + this instanceof NdisRoleTypeType or + this instanceof StorportRoleTypeType + } +} + +/** + * Role Type annotations which apply to entire functions + */ +class RoleTypeFunctionAnnotation extends SALAnnotation { + string roleTypeString; + string roleTypeName; + + RoleTypeFunctionAnnotation() { + ( + this.getMacroName().matches(["_Function_class_"]) and + roleTypeString = this.getUnexpandedArgument(0) + ) and + roleTypeName = this.getMacroName() + } + + /** + * Returns the raw text of the role type value used in this annotation. + */ + string getRoleTypeString() { result = roleTypeString } + + /** + * Returns the text of this annotation + */ + string getRoleTypeMacroName() { result = roleTypeName } +} + +/** + * A typedef that has Role Type annotations applied to it. + */ +class RoleTypeAnnotatedTypedef extends TypedefType { + RoleTypeFunctionAnnotation roleTypeAnnotation; + + RoleTypeAnnotatedTypedef() { roleTypeAnnotation.getTypedefDeclarations() = this } + + RoleTypeFunctionAnnotation getRoleTypeAnnotation() { result = roleTypeAnnotation } +} + +/** + * A function that is annotated to specify role type + */ +cached +class RoleTypeAnnotatedFunction extends Function { + RoleTypeFunctionAnnotation roleTypeAnnotation; + + cached + RoleTypeAnnotatedFunction() { + ( + this.hasCLinkage() and + exists( + FunctionDeclarationEntry fde // actual function declarations + | + fde = this.getADeclarationEntry() and + roleTypeAnnotation.getDeclarationEntry() = fde + ) + or + exists( + FunctionDeclarationEntry fde // typedefs + | + fde.getFunction() = this and + fde.getTypedefType().(RoleTypeAnnotatedTypedef).getRoleTypeAnnotation() = roleTypeAnnotation + ) + ) + } + + cached + string getFuncRoleTypeAnnotation() { result = roleTypeAnnotation.getRoleTypeMacroName() } + + cached + RoleTypeFunctionAnnotation getRoleTypeAnnotation() { result = roleTypeAnnotation } +} + +/** + * A function that is annotated or declared to specify role type + */ +class RoleTypeFunction extends Function { + RoleTypeType roleType; + + //int irqlLevel; // TODO: add this back in + RoleTypeFunction() { + this.hasCLinkage() and + ( + exists(FunctionDeclarationEntry fde | + ( + fde.getFunction() = this and + fde.getTypedefType() = roleType + ) + ) + or + this instanceof RoleTypeAnnotatedFunction and + roleType.getName() = + this.(RoleTypeAnnotatedFunction).getRoleTypeAnnotation().getRoleTypeString() + ) + // TODO: add this back in + // and + // if this instanceof IrqlRestrictsFunction + // then irqlLevel = getAllowableIrqlLevel(this) + // else irqlLevel = -1 + } + + // TODO: add this back in + // int getExpectedIrqlLevelString() { result = irqlLevel } + string getRoleTypeString() { result = roleType.getName() } + + RoleTypeType getRoleTypeType() { result = roleType } +} + +/** + */ +class DriverObjectFunctionAccess extends FunctionAccess { + RoleTypeType rttExpected; + + DriverObjectFunctionAccess() { + exists(VariableAccess driverObjectAccess, AssignExpr driverObjectAssign | + driverObjectAccess.getTarget().getType().getName().matches("PDRIVER_OBJECT") and + this = driverObjectAssign.getRValue() and + rttExpected = driverObjectAssign.getLValue().getUnderlyingType().(PointerType).getBaseType() + ) + } + + RoleTypeType getExpectedRoleTypeType() { result = rttExpected } +} + +/** + * Declared functions that are used as if they have a role type, wether or not they do + */ +cached +class ImplicitRoleTypeFunction extends Function { + RoleTypeType rttExpected; + FunctionAccess funcUse; + + cached + ImplicitRoleTypeFunction() { + ( + exists(FunctionCall fc, int n | fc.getArgument(n) instanceof FunctionAccess | + this = fc.getArgument(n).(FunctionAccess).getTarget() and + rttExpected = fc.getTarget().getParameter(n).getUnderlyingType().(PointerType).getBaseType() and + funcUse = fc.getArgument(n) + ) + or + exists(DriverObjectFunctionAccess funcAssign | + funcAssign.getTarget() = this and + rttExpected = funcAssign.getExpectedRoleTypeType() and + funcUse = funcAssign + ) + ) and + this.hasCLinkage() + } + + cached + string getExpectedRoleTypeString() { result = rttExpected.getName() } + + cached + RoleTypeType getExpectedRoleTypeType() { result = rttExpected } + + cached + string getActualRoleTypeString() { + if not this instanceof RoleTypeFunction + then result = "" + else result = this.(RoleTypeFunction).getRoleTypeType().toString() + } + + // TODO: add this back in + // cached + // int getExpectedIrqlLevel() { + // if rttExpected instanceof IrqlAnnotatedTypedef + // then result = getAlloweableIrqlLevel(rttExpected) + // else result = -1 + // } + // cached + // int getFoundIrqlLevel() { + // if this instanceof IrqlRestrictsFunction + // then result = getAllowableIrqlLevel(this) + // else result = -1 + // } + cached + FunctionAccess getFunctionUse() { result = funcUse } +} + +/** Predicates */ +predicate roleTypeAssignment(AssignExpr ae) { + exists(FunctionAccess fa | + ae.getRValue() = fa and + fa.getTarget() instanceof WdmDispatchRoutine + ) + or + ae.getRValue() instanceof AssignExpr and + roleTypeAssignment(ae.getRValue().(AssignExpr)) +} diff --git a/src/drivers/ndis/libraries/NdisDrivers.qll b/src/drivers/ndis/libraries/NdisDrivers.qll new file mode 100644 index 00000000..a0a7ce27 --- /dev/null +++ b/src/drivers/ndis/libraries/NdisDrivers.qll @@ -0,0 +1,847 @@ +/** + * This QL library defines classes and predicates for analyzing NDIS drivers. + * It provides definitions for NDIS dispatch routines, callback routines, and role types. + * The library also includes a typedef for the standard NDIS callback routines. + */ + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +import cpp +import drivers.libraries.SAL + +/** + * NDIS dispatch routine class. + * We hold a routine to be a dispatch routine if there is + * an assignment in DriverEntry that assigns the function to + * the dispatch table. + */ +cached +class NdisDispatchRoutine extends NdisCallbackRoutine { + /** + * The OID type covered by this dispatch routine. + */ + Literal dispatchType; + /** The DriverEntry function this dispatch routine was assigned in. */ + NdisDriverEntry driverEntry; + + /** + * Dispatch routines are defined by assignments of the form + * MiniportDriverObject->DriverDispatch->MiniportXxxHandler = XxxHandler; + * This characteristic predicate thus looks for assignments of this form + * where the right-side value is a function with the NDIS_DISPATCH typedef. + */ + cached + NdisDispatchRoutine() { + callbackType.getName().matches("NDIS_DISPATCH") and + exists( + NdisCallbackRoutineAssignment cra, PointerFieldAccess dispatchTable, + PointerFieldAccess fieldAccess, VariableAccess driverObjectAccess + | + cra.getLValue() = fieldAccess and + fieldAccess.getQualifier() = dispatchTable and + dispatchTable.getQualifier() = driverObjectAccess and + driverObjectAccess.getTarget().getType().getName().matches("PNDIS_MINIPORT_BLOCK") and + cra.getTarget() = this and + cra.getEnclosingFunction() = driverEntry + ) + } + + /** Gets the OID type this dispatch routine handles, as a number. */ + cached + Literal getDispatchType() { result = dispatchType } + + /** Gets the DriverEntry this dispatch routine was assigned in. */ + cached + NdisDriverEntry getDriverEntry() { result = driverEntry } +} + +/** An assignment where the right-hand side is a NDIS callback routine. */ +class NdisCallbackRoutineAssignment extends AssignExpr { + /* + * A common paradigm in dispatch routine setup is to chain assignments to cover multiple IRPs. + * As such, it's necessary to recursively walk the assignment to handle cases such as + * DriverObject->MajorFunction[IRP_MJ_CREATE] = + * DriverObject->MajorFunction[IRP_MJ_OPEN] = + * MyMultiFunctionIrpHandler; + * However, characterstic predicates cannot be recurisve, so the logic is placed in a separate + * predicate below, isNdisCallbackRoutineAssignment. + */ + + NdisCallbackRoutineAssignment() { isNdisCallbackRoutineAssignment(this) } + + /** Gets the callback routine that this dispatch routine assignment is targeting. */ + cached + NdisCallbackRoutine getTarget() { + if + exists(FunctionAccess fa | + this.getRValue() = fa and + fa.getTarget() instanceof NdisCallbackRoutine + ) + then result = this.getRValue().(FunctionAccess).getTarget() + else result = getTarget_aux(this.getRValue()) + } + + /** Auxilliary function to getTarget(). */ + private NdisCallbackRoutine getTarget_aux(AssignExpr ae) { + if + exists(FunctionAccess fa | + ae.getRValue() = fa and + fa.getTarget() instanceof NdisCallbackRoutine + ) + then result = ae.getRValue().(FunctionAccess).getTarget() + else result = getTarget_aux(ae.getRValue()) + } +} + +/** Determines if a given assignment, recursively, has a NDIS callback routine as the right-hand side. */ +private predicate isNdisCallbackRoutineAssignment(AssignExpr ae) { + exists(FunctionAccess fa | + ae.getRValue() = fa and + fa.getTarget() instanceof NdisCallbackRoutine + ) + or + ae.getRValue() instanceof AssignExpr and + isNdisCallbackRoutineAssignment(ae.getRValue().(AssignExpr)) +} + +/** A typedef for Role Types */ +class NdisRoleTypeType extends TypedefType { + NdisRoleTypeType() { + ( + this.getName().matches("MINIPORT_PROCESS_SG_LIST") or + this.getName().matches("NDIS_TIMER_FUNCTION") or + this.getName().matches("NDIS_IO_WORKITEM") or + this.getName().matches("MINIPORT_ADD_DEVICE") or + this.getName().matches("MINIPORT_CANCEL_DIRECT_OID_REQUEST") or + this.getName().matches("MINIPORT_DIRECT_OID_REQUEST") or + this.getName().matches("MINIPORT_FILTER_RESOURCE_REQUIREMENTS") or + this.getName().matches("MINIPORT_START_DEVICE") or + this.getName().matches("MINIPORT_SYNCHRONIZE_MESSAGE_INTERRUPT") or + this.getName().matches("NDIS_IO_WORKITEM_FUNCTION") or + this.getName().matches("FILTER_ATTACH") or + this.getName().matches("FILTER_CANCEL_DIRECT_OID_REQUEST") or + this.getName().matches("FILTER_CANCEL_SEND_NET_BUFFER_LISTS") or + this.getName().matches("FILTER_CANCEL_OID_REQUEST") or + this.getName().matches("FILTER_DETACH") or + this.getName().matches("FILTER_DEVICE_PNP_EVENT_NOTIFY") or + this.getName().matches("FILTER_DIRECT_OID_REQUEST") or + this.getName().matches("FILTER_DIRECT_OID_REQUEST_COMPLETE") or + this.getName().matches("DRIVER_UNLOAD") or + this.getName().matches("FILTER_NET_PNP_EVENT") or + this.getName().matches("FILTER_OID_REQUEST") or + this.getName().matches("FILTER_OID_REQUEST_COMPLETE") or + this.getName().matches("FILTER_PAUSE") or + this.getName().matches("FILTER_RECEIVE_NET_BUFFER_LISTS") or + this.getName().matches("FILTER_RESTART") or + this.getName().matches("FILTER_RETURN_NET_BUFFER_LISTS") or + this.getName().matches("FILTER_SEND_NET_BUFFER_LISTS") or + this.getName().matches("FILTER_SEND_NET_BUFFER_LISTS_COMPLETE") or + this.getName().matches("FILTER_SET_MODULE_OPTIONS") or + this.getName().matches("FILTER_SET_OPTIONS") or + this.getName().matches("FILTER_STATUS") or + this.getName().matches("MINIPORT_CO_ACTIVATE_VC") or + this.getName().matches("MINIPORT_CO_CREATE_VC") or + this.getName().matches("MINIPORT_CO_DEACTIVATE_VC") or + this.getName().matches("MINIPORT_CO_DELETE_VC") or + this.getName().matches("MINIPORT_CO_OID_REQUEST") or + this.getName().matches("MINIPORT_CO_SEND_NET_BUFFER_LISTS") or + this.getName().matches("PROTOCOL_BIND_ADAPTER_EX") or + this.getName().matches("PROTOCOL_CLOSE_ADAPTER_COMPLETE_EX") or + this.getName().matches("PROTOCOL_DIRECT_OID_REQUEST_COMPLETE") or + this.getName().matches("PROTOCOL_NET_PNP_EVENT") or + this.getName().matches("PROTOCOL_OID_REQUEST_COMPLETE") or + this.getName().matches("PROTOCOL_OPEN_ADAPTER_COMPLETE_EX") or + this.getName().matches("PROTOCOL_RECEIVE_NET_BUFFER_LISTS") or + this.getName().matches("PROTOCOL_SEND_NET_BUFFER_LISTS_COMPLETE") or + this.getName().matches("PROTOCOL_SET_OPTIONS") or + this.getName().matches("PROTOCOL_STATUS_EX") or + this.getName().matches("PROTOCOL_UNBIND_ADAPTER_EX") or + this.getName().matches("PROTOCOL_UNINSTALL") or + this.getName().matches("PROTOCOL_CL_ADD_PARTY_COMPLETE") or + this.getName().matches("PROTOCOL_CL_CALL_CONNECTED") or + this.getName().matches("PROTOCOL_CL_CLOSE_AF_COMPLETE") or + this.getName().matches("PROTOCOL_CL_CLOSE_CALL_COMPLETE") or + this.getName().matches("PROTOCOL_CL_DEREGISTER_SAP_COMPLETE") or + this.getName().matches("PROTOCOL_CL_DROP_PARTY_COMPLETE") or + this.getName().matches("PROTOCOL_CL_INCOMING_CALL") or + this.getName().matches("PROTOCOL_CL_INCOMING_CALL_QOS_CHANGE") or + this.getName().matches("PROTOCOL_CL_INCOMING_CLOSE_CALL") or + this.getName().matches("PROTOCOL_CL_INCOMING_DROP_PARTY") or + this.getName().matches("PROTOCOL_CL_MAKE_CALL_COMPLETE") or + this.getName().matches("PROTOCOL_CL_MODIFY_CALL_QOS_COMPLETE") or + this.getName().matches("PROTOCOL_CL_NOTIFY_CLOSE_AF") or + this.getName().matches("PROTOCOL_CL_OPEN_AF_COMPLETE") or + this.getName().matches("PROTOCOL_CL_OPEN_AF_COMPLETE_EX") or + this.getName().matches("PROTOCOL_CL_REGISTER_SAP_COMPLETE") or + this.getName().matches("PROTOCOL_CM_ACTIVATE_VC_COMPLETE") or + this.getName().matches("PROTOCOL_CM_ADD_PARTY") or + this.getName().matches("PROTOCOL_CM_CLOSE_AF") or + this.getName().matches("PROTOCOL_CM_CLOSE_CALL") or + this.getName().matches("PROTOCOL_CM_DEACTIVATE_VC_COMPLETE") or + this.getName().matches("PROTOCOL_CM_DEREGISTER_SAP") or + this.getName().matches("PROTOCOL_CM_DROP_PARTY") or + this.getName().matches("PROTOCOL_CM_INCOMING_CALL_COMPLETE") or + this.getName().matches("PROTOCOL_CM_MAKE_CALL") or + this.getName().matches("PROTOCOL_CM_MODIFY_QOS_CALL") or + this.getName().matches("PROTOCOL_CM_NOTIFY_CLOSE_AF_COMPLETE") or + this.getName().matches("PROTOCOL_CM_OPEN_AF") or + this.getName().matches("PROTOCOL_CM_REG_SAP") or + this.getName().matches("PROTCOL_CO_AF_REGISTER_NOTIFY") or + this.getName().matches("PROTOCOL_CO_CREATE_VC") or + this.getName().matches("PROTOCOL_CO_DELETE_VC") or + this.getName().matches("PROTOCOL_CO_OID_REQUEST") or + this.getName().matches("PROTOCOL_CO_OID_REQUEST_COMPLETE") or + this.getName().matches("PROTOCOL_CO_RECEIVE_NET_BUFFER_LISTS") or + this.getName().matches("PROTOCOL_CO_SEND_NET_BUFFER_LISTS_COMPLETE") or + this.getName().matches("PROTOCOL_CO_STATUS_EX") + ) + } +} + +/** A typedef for the standard NDIS callback routines. Aka Role Types */ +class NdisCallbackRoutineTypedef extends NdisRoleTypeType { + NdisCallbackRoutineTypedef() { this.getFile().getBaseName().matches("ndis.h") } +} + +/** + * Represents a function implementing a NDIS callback routine. + * Defines a function to be a callback routine iff it has a typedef + * in its definition which matches the NDIS callback typedefs, and it + * is in a NDIS driver (includes wdm.h.) + */ +class NdisCallbackRoutine extends Function { + /** The callback routine type, i.e. DRIVER_UNLOAD. */ + NdisCallbackRoutineTypedef callbackType; + + NdisCallbackRoutine() { + exists(FunctionDeclarationEntry fde | + fde.getFunction() = this and + fde.getTypedefType() = callbackType + ) + } +} + + +/** A NDIS DriverEntry callback routine. */ +class NdisDriverEntry extends NdisCallbackRoutine { + NdisDriverEntry() { callbackType.getName().matches("DRIVER_INITIALIZE") } +} + +/** A NDIS MiniportAllocateSharedMemoryComplete callback routine. */ +class NdisMiniportAllocateSharedMemoryComplete extends NdisCallbackRoutine { + NdisMiniportAllocateSharedMemoryComplete() { + callbackType.getName().matches("MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE") + } +} + +/** A NDIS MiniportHalt callback routine. */ +class NdisMiniportHalt extends NdisCallbackRoutine { + NdisMiniportHalt() { callbackType.getName().matches("MINIPORT_HALT") } +} + +/** A NDIS MiniportSetOptions callback routine. */ +class NdisMiniportSetOptions extends NdisCallbackRoutine { + NdisMiniportSetOptions() { callbackType.getName().matches("MINIPORT_SET_OPTIONS") } +} + +/** A NDIS MiniportInitialize callback routine. */ +class NdisMiniportInitialize extends NdisCallbackRoutine { + NdisMiniportInitialize() { callbackType.getName().matches("MINIPORT_INITIALIZE") } +} + +/** A NDIS MiniportPause callback routine. */ +class NdisMiniportPause extends NdisCallbackRoutine { + NdisMiniportPause() { callbackType.getName().matches("MINIPORT_PAUSE") } +} + +/** A NDIS MiniportRestart callback routine. */ +class NdisMiniportRestart extends NdisCallbackRoutine { + NdisMiniportRestart() { callbackType.getName().matches("MINIPORT_RESTART") } +} + +/** A NDIS MiniportOidRequest callback routine. */ +class NdisMiniportOidRequest extends NdisCallbackRoutine { + NdisMiniportOidRequest() { callbackType.getName().matches("MINIPORT_OID_REQUEST") } +} + +/** A NDIS MiniportInterruptDpc callback routine. */ +class NdisMiniportInterruptDpc extends NdisCallbackRoutine { + NdisMiniportInterruptDpc() { callbackType.getName().matches("MINIPORT_INTERRUPT_DPC") } +} + +/** A NDIS MiniportIsr callback routine. */ +class NdisMiniportIsr extends NdisCallbackRoutine { + NdisMiniportIsr() { callbackType.getName().matches("MINIPORT_ISR") } +} + +/** A NDIS MiniportReset callback routine. */ +class NdisMiniportReset extends NdisCallbackRoutine { + NdisMiniportReset() { callbackType.getName().matches("MINIPORT_RESET") } +} + +/** A NDIS MiniportReturnNetBufferLists callback routine. */ +class NdisMiniportReturnNetBufferLists extends NdisCallbackRoutine { + NdisMiniportReturnNetBufferLists() { + callbackType.getName().matches("MINIPORT_RETURN_NET_BUFFER_LISTS") + } +} + +/** A NDIS MiniportCancelOidRequest callback routine. */ +class NdisMiniportCancelOidRequest extends NdisCallbackRoutine { + NdisMiniportCancelOidRequest() { callbackType.getName().matches("MINIPORT_CANCEL_OID_REQUEST") } +} + +/** A NDIS MiniportShutdown callback routine. */ +class NdisMiniportShutdown extends NdisCallbackRoutine { + NdisMiniportShutdown() { callbackType.getName().matches("MINIPORT_SHUTDOWN") } +} + +/** A NDIS MiniportSendNetBufferLists callback routine. */ +class NdisMiniportSendNetBufferLists extends NdisCallbackRoutine { + NdisMiniportSendNetBufferLists() { + callbackType.getName().matches("MINIPORT_SEND_NET_BUFFER_LISTS") + } +} + +/** A NDIS MiniportCancelSend callback routine. */ +class NdisMiniportCancelSend extends NdisCallbackRoutine { + NdisMiniportCancelSend() { callbackType.getName().matches("MINIPORT_CANCEL_SEND") } +} + +/** A NDIS MiniportDevicePnpEventNotify callback routine. */ +class NdisMiniportDevicePnpEventNotify extends NdisCallbackRoutine { + NdisMiniportDevicePnpEventNotify() { + callbackType.getName().matches("MINIPORT_DEVICE_PNP_EVENT_NOTIFY") + } +} + +/** A NDIS MiniportUnload callback routine. */ +class NdisMiniportUnload extends NdisCallbackRoutine { + NdisMiniportUnload() { callbackType.getName().matches("MINIPORT_UNLOAD") } +} + +/** A NDIS MiniportCheckForHang callback routine. */ +class NdisMiniportCheckForHang extends NdisCallbackRoutine { + NdisMiniportCheckForHang() { callbackType.getName().matches("MINIPORT_CHECK_FOR_HANG") } +} + +/** A NDIS MiniportEnableInterrupt callback routine. */ +class NdisMiniportEnableInterrupt extends NdisCallbackRoutine { + NdisMiniportEnableInterrupt() { callbackType.getName().matches("MINIPORT_ENABLE_INTERRUPT") } +} + +/** A NDIS MiniportDisableInterrupt callback routine. */ +class NdisMiniportDisableInterrupt extends NdisCallbackRoutine { + NdisMiniportDisableInterrupt() { callbackType.getName().matches("MINIPORT_DISABLE_INTERRUPT") } +} + +/** A NDIS MiniportSynchronizeInterrupt callback routine. */ +class NdisMiniportSynchronizeInterrupt extends NdisCallbackRoutine { + NdisMiniportSynchronizeInterrupt() { + callbackType.getName().matches("MINIPORT_SYNCHRONIZE_INTERRUPT") + } +} + +/** A NDIS MiniportProcessSgList callback routine. */ +class NdisMiniportProcessSgList extends NdisCallbackRoutine { + NdisMiniportProcessSgList() { callbackType.getName().matches("MINIPORT_PROCESS_SG_LIST") } +} + +/** A NDIS timer callback routine. */ +class NdisTimerFunction extends NdisCallbackRoutine { + NdisTimerFunction() { callbackType.getName().matches("NDIS_TIMER_FUNCTION") } +} + +/** A NDIS I/O work item callback routine. */ +class NdisIoWorkitem extends NdisCallbackRoutine { + NdisIoWorkitem() { callbackType.getName().matches("NDIS_IO_WORKITEM") } +} + +/** A NDIS MiniportAddDevice callback routine. */ +class NdisMiniportAddDevice extends NdisCallbackRoutine { + NdisMiniportAddDevice() { callbackType.getName().matches("MINIPORT_ADD_DEVICE") } +} + +/** A NDIS MiniportCancelDirectOidRequest callback routine. */ +class NdisMiniportCancelDirectOidRequest extends NdisCallbackRoutine { + NdisMiniportCancelDirectOidRequest() { + callbackType.getName().matches("MINIPORT_CANCEL_DIRECT_OID_REQUEST") + } +} + +/** A NDIS MiniportDirectOidRequest callback routine. */ +class NdisMiniportDirectOidRequest extends NdisCallbackRoutine { + NdisMiniportDirectOidRequest() { callbackType.getName().matches("MINIPORT_DIRECT_OID_REQUEST") } +} + +/** A NDIS MiniportFilterResourceRequirements callback routine. */ +class NdisMiniportFilterResourceRequirements extends NdisCallbackRoutine { + NdisMiniportFilterResourceRequirements() { + callbackType.getName().matches("MINIPORT_FILTER_RESOURCE_REQUIREMENTS") + } +} + +/** A NDIS MiniportStartDevice callback routine. */ +class NdisMiniportStartDevice extends NdisCallbackRoutine { + NdisMiniportStartDevice() { callbackType.getName().matches("MINIPORT_START_DEVICE") } +} + +/** A NDIS MiniportSynchronizeMessageInterrupt callback routine. */ +class NdisMiniportSynchronizeMessageInterrupt extends NdisCallbackRoutine { + NdisMiniportSynchronizeMessageInterrupt() { + callbackType.getName().matches("MINIPORT_SYNCHRONIZE_MESSAGE_INTERRUPT") + } +} + +/** A NDIS IoWorkItemFunction callback routine. */ +class NdisIoWorkItemFunction extends NdisCallbackRoutine { + NdisIoWorkItemFunction() { callbackType.getName().matches("NDIS_IO_WORKITEM_FUNCTION") } +} + +/** A NDIS filter attach callback routine. */ +class NdisFilterAttach extends NdisCallbackRoutine { + NdisFilterAttach() { callbackType.getName().matches("FILTER_ATTACH") } +} + +/** A NDIS filter cancel direct OID request callback routine. */ +class NdisFilterCancelDirectOidRequest extends NdisCallbackRoutine { + NdisFilterCancelDirectOidRequest() { + callbackType.getName().matches("FILTER_CANCEL_DIRECT_OID_REQUEST") + } +} + +/** A NDIS filter cancel send net buffer lists callback routine. */ +class NdisFilterCancelSendNetBufferLists extends NdisCallbackRoutine { + NdisFilterCancelSendNetBufferLists() { + callbackType.getName().matches("FILTER_CANCEL_SEND_NET_BUFFER_LISTS") + } +} + +/** A NDIS filter cancel OID request callback routine. */ +class NdisFilterCancelOidRequest extends NdisCallbackRoutine { + NdisFilterCancelOidRequest() { callbackType.getName().matches("FILTER_CANCEL_OID_REQUEST") } +} + +/** A NDIS filter detach callback routine. */ +class NdisFilterDetach extends NdisCallbackRoutine { + NdisFilterDetach() { callbackType.getName().matches("FILTER_DETACH") } +} + +/** A NDIS filter device PNP event notify callback routine. */ +class NdisFilterDevicePnpEventNotify extends NdisCallbackRoutine { + NdisFilterDevicePnpEventNotify() { + callbackType.getName().matches("FILTER_DEVICE_PNP_EVENT_NOTIFY") + } +} + +/** A NDIS filter direct OID request callback routine. */ +class NdisFilterDirectOidRequest extends NdisCallbackRoutine { + NdisFilterDirectOidRequest() { callbackType.getName().matches("FILTER_DIRECT_OID_REQUEST") } +} + +/** A NDIS filter direct OID request complete callback routine. */ +class NdisFilterDirectOidRequestComplete extends NdisCallbackRoutine { + NdisFilterDirectOidRequestComplete() { + callbackType.getName().matches("FILTER_DIRECT_OID_REQUEST_COMPLETE") + } +} + +/** A NDIS driver unload callback routine. */ +class NdisDriverUnload extends NdisCallbackRoutine { + NdisDriverUnload() { callbackType.getName().matches("DRIVER_UNLOAD") } +} + +/** A NDIS filter net PNP event callback routine. */ +class NdisFilterNetPnpEvent extends NdisCallbackRoutine { + NdisFilterNetPnpEvent() { callbackType.getName().matches("FILTER_NET_PNP_EVENT") } +} + +/** A NDIS filter OID request callback routine. */ +class NdisFilterOidRequest extends NdisCallbackRoutine { + NdisFilterOidRequest() { callbackType.getName().matches("FILTER_OID_REQUEST") } +} + +/** A NDIS filter OID request complete callback routine. */ +class NdisFilterOidRequestComplete extends NdisCallbackRoutine { + NdisFilterOidRequestComplete() { callbackType.getName().matches("FILTER_OID_REQUEST_COMPLETE") } +} + +/** A NDIS filter pause callback routine. */ +class NdisFilterPause extends NdisCallbackRoutine { + NdisFilterPause() { callbackType.getName().matches("FILTER_PAUSE") } +} + +/** A NDIS filter receive net buffer lists callback routine. */ +class NdisFilterReceiveNetBufferLists extends NdisCallbackRoutine { + NdisFilterReceiveNetBufferLists() { + callbackType.getName().matches("FILTER_RECEIVE_NET_BUFFER_LISTS") + } +} + +/** A NDIS filter restart callback routine. */ +class NdisFilterRestart extends NdisCallbackRoutine { + NdisFilterRestart() { callbackType.getName().matches("FILTER_RESTART") } +} + +/** A NDIS filter return net buffer lists callback routine. */ +class NdisFilterReturnNetBufferLists extends NdisCallbackRoutine { + NdisFilterReturnNetBufferLists() { + callbackType.getName().matches("FILTER_RETURN_NET_BUFFER_LISTS") + } +} + +/** A NDIS filter send net buffer lists callback routine. */ +class NdisFilterSendNetBufferLists extends NdisCallbackRoutine { + NdisFilterSendNetBufferLists() { callbackType.getName().matches("FILTER_SEND_NET_BUFFER_LISTS") } +} + +/** A NDIS filter send net buffer lists complete callback routine. */ +class NdisFilterSendNetBufferListsComplete extends NdisCallbackRoutine { + NdisFilterSendNetBufferListsComplete() { + callbackType.getName().matches("FILTER_SEND_NET_BUFFER_LISTS_COMPLETE") + } +} + +/** A NDIS filter set module options callback routine. */ +class NdisFilterSetModuleOptions extends NdisCallbackRoutine { + NdisFilterSetModuleOptions() { callbackType.getName().matches("FILTER_SET_MODULE_OPTIONS") } +} + +/** A NDIS filter set options callback routine. */ +class NdisFilterSetOptions extends NdisCallbackRoutine { + NdisFilterSetOptions() { callbackType.getName().matches("FILTER_SET_OPTIONS") } +} + +/** A NDIS filter status callback routine. */ +class NdisFilterStatus extends NdisCallbackRoutine { + NdisFilterStatus() { callbackType.getName().matches("FILTER_STATUS") } +} + +/** A NDIS miniport CO activate VC callback routine. */ +class NdisMiniportCoActivateVc extends NdisCallbackRoutine { + NdisMiniportCoActivateVc() { callbackType.getName().matches("MINIPORT_CO_ACTIVATE_VC") } +} + +/** A NDIS miniport CO create VC callback routine. */ +class NdisMiniportCoCreateVc extends NdisCallbackRoutine { + NdisMiniportCoCreateVc() { callbackType.getName().matches("MINIPORT_CO_CREATE_VC") } +} + +/** A NDIS miniport CO deactivate VC callback routine. */ +class NdisMiniportCoDeactivateVc extends NdisCallbackRoutine { + NdisMiniportCoDeactivateVc() { callbackType.getName().matches("MINIPORT_CO_DEACTIVATE_VC") } +} + +/** A NDIS miniport CO delete VC callback routine. */ +class NdisMiniportCoDeleteVc extends NdisCallbackRoutine { + NdisMiniportCoDeleteVc() { callbackType.getName().matches("MINIPORT_CO_DELETE_VC") } +} + +/** A NDIS miniport CO OID request callback routine. */ +class NdisMiniportCoOidRequest extends NdisCallbackRoutine { + NdisMiniportCoOidRequest() { callbackType.getName().matches("MINIPORT_CO_OID_REQUEST") } +} + +/** A NDIS miniport CO send net buffer lists callback routine. */ +class NdisMiniportCoSendNetBufferLists extends NdisCallbackRoutine { + NdisMiniportCoSendNetBufferLists() { + callbackType.getName().matches("MINIPORT_CO_SEND_NET_BUFFER_LISTS") + } +} + +/** A NDIS protocol bind adapter ex callback routine. */ +class NdisProtocolBindAdapterEx extends NdisCallbackRoutine { + NdisProtocolBindAdapterEx() { callbackType.getName().matches("PROTOCOL_BIND_ADAPTER_EX") } +} + +/** A NDIS protocol close adapter complete ex callback routine. */ +class NdisProtocolCloseAdapterCompleteEx extends NdisCallbackRoutine { + NdisProtocolCloseAdapterCompleteEx() { + callbackType.getName().matches("PROTOCOL_CLOSE_ADAPTER_COMPLETE_EX") + } +} + +/** A NDIS protocol direct OID request complete callback routine. */ +class NdisProtocolDirectOidRequestComplete extends NdisCallbackRoutine { + NdisProtocolDirectOidRequestComplete() { + callbackType.getName().matches("PROTOCOL_DIRECT_OID_REQUEST_COMPLETE") + } +} + +/** A NDIS protocol net PNP event callback routine. */ +class NdisProtocolNetPnpEvent extends NdisCallbackRoutine { + NdisProtocolNetPnpEvent() { callbackType.getName().matches("PROTOCOL_NET_PNP_EVENT") } +} + +/** A NDIS protocol OID request complete callback routine. */ +class NdisProtocolOidRequestComplete extends NdisCallbackRoutine { + NdisProtocolOidRequestComplete() { + callbackType.getName().matches("PROTOCOL_OID_REQUEST_COMPLETE") + } +} + +/** A NDIS protocol open adapter complete ex callback routine. */ +class NdisProtocolOpenAdapterCompleteEx extends NdisCallbackRoutine { + NdisProtocolOpenAdapterCompleteEx() { + callbackType.getName().matches("PROTOCOL_OPEN_ADAPTER_COMPLETE_EX") + } +} + +/** A NDIS protocol receive net buffer lists callback routine. */ +class NdisProtocolReceiveNetBufferLists extends NdisCallbackRoutine { + NdisProtocolReceiveNetBufferLists() { + callbackType.getName().matches("PROTOCOL_RECEIVE_NET_BUFFER_LISTS") + } +} + +/** A NDIS protocol send net buffer lists complete callback routine. */ +class NdisProtocolSendNetBufferListsComplete extends NdisCallbackRoutine { + NdisProtocolSendNetBufferListsComplete() { + callbackType.getName().matches("PROTOCOL_SEND_NET_BUFFER_LISTS_COMPLETE") + } +} + +/** A NDIS protocol set options callback routine. */ +class NdisProtocolSetOptions extends NdisCallbackRoutine { + NdisProtocolSetOptions() { callbackType.getName().matches("PROTOCOL_SET_OPTIONS") } +} + +/** A NDIS protocol status ex callback routine. */ +class NdisProtocolStatusEx extends NdisCallbackRoutine { + NdisProtocolStatusEx() { callbackType.getName().matches("PROTOCOL_STATUS_EX") } +} + +/** A NDIS protocol unbind adapter ex callback routine. */ +class NdisProtocolUnbindAdapterEx extends NdisCallbackRoutine { + NdisProtocolUnbindAdapterEx() { callbackType.getName().matches("PROTOCOL_UNBIND_ADAPTER_EX") } +} + +/** A NDIS protocol uninstall callback routine. */ +class NdisProtocolUninstall extends NdisCallbackRoutine { + NdisProtocolUninstall() { callbackType.getName().matches("PROTOCOL_UNINSTALL") } +} + +/** A NDIS protocol call manager add party complete callback routine. */ +class NdisProtocolClAddPartyComplete extends NdisCallbackRoutine { + NdisProtocolClAddPartyComplete() { + callbackType.getName().matches("PROTOCOL_CL_ADD_PARTY_COMPLETE") + } +} + +/** A NDIS protocol call manager call connected callback routine. */ +class NdisProtocolClCallConnected extends NdisCallbackRoutine { + NdisProtocolClCallConnected() { callbackType.getName().matches("PROTOCOL_CL_CALL_CONNECTED") } +} + +/** A NDIS protocol call manager close AF complete callback routine. */ +class NdisProtocolClCloseAfComplete extends NdisCallbackRoutine { + NdisProtocolClCloseAfComplete() { + callbackType.getName().matches("PROTOCOL_CL_CLOSE_AF_COMPLETE") + } +} + +/** A NDIS protocol call manager close call complete callback routine. */ +class NdisProtocolClCloseCallComplete extends NdisCallbackRoutine { + NdisProtocolClCloseCallComplete() { + callbackType.getName().matches("PROTOCOL_CL_CLOSE_CALL_COMPLETE") + } +} + +/** A NDIS protocol call manager deregister SAP complete callback routine. */ +class NdisProtocolClDeregisterSapComplete extends NdisCallbackRoutine { + NdisProtocolClDeregisterSapComplete() { + callbackType.getName().matches("PROTOCOL_CL_DEREGISTER_SAP_COMPLETE") + } +} + +/** A NDIS protocol call manager drop party complete callback routine. */ +class NdisProtocolClDropPartyComplete extends NdisCallbackRoutine { + NdisProtocolClDropPartyComplete() { + callbackType.getName().matches("PROTOCOL_CL_DROP_PARTY_COMPLETE") + } +} + +/** A NDIS protocol call manager incoming call callback routine. */ +class NdisProtocolClIncomingCall extends NdisCallbackRoutine { + NdisProtocolClIncomingCall() { callbackType.getName().matches("PROTOCOL_CL_INCOMING_CALL") } +} + +/** A NDIS protocol call manager incoming call QoS change callback routine. */ +class NdisProtocolClIncomingCallQosChange extends NdisCallbackRoutine { + NdisProtocolClIncomingCallQosChange() { + callbackType.getName().matches("PROTOCOL_CL_INCOMING_CALL_QOS_CHANGE") + } +} + +/** A NDIS protocol call manager incoming close call callback routine. */ +class NdisProtocolClIncomingCloseCall extends NdisCallbackRoutine { + NdisProtocolClIncomingCloseCall() { + callbackType.getName().matches("PROTOCOL_CL_INCOMING_CLOSE_CALL") + } +} + +/** A NDIS protocol call manager incoming drop party callback routine. */ +class NdisProtocolClIncomingDropParty extends NdisCallbackRoutine { + NdisProtocolClIncomingDropParty() { + callbackType.getName().matches("PROTOCOL_CL_INCOMING_DROP_PARTY") + } +} + +/** A NDIS protocol call manager make call complete callback routine. */ +class NdisProtocolClMakeCallComplete extends NdisCallbackRoutine { + NdisProtocolClMakeCallComplete() { + callbackType.getName().matches("PROTOCOL_CL_MAKE_CALL_COMPLETE") + } +} + +/** A NDIS protocol call manager modify call QoS complete callback routine. */ +class NdisProtocolClModifyCallQosComplete extends NdisCallbackRoutine { + NdisProtocolClModifyCallQosComplete() { + callbackType.getName().matches("PROTOCOL_CL_MODIFY_CALL_QOS_COMPLETE") + } +} + +/** A NDIS protocol call manager notify close AF callback routine. */ +class NdisProtocolClNotifyCloseAf extends NdisCallbackRoutine { + NdisProtocolClNotifyCloseAf() { callbackType.getName().matches("PROTOCOL_CL_NOTIFY_CLOSE_AF") } +} + +/** A NDIS protocol call manager open AF complete callback routine. */ +class NdisProtocolClOpenAfComplete extends NdisCallbackRoutine { + NdisProtocolClOpenAfComplete() { callbackType.getName().matches("PROTOCOL_CL_OPEN_AF_COMPLETE") } +} + +/** A NDIS protocol call manager open AF complete ex callback routine. */ +class NdisProtocolClOpenAfCompleteEx extends NdisCallbackRoutine { + NdisProtocolClOpenAfCompleteEx() { + callbackType.getName().matches("PROTOCOL_CL_OPEN_AF_COMPLETE_EX") + } +} + +/** A NDIS protocol call manager register SAP complete callback routine. */ +class NdisProtocolClRegisterSapComplete extends NdisCallbackRoutine { + NdisProtocolClRegisterSapComplete() { + callbackType.getName().matches("PROTOCOL_CL_REGISTER_SAP_COMPLETE") + } +} + +/** A NDIS protocol connection manager activate VC complete callback routine. */ +class NdisProtocolCmActivateVcComplete extends NdisCallbackRoutine { + NdisProtocolCmActivateVcComplete() { + callbackType.getName().matches("PROTOCOL_CM_ACTIVATE_VC_COMPLETE") + } +} + +/** A NDIS protocol connection manager add party callback routine. */ +class NdisProtocolCmAddParty extends NdisCallbackRoutine { + NdisProtocolCmAddParty() { callbackType.getName().matches("PROTOCOL_CM_ADD_PARTY") } +} + +/** A NDIS protocol connection manager close AF callback routine. */ +class NdisProtocolCmCloseAf extends NdisCallbackRoutine { + NdisProtocolCmCloseAf() { callbackType.getName().matches("PROTOCOL_CM_CLOSE_AF") } +} + +/** A NDIS protocol connection manager close call callback routine. */ +class NdisProtocolCmCloseCall extends NdisCallbackRoutine { + NdisProtocolCmCloseCall() { callbackType.getName().matches("PROTOCOL_CM_CLOSE_CALL") } +} + +/** A NDIS protocol connection manager deactivate VC complete callback routine. */ +class NdisProtocolCmDeactivateVcComplete extends NdisCallbackRoutine { + NdisProtocolCmDeactivateVcComplete() { + callbackType.getName().matches("PROTOCOL_CM_DEACTIVATE_VC_COMPLETE") + } +} + +/** A NDIS protocol connection manager deregister SAP callback routine. */ +class NdisProtocolCmDeregisterSap extends NdisCallbackRoutine { + NdisProtocolCmDeregisterSap() { callbackType.getName().matches("PROTOCOL_CM_DEREGISTER_SAP") } +} + +/** A NDIS protocol connection manager drop party callback routine. */ +class NdisProtocolCmDropParty extends NdisCallbackRoutine { + NdisProtocolCmDropParty() { callbackType.getName().matches("PROTOCOL_CM_DROP_PARTY") } +} + +/** A NDIS protocol connection manager incoming call complete callback routine. */ +class NdisProtocolCmIncomingCallComplete extends NdisCallbackRoutine { + NdisProtocolCmIncomingCallComplete() { + callbackType.getName().matches("PROTOCOL_CM_INCOMING_CALL_COMPLETE") + } +} + +/** A NDIS protocol connection manager make call callback routine. */ +class NdisProtocolCmMakeCall extends NdisCallbackRoutine { + NdisProtocolCmMakeCall() { callbackType.getName().matches("PROTOCOL_CM_MAKE_CALL") } +} + +/** A NDIS protocol connection manager modify QoS call callback routine. */ +class NdisProtocolCmModifyQosCall extends NdisCallbackRoutine { + NdisProtocolCmModifyQosCall() { callbackType.getName().matches("PROTOCOL_CM_MODIFY_QOS_CALL") } +} + +/** A NDIS protocol connection manager notify close AF complete callback routine. */ +class NdisProtocolCmNotifyCloseAfComplete extends NdisCallbackRoutine { + NdisProtocolCmNotifyCloseAfComplete() { + callbackType.getName().matches("PROTOCOL_CM_NOTIFY_CLOSE_AF_COMPLETE") + } +} + +/** A NDIS protocol connection manager open AF callback routine. */ +class NdisProtocolCmOpenAf extends NdisCallbackRoutine { + NdisProtocolCmOpenAf() { callbackType.getName().matches("PROTOCOL_CM_OPEN_AF") } +} + +/** A NDIS protocol connection manager register SAP callback routine. */ +class NdisProtocolCmRegSap extends NdisCallbackRoutine { + NdisProtocolCmRegSap() { callbackType.getName().matches("PROTOCOL_CM_REG_SAP") } +} + +/** A NDIS protocol CO AF register notify callback routine. */ +class NdisProtocolCoAfRegisterNotify extends NdisCallbackRoutine { + NdisProtocolCoAfRegisterNotify() { + callbackType.getName().matches("PROTCOL_CO_AF_REGISTER_NOTIFY") + } +} + +/** A NDIS protocol CO create VC callback routine. */ +class NdisProtocolCoCreateVc extends NdisCallbackRoutine { + NdisProtocolCoCreateVc() { callbackType.getName().matches("PROTOCOL_CO_CREATE_VC") } +} + +/** A NDIS protocol CO delete VC callback routine. */ +class NdisProtocolCoDeleteVc extends NdisCallbackRoutine { + NdisProtocolCoDeleteVc() { callbackType.getName().matches("PROTOCOL_CO_DELETE_VC") } +} + +/** A NDIS protocol CO OID request callback routine. */ +class NdisProtocolCoOidRequest extends NdisCallbackRoutine { + NdisProtocolCoOidRequest() { callbackType.getName().matches("PROTOCOL_CO_OID_REQUEST") } +} + +/** A NDIS protocol CO OID request complete callback routine. */ +class NdisProtocolCoOidRequestComplete extends NdisCallbackRoutine { + NdisProtocolCoOidRequestComplete() { + callbackType.getName().matches("PROTOCOL_CO_OID_REQUEST_COMPLETE") + } +} + +/** A NDIS protocol CO receive net buffer lists callback routine. */ +class NdisProtocolCoReceiveNetBufferLists extends NdisCallbackRoutine { + NdisProtocolCoReceiveNetBufferLists() { + callbackType.getName().matches("PROTOCOL_CO_RECEIVE_NET_BUFFER_LISTS") + } +} + +/** A NDIS protocol CO send net buffer lists complete callback routine. */ +class NdisProtocolCoSendNetBufferListsComplete extends NdisCallbackRoutine { + NdisProtocolCoSendNetBufferListsComplete() { + callbackType.getName().matches("PROTOCOL_CO_SEND_NET_BUFFER_LISTS_COMPLETE") + } +} + +/** A NDIS protocol CO status ex callback routine. */ +class NdisProtocolCoStatusEx extends NdisCallbackRoutine { + NdisProtocolCoStatusEx() { callbackType.getName().matches("PROTOCOL_CO_STATUS_EX") } +} diff --git a/src/drivers/storport/libraries/StorportDrivers.qll b/src/drivers/storport/libraries/StorportDrivers.qll new file mode 100644 index 00000000..42e677b7 --- /dev/null +++ b/src/drivers/storport/libraries/StorportDrivers.qll @@ -0,0 +1,251 @@ +/** + * This QL library defines classes and predicates for analyzing NDIS drivers. + * It provides definitions for NDIS dispatch routines, callback routines, and role types. + * The library also includes a typedef for the standard NDIS callback routines. + */ + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +import cpp +import drivers.libraries.SAL + + +/** Determines if a given assignment, recursively, has a Storport callback routine as the right-hand side. */ + +private predicate isCallbackRoutineAssignment(AssignExpr ae) { + exists(FunctionAccess fa | + ae.getRValue() = fa and + fa.getTarget() instanceof StorportCallbackRoutine + ) + or + ae.getRValue() instanceof AssignExpr and + isCallbackRoutineAssignment(ae.getRValue().(AssignExpr)) +} + +/** A typedef for Role Types */ +class StorportRoleTypeType extends TypedefType { + StorportRoleTypeType() { + ( + this.getName().matches("sp_DRIVER_INITIALIZE") or + this.getName().matches("HW_INITIALIZE") or + this.getName().matches("HW_BUILDIO") or + this.getName().matches("HW_STARTIO") or + this.getName().matches("HW_INTERRUPT") or + this.getName().matches("HW_TIMER") or + this.getName().matches("HW_FIND_ADAPTER") or + this.getName().matches("HW_RESET_BUS") or + this.getName().matches("HW_ADAPTER_CONTROL") or + this.getName().matches("HW_PASSIVE_INITIALIZE_ROUTINE") or + this.getName().matches("HW_DPC_ROUTINE") or + this.getName().matches("HW_FREE_ADAPTER_RESOURCES") or + this.getName().matches("HW_PROCESS_SERVICE_REQUEST") or + this.getName().matches("HW_COMPLETE_SERVICE_IRP") or + this.getName().matches("HW_INITIALIZE_TRACING") or + this.getName().matches("HW_CLEANUP_TRACING") or + this.getName().matches("VIRTUAL_HW_FIND_ADAPTER") or + this.getName().matches("HW_MESSAGE_SIGNALED_INTERRUPT_ROUTINE") + ) + } +} + +/** A typedef for the standard Storport callback routines. Aka Role Types */ + +class StorportCallbackRoutineTypedef extends StorportRoleTypeType { + StorportCallbackRoutineTypedef() { this.getFile().getBaseName().matches("storport.h") } +} + +/** + * Represents a function implementing a Storport callback routine. + + * Defines a function to be a callback routine iff it has a typedef + * in its definition which matches the Storport callback typedefs, and it + + * is in a Storport driver (includes wdm.h.) + + */ +class StorportCallbackRoutine extends Function { + /** The callback routine type, i.e. DRIVER_UNLOAD. */ + StorportCallbackRoutineTypedef callbackType; + + StorportCallbackRoutine() { + exists(FunctionDeclarationEntry fde | + fde.getFunction() = this and + fde.getTypedefType() = callbackType + ) + } +} + +/** + * Similar to StorportCallbackRoutine, but specifically for Role Types + */ +abstract class StorportRoleTypeFunction extends Function { + StorportCallbackRoutineTypedef roleType; + + StorportRoleTypeFunction() { + exists(FunctionDeclarationEntry fde | + fde.getFunction() = this and + fde.getTypedefType() = roleType + ) + } + + string getRoleTypeString() { result = roleType.getName() } + + StorportRoleTypeType getRoleTypeType() { result = roleType } +} + +predicate hasRoleType(Function f) { f instanceof StorportRoleTypeFunction } + +class StorportDriverObjectFunctionAccess extends FunctionAccess { + StorportRoleTypeType rttExpected; + + StorportDriverObjectFunctionAccess() { + exists(VariableAccess driverObjectAccess, AssignExpr driverObjectAssign | + driverObjectAccess.getTarget().getType().getName().matches("PDRIVER_OBJECT") and + this = driverObjectAssign.getRValue() and + rttExpected = driverObjectAssign.getLValue().getUnderlyingType().(PointerType).getBaseType() + ) + } + + StorportRoleTypeType getExpectedRoleTypeType() { result = rttExpected } +} + +class StorportDriverEntryPoint extends FunctionAccess { + StorportDriverEntryPoint() { this instanceof StorportDriverObjectFunctionAccess } +} + +// declared functions that are used as if they have a role type, wether or not they do +class StorportImplicitRoleTypeFunction extends Function { + StorportRoleTypeType rttExpected; + FunctionAccess funcUse; + + StorportImplicitRoleTypeFunction() { + exists(FunctionCall fc, int n | fc.getArgument(n) instanceof FunctionAccess | + this = fc.getArgument(n).(FunctionAccess).getTarget() and + fc.getTarget().getParameter(n).getUnderlyingType().(PointerType).getBaseType() instanceof + StorportRoleTypeType and + rttExpected = fc.getTarget().getParameter(n).getUnderlyingType().(PointerType).getBaseType() and + fc.getTarget().getParameter(n).getUnderlyingType().(PointerType).getBaseType() instanceof + StorportRoleTypeType and + funcUse = fc.getArgument(n) + ) + or + exists(StorportDriverObjectFunctionAccess funcAssign | + funcAssign.getTarget() = this and + rttExpected = funcAssign.getExpectedRoleTypeType() and + funcUse = funcAssign + ) + } + + string getExpectedRoleTypeString() { result = rttExpected.toString() } + + StorportRoleTypeType getExpectedRoleTypeType() { result = rttExpected } + + string getActualRoleTypeString() { + if this instanceof StorportRoleTypeFunction + then result = this.(StorportRoleTypeFunction).getRoleTypeType().toString() + else result = "" + } + + FunctionAccess getFunctionUse() { result = funcUse } +} + +/** A Storport protocol Driver Initialize callback routine. */ +class StorportDriverInitialize extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportDriverInitialize() { callbackType.getName().matches("sp_DRIVER_INITIALIZE") } +} + +/** A Storport protocol Hardware Initialize callback routine. */ +class StorportHwInitialize extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwInitialize() { callbackType.getName().matches("HW_INITIALIZE") } +} + +/** A Storport protocol Hardware Build IO callback routine. */ +class StorportHwBuildIo extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwBuildIo() { callbackType.getName().matches("HW_BUILDIO") } +} + +/** A Storport protocol Hardware Start IO callback routine. */ +class StorportHwStartIo extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwStartIo() { callbackType.getName().matches("HW_STARTIO") } +} + +/** A Storport protocol Hardware Interrupt callback routine. */ +class StorportHwInterrupt extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwInterrupt() { callbackType.getName().matches("HW_INTERRUPT") } +} + +/** A Storport protocol Hardware Timer callback routine. */ +class StorportHwTimer extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwTimer() { callbackType.getName().matches("HW_TIMER") } +} + +/** A Storport protocol Hardware Find Adapter callback routine. */ +class StorportHwFindAdapter extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwFindAdapter() { callbackType.getName().matches("HW_FIND_ADAPTER") } +} + +/** A Storport protocol Hardware Reset Bus callback routine. */ +class StorportHwResetBus extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwResetBus() { callbackType.getName().matches("HW_RESET_BUS") } +} + +/** A Storport protocol Hardware Adapter Control callback routine. */ +class StorportHwAdapterControl extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwAdapterControl() { callbackType.getName().matches("HW_ADAPTER_CONTROL") } +} + +/** A Storport protocol Hardware Passive Initialize callback routine. */ +class StorportHwPassiveInitializeRoutine extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwPassiveInitializeRoutine() { + callbackType.getName().matches("HW_PASSIVE_INITIALIZE_ROUTINE") + } +} + +/** A Storport protocol Hardware DPC callback routine. */ +class StorportHwDpcRoutine extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwDpcRoutine() { callbackType.getName().matches("HW_DPC_ROUTINE") } +} + +/** A Storport protocol Hardware Free Adapter Resources callback routine. */ +class StorportHwFreeAdapterResources extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwFreeAdapterResources() { callbackType.getName().matches("HW_FREE_ADAPTER_RESOURCES") } +} + +/** A Storport protocol Hardware Process Service Request callback routine. */ +class StorportHwProcessServiceRequest extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwProcessServiceRequest() { callbackType.getName().matches("HW_PROCESS_SERVICE_REQUEST") } +} + +/** A Storport protocol Hardware Complete Service IRP callback routine. */ +class StorportHwCompleteServiceIrp extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwCompleteServiceIrp() { callbackType.getName().matches("HW_COMPLETE_SERVICE_IRP") } +} + +/** A Storport protocol Hardware Initialize Tracing callback routine. */ +class StorportHwInitializeTracing extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwInitializeTracing() { callbackType.getName().matches("HW_INITIALIZE_TRACING") } +} + +/** A Storport protocol Hardware Cleanup Tracing callback routine. */ +class StorportHwCleanupTracing extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportHwCleanupTracing() { callbackType.getName().matches("HW_CLEANUP_TRACING") } +} + +/** A Storport protocol Virtual Hardware Find Adapter callback routine. */ +class StorportVirtualHwFindAdapter extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportVirtualHwFindAdapter() { callbackType.getName().matches("VIRTUAL_HW_FIND_ADAPTER") } +} + +/** A Storport protocol Hardware Message Signaled Interrupt callback routine. */ +class StorportHwMessageSignaledInterruptRoutine extends StorportCallbackRoutine, + StorportRoleTypeFunction +{ + StorportHwMessageSignaledInterruptRoutine() { + callbackType.getName().matches("HW_MESSAGE_SIGNALED_INTERRUPT_ROUTINE") + } +} + +/** A Storport protocol Driver Unload callback routine. */ +class StorportDriverUnload extends StorportCallbackRoutine, StorportRoleTypeFunction { + StorportDriverUnload() { callbackType.getName().matches("DRIVER_UNLOAD") } +} diff --git a/src/drivers/test/build_create_analyze_test.cmd b/src/drivers/test/build_create_analyze_test.cmd new file mode 100644 index 00000000..d9fbac95 --- /dev/null +++ b/src/drivers/test/build_create_analyze_test.cmd @@ -0,0 +1,68 @@ +rd /s /q working >NUL 2>&1 +rd /s /q TestDB >NUL 2>&1 +rd /s /q AnalysisFiles >NUL 2>&1 + + +call :test PendingStatusError WDMTestTemplate wdm queries +call :test ExaminedValue WDMTestTemplate wdm queries +call :test StrSafe KMDFTestTemplate kmdf queries +call :test MultiplePagedCode WDMTestTemplate wdm queries +call :test NoPagedCode WDMTestTemplate wdm queries +call :test NoPagingSegment WDMTestTemplate wdm queries +call :test OpaqueMdlUse WDMTestTemplate wdm queries +call :test OpaqueMdlWrite WDMTestTemplate wdm queries +call :test KeWaitLocal WDMTestTemplate wdm queries +call :test IrqlTooHigh WDMTestTemplate general queries\experimental +call :test IrqlTooLow WDMTestTemplate general queries\experimental +call :test IrqlSetTooHigh WDMTestTemplate general queries\experimental +call :test IrqlSetTooLow WDMTestTemplate general queries\experimental +call :test WrongDispatchTableAssignment WDMTestTemplate wdm queries +call :test ExtendedDeprecatedApis WDMTestTemplate general queries +call :test WdkDeprecatedApis WDMTestTemplate general queries +call :test IllegalFieldAccess WDMTestTemplate wdm queries +call :test PoolTagIntegral WDMTestTemplate general queries +call :test ObReferenceMode WDMTestTemplate wdm queries +call :test DeviceInitApi KMDFTestTemplate kmdf queries\experimental +call :test DefaultPoolTag WDMTestTemplate general queries +call :test DefaultPoolTagExtended WDMTestTemplate general queries\experimental +call :test InitNotCleared WDMTestTemplate wdm queries +call :test IrqlNotUsed WDMTestTemplate general queries +call :test IrqlNotSaved WDMTestTemplate general queries +call :test IllegalFieldWrite WDMTestTemplate wdm queries +call :test IllegalFieldAccess2 WDMTestTemplate wdm queries +call :test RoleTypeCorrectlyUsed WDMTestTemplate general queries +call :test RoutineFunctionTypeNotExpected WDMTestTemplate general queries +call :test KeSetEventIrql WDMTestTemplate general queries\experimental +call :test KeSetEventPageable WDMTestTemplate general queries + +exit /b 0 + +:test +echo %0 %1 { +rd /s /q working\%1 >NUL 2>&1 +robocopy /e %2 working\%1\ +robocopy /e ..\%3\%4\%1\ working\%1\driver\ + +cd working\%1 + +echo building +msbuild /t:rebuild /p:platform=x64 + + +@REM the "..\..\TestDB\%1" in the command below specifies a location for the database we want to create. The %1 will correspond to the +@REM first argument of the calls above, for example, PendingStatusError for the first call. +echo creating_database +mkdir ..\..\TestDB +codeql database create -l=cpp -c "msbuild /p:Platform=x64 /t:rebuild" "..\..\TestDB\%1" + +@REM Similar to the case above, the %1 corresponds to PendingStatusError +cd ..\.. +echo analysing_database +mkdir "AnalysisFiles\Test Samples" +codeql database analyze "TestDB\%1" --format=sarifv2.1.0 --output="AnalysisFiles\Test Samples\%1.sarif" "..\%3\%4\%1\*.ql" + + +echo comparing analysis result with expected result +sarif diff -o "diff\%1.sarif" "..\%3\%4\%1\%1.sarif" "AnalysisFiles\Test Samples\%1.sarif" + +echo %0 %1 } diff --git a/src/drivers/test/diff/ExaminedValue.sarif b/src/drivers/test/diff/ExaminedValue.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/ExaminedValue.sarif +++ b/src/drivers/test/diff/ExaminedValue.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IllegalFieldAccess.sarif b/src/drivers/test/diff/IllegalFieldAccess.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IllegalFieldAccess.sarif +++ b/src/drivers/test/diff/IllegalFieldAccess.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IllegalFieldAccess2.sarif b/src/drivers/test/diff/IllegalFieldAccess2.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IllegalFieldAccess2.sarif +++ b/src/drivers/test/diff/IllegalFieldAccess2.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IllegalFieldWrite.sarif b/src/drivers/test/diff/IllegalFieldWrite.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IllegalFieldWrite.sarif +++ b/src/drivers/test/diff/IllegalFieldWrite.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IrqlNotSaved.sarif b/src/drivers/test/diff/IrqlNotSaved.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IrqlNotSaved.sarif +++ b/src/drivers/test/diff/IrqlNotSaved.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IrqlNotUsed.sarif b/src/drivers/test/diff/IrqlNotUsed.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IrqlNotUsed.sarif +++ b/src/drivers/test/diff/IrqlNotUsed.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IrqlSetTooHigh.sarif b/src/drivers/test/diff/IrqlSetTooHigh.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IrqlSetTooHigh.sarif +++ b/src/drivers/test/diff/IrqlSetTooHigh.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IrqlTooHigh.sarif b/src/drivers/test/diff/IrqlTooHigh.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IrqlTooHigh.sarif +++ b/src/drivers/test/diff/IrqlTooHigh.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/IrqlTooLow.sarif b/src/drivers/test/diff/IrqlTooLow.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/IrqlTooLow.sarif +++ b/src/drivers/test/diff/IrqlTooLow.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/KeWaitLocal.sarif b/src/drivers/test/diff/KeWaitLocal.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/KeWaitLocal.sarif +++ b/src/drivers/test/diff/KeWaitLocal.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/MultiplePagedCode.sarif b/src/drivers/test/diff/MultiplePagedCode.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/MultiplePagedCode.sarif +++ b/src/drivers/test/diff/MultiplePagedCode.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/NoPagedCode.sarif b/src/drivers/test/diff/NoPagedCode.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/NoPagedCode.sarif +++ b/src/drivers/test/diff/NoPagedCode.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/NoPagingSegment.sarif b/src/drivers/test/diff/NoPagingSegment.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/NoPagingSegment.sarif +++ b/src/drivers/test/diff/NoPagingSegment.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/OpaqueMdlUse.sarif b/src/drivers/test/diff/OpaqueMdlUse.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/OpaqueMdlUse.sarif +++ b/src/drivers/test/diff/OpaqueMdlUse.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/OpaqueMdlWrite.sarif b/src/drivers/test/diff/OpaqueMdlWrite.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/OpaqueMdlWrite.sarif +++ b/src/drivers/test/diff/OpaqueMdlWrite.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/PendingStatusError.sarif b/src/drivers/test/diff/PendingStatusError.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/PendingStatusError.sarif +++ b/src/drivers/test/diff/PendingStatusError.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/RoleTypeCorrectlyUsed.sarif b/src/drivers/test/diff/RoleTypeCorrectlyUsed.sarif new file mode 100644 index 00000000..8d5a80f9 --- /dev/null +++ b/src/drivers/test/diff/RoleTypeCorrectlyUsed.sarif @@ -0,0 +1,21 @@ +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } +} \ No newline at end of file diff --git a/src/drivers/test/diff/StrSafe.sarif b/src/drivers/test/diff/StrSafe.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/StrSafe.sarif +++ b/src/drivers/test/diff/StrSafe.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/test/diff/WrongDispatchTableAssignment.sarif b/src/drivers/test/diff/WrongDispatchTableAssignment.sarif index dea8275e..8d5a80f9 100644 --- a/src/drivers/test/diff/WrongDispatchTableAssignment.sarif +++ b/src/drivers/test/diff/WrongDispatchTableAssignment.sarif @@ -1,21 +1,21 @@ -{ - "all": { - "+": 0, - "-": 0 - }, - "error": { - "+": 0, - "-": 0, - "codes": [] - }, - "warning": { - "+": 0, - "-": 0, - "codes": [] - }, - "note": { - "+": 0, - "-": 0, - "codes": [] - } +{ + "all": { + "+": 0, + "-": 0 + }, + "error": { + "+": 0, + "-": 0, + "codes": [] + }, + "warning": { + "+": 0, + "-": 0, + "codes": [] + }, + "note": { + "+": 0, + "-": 0, + "codes": [] + } } \ No newline at end of file diff --git a/src/drivers/wdm/libraries/WdmDrivers.qll b/src/drivers/wdm/libraries/WdmDrivers.qll index 3dbd57f6..2dea9558 100644 --- a/src/drivers/wdm/libraries/WdmDrivers.qll +++ b/src/drivers/wdm/libraries/WdmDrivers.qll @@ -38,30 +38,31 @@ class DriverExtension extends Struct { } } -/** A typedef for the standard WDM callback routines. */ -class WdmCallbackRoutineTypedef extends TypedefType { - WdmCallbackRoutineTypedef() { +/** A typedef for Role Types */ +class WdmRoleTypeType extends TypedefType { + WdmRoleTypeType() { ( - this.getName().matches("DRIVER_UNLOAD") - or - this.getName().matches("DRIVER_DISPATCH") - or - this.getName().matches("DRIVER_INITIALIZE") - or - this.getName().matches("DRIVER_CANCEL") - or - this.getName().matches("IO_COMPLETION_ROUTINE") - or - this.getName().matches("KSERVICE_ROUTINE") - or - this.getName().matches("IO_DPC_ROUTINE") - or - this.getName().matches("DRIVER_ADD_DEVICE") - ) and - this.getFile().getBaseName().matches("wdm.h") + this.getName().matches("DRIVER_INITIALIZE") or + this.getName().matches("DRIVER_STARTIO") or + this.getName().matches("DRIVER_UNLOAD") or + this.getName().matches("DRIVER_ADD_DEVICE") or + this.getName().matches("DRIVER_DISPATCH") or + this.getName().matches("IO_COMPLETION_ROUTINE") or + this.getName().matches("DRIVER_CANCEL") or + this.getName().matches("IO_DPC_ROUTINE") or + this.getName().matches("KDEFERRED_ROUTINE") or + this.getName().matches("KSERVICE_ROUTINE") or + this.getName().matches("REQUEST_POWER_COMPLETE") or + this.getName().matches("WORKER_THREAD_ROUTINE") + ) } } +/** A typedef for the standard WDM callback routines. Aka Role Types */ +class WdmCallbackRoutineTypedef extends WdmRoleTypeType { + WdmCallbackRoutineTypedef() { this.getFile().getBaseName().matches("wdm.h") } +} + /** * Represents a function implementing a WDM callback routine. * Defines a function to be a callback routine iff it has a typedef @@ -80,24 +81,137 @@ class WdmCallbackRoutine extends Function { } } + +/** A WDM DriverEntry callback routine. */ +class WdmDriverEntry extends WdmCallbackRoutine { + WdmDriverEntry() { callbackType.getName().matches("DRIVER_INITIALIZE") } + + string getExpectedMaxIrqlLevelString() { result = "PASSIVE_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } +} + +/** A WDM DrierStartIo callback routine */ +class WdmDriverStartIo extends WdmCallbackRoutine { + WdmDriverStartIo() { callbackType.getName().matches("DRIVER_STARTIO") } + + string getExpectedMaxIrqlLevelString() { result = "DISPATCH_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } +} + +/** + * A WDM DriverUnload callback routine. + */ +class WdmDriverUnload extends WdmCallbackRoutine { + WdmDriverUnload() { callbackType.getName().matches("DRIVER_UNLOAD") } + + string getExpectedMaxIrqlLevelString() { result = "PASSIVE_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } +} + +// NOTE duplicate for backward compatibility with other query. Remove when other query is updated. /** A WDM AddDevice callback routine. */ class WdmAddDevice extends WdmCallbackRoutine { WdmAddDevice() { callbackType.getName().matches("DRIVER_ADD_DEVICE") } } -/** A WDM DriverUnload callback routine. */ -class WdmDriverUnload extends WdmCallbackRoutine { - WdmDriverUnload() { callbackType.getName().matches("DRIVER_UNLOAD") } +/** + * A WDM DriverAddDevice callback routine. + */ +class WdmDriverAddDevice extends WdmCallbackRoutine { + WdmDriverAddDevice() { callbackType.getName().matches("DRIVER_ADD_DEVICE") } + + string getExpectedMaxIrqlLevelString() { result = "PASSIVE_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } } -/** A WDM DriverEntry callback routine. */ -class WdmDriverEntry extends WdmCallbackRoutine { - WdmDriverEntry() { callbackType.getName().matches("DRIVER_INITIALIZE") } +/** + * A WDM DriverDispatch callback routine. + */ +class WdmDriverDispatch extends WdmCallbackRoutine { + WdmDriverDispatch() { callbackType.getName().matches("DRIVER_DISPATCH") } + + string getExpectedMaxIrqlLevelString() { result = "PASSIVE_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } } -/** A WDM DriverCancel callback routine. */ +/** + * A WDM IO completion routine. + */ +class WdmDriverCompletionRoutine extends WdmCallbackRoutine { + WdmDriverCompletionRoutine() { callbackType.getName().matches("IO_COMPLETION_ROUTINE") } + + string getExpectedMaxIrqlLevelString() { result = "DISPATCH_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } +} + +/** + * A WDM DriverCancel callback routine. + */ class WdmDriverCancel extends WdmCallbackRoutine { - WdmDriverCancel() { callbackType.getName().matches("DRIVER_CANCEL")} + WdmDriverCancel() { callbackType.getName().matches("DRIVER_CANCEL") } + + string getExpectedMaxIrqlLevelString() { result = "DISPATCH_LEVEL" } +} + +/** + * A WDM DriverDpcRoutine callback routine. + */ +class WdmDriverDpcRoutine extends WdmCallbackRoutine { + WdmDriverDpcRoutine() { callbackType.getName().matches("IO_DPC_ROUTINE") } + + string getExpectedMaxIrqlLevelString() { result = "DISPATCH_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "DISPATCH_LEVEL" } +} + +/** + * A WDM DriverDeferredRoutine callback routine. + */ +class WdmDriverDeferredRoutine extends WdmCallbackRoutine { + WdmDriverDeferredRoutine() { callbackType.getName().matches("KDEFERRED_ROUTINE") } + + string getExpectedMaxIrqlLevelString() { result = "DISPATCH_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "DISPATCH_LEVEL" } +} + +/** + * A WDM DriverServiceRoutine callback routine. + */ +class WdmDriverServiceRoutine extends WdmCallbackRoutine { + WdmDriverServiceRoutine() { callbackType.getName().matches("KSERVICE_ROUTINE") } + + string getExpectedMaxIrqlLevelString() { result = "DIRQL" } + + string getExpectedMinIrqlLevelString() { result = "DIRQL" } +} + +/** + * A WDM DriverPowerComplete callback routine. + */ +class WdmDriverPowerComplete extends WdmCallbackRoutine { + WdmDriverPowerComplete() { callbackType.getName().matches("REQUEST_POWER_COMPLETE") } + + string getExpectedMaxIrqlLevelString() { result = "DISPATCH_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } +} + +/** + * A WDM DriverWorkerThreadRoutine callback routine. + */ +class WdmDriverWorkerThreadRoutine extends WdmCallbackRoutine { + WdmDriverWorkerThreadRoutine() { callbackType.getName().matches("WORKER_THREAD_ROUTINE") } + + string getExpectedMaxIrqlLevelString() { result = "PASSIVE_LEVEL" } + + string getExpectedMinIrqlLevelString() { result = "PASSIVE_LEVEL" } } /**