在 Windows 驱动程序代码上运行 CodeQL 分析

CodeQL 是一个功能强大的静态分析引擎,可帮助开发人员识别 Windows 驱动程序源代码中的安全漏洞和代码冲突。 本文介绍如何使用 CodeQL 分析为 Windows 硬件兼容性计划 (WHCP) 认证创建驱动程序验证文件。

本文内容:

  • 安装相应的 CodeQL 版本。
  • 安装必要的 CodeQL 包和查询套件。
  • 运行 CodeQL 以生成数据库并分析代码。
  • 生成驱动程序验证文件。

为驱动程序选择适当的 CodeQL 版本

注释

Visual Studio (VS) 17.8 中断了与WHCP_21H2和WHCP_22H2分支中使用的旧版 CodeQL 的兼容性。 使用 Visual Studio 17.8 或更高版本时,验证 CodeQL CLI 版本 2.15.4 是否与 WHCP 21H2 和 WHCP 22H2 一起使用。 使用 Visual Studio 17.7 或更早版本时,请使用版本 2.4.6 或版本 2.6.3。 对于 WHCP 计划,请使用要认证的 CodeQL CLI 版本和 Windows 版本 - 版本 2.4.6、版本 2.6.3 或版本 2.15.4。 若要与主分支一起使用,请使用 CodeQL CLI 版本 2.15.4。

为方案选择选项卡:

使用此矩阵确定要下载的版本。

Windows 版本 CodeQL CLI 版本 Microsoft/Windows-Drivers CodeQL 包版本 codeql/cpp-queries CodeQL pack 版本 要使用的分支
Windows Server 2022 2.4.62.15.4 1.0.13 (如果使用 codeql 2.15.4) 0.9.0 (如果使用 codeql 2.15.4) WHCP_21H2
Windows 11 2.4.62.15.4 1.0.13 (如果使用 codeql 2.15.4) 0.9.0 (如果使用 codeql 2.15.4) WHCP_21H2
Windows 11 版本 22H2 2.6.32.15.4 1.0.13 (如果使用 codeql 2.15.4) 0.9.0 (如果使用 codeql 2.15.4) WHCP_22H2
Windows 11 版本 23H2 2.6.32.15.4 1.0.13 (如果使用 codeql 2.15.4) 0.9.0 (如果使用 codeql 2.15.4) WHCP_22H2
Windows 11,版本 24H2 2.15.4 1.1.0 0.9.0 WHCP_24H2

注释

CodeQL CLI 2.4.6 和 2.6.3 未指定 CodeQL 包的版本,因为 CodeQL 版本晚于 v2.7.0 支持 CodeQL 包。

下载并安装 CodeQL

  1. 创建包含 CodeQL 的目录。 此示例使用 C:\codeql-home\

    C:\> mkdir C:\codeql-home
    
  2. 请参阅前面的表,根据Microsoft驱动程序查询的所需分支选择要使用的 CodeQL CLI 版本。 如果要作为 WHCP 程序的一部分执行分析,请参阅“ Windows 硬件兼容性计划使用”表,否则使用 Main Branch 和 2.15.4。 使用不同的版本可能会导致数据库与库不兼容。

  3. 导航到与上一个表关联的 CodeQL CLI 二进制文件版本,并根据项目的体系结构下载 zip 文件。 例如,对于 64 位 Windows codeql-win64.zip

  4. 将 Codeql CLI 目录提取到刚刚创建的目录,例如:*C:\codeql-home\codeql*。

  5. 通过检查版本验证 CodeQL 是否已正确安装:

     C:\codeql-home\codeql>codeql --version
     CodeQL command-line toolchain release 2.15.4.
     Copyright (C) 2019-2023 GitHub, Inc.
     Unpacked in: C:\codeql-home\codeql
         Analysis results depend critically on separately distributed query and
         extractor modules. To list modules that are visible to the toolchain,
         use 'codeql resolve qlpacks' and 'codeql resolve languages'.
    

使用 CodeQL 帮助

C:\codeql-home\codeql\>codeql --help
Usage: codeql <command> <argument>...
Create and query CodeQL databases, or work with the QL language.

GitHub makes this program freely available for the analysis of open-source software and certain other uses, but it is
not itself free software. Type codeql --license to see the license terms.

      --license              Show the license terms for the CodeQL toolchain.
Common options:
  -h, --help                 Show this help text.
  -v, --verbose              Incrementally increase the number of progress messages printed.
  -q, --quiet                Incrementally decrease the number of progress messages printed.
Some advanced options have been hidden; try --help -v for a fuller view.
Commands:
  query     Compile and execute QL code.
  bqrs      Get information from .bqrs files.
  database  Create, analyze and process CodeQL databases.
  dataset   [Plumbing] Work with raw QL datasets.
  test      Execute QL unit tests.
  resolve   [Deep plumbing] Helper commands to resolve disk locations etc.
  execute   [Deep plumbing] Low-level commands that need special JVM options.
  version   Show the version of the CodeQL toolchain.
  generate  Generate formatted QL documentation.

有关特定命令的帮助,请运行 codeql <命令> --help。 例如:

codeql create --help

若要获取子命令的帮助,请按层次结构列出它们,例如

codeql create language --help

安装 CodeQL 包

选择构建环境的选项卡:

如果将 Visual Studio 2022 17.8 或更高版本与 WHCP_21H2 或 WHCP_22H2 和 CodeQL CLI 版本 2.15.4 配合使用,请使用此过程。

注释

如果使用早期版本的 CodeQL 运行 CodeQL 测试,请确保删除旧 CodeQL 子模块(如果仍具有克隆的存储库的旧版本)。 默认情况下,CodeQL 可能会尝试使用子模块中的查询,这可能会导致错误,因为版本不匹配。

下载 CodeQL 查询包

CodeQL 在版本 2.7.0 中引入了 CodeQL 包(CodeQL 包查询包),无需克隆 Windows-Driver-Developer-Supplemental-Tools 存储库以使用查询进行认证。

注释

可以跳过步骤 1,因为--download 选项会在运行分析过程时下载必要的任何查询。

  1. Windows 硬件兼容性计划使用 表下载正确的 microsoft/windows 驱动程序包版本。 请在以下命令中指定 @<version>
C:\codeql-home\> codeql pack download microsoft/windows-drivers@<version>

例如,如果使用WHCP_24H2,请运行以下命令下载版本 1.1.0 的 Windows-Drivers 查询包:

C:\codeql-home\> codeql pack download microsoft/windows-drivers@1.1.0

使用此命令下载 CodeQL cpp 查询包的版本 0.9.0。

C:\codeql-home\> codeql pack download codeql/cpp-queries@0.9.0

CodeQL 将查询包安装到默认目录:

C:\Users\<current user>\.codeql\packages\microsoft\windows-drivers\<downloaded version>\

重要

请勿更改安装目录或移动已安装的查询包。

下载 Windows 驱动程序查询套件

Microsoft提供了两个查询套件来简化端到端驱动程序开发人员工作流。 windows_driver_recommended.qls 套件是 Microsoft驱动程序开发人员认为有价值的所有查询的超集,windows_driver_mustfix.qls 套件包含被视为“必须修复”的 WHCP 认证查询。 windows_driver_mustfix.qls 必须运行并通过,以便通过静态工具徽标测试。

将两个查询套件文件从 https://github.com/microsoft/Windows-Driver-Developer-Supplemental-Tools/tree/main/suites 复制到您的本地电脑。

  • windows_driver_recommended.qls
  • windows_driver_mustfix.qls

有关查询套件内容的详细信息,请参阅 CodeQL 查询和套件

生成 CodeQL 数据库

这些示例假定使用 Windows 开发环境,并且安装位置为 C:\codeql-home,但你可以使用适合你的设置。 有关支持哪些编译器的列表,请参阅 CodeQL 支持的语言和框架

  1. 创建 CodeQL 的目录以放置它创建的数据库。 例如:C:\codeql-home\databases

    mkdir C:\codeql-home\databases
    
  2. 使用 CodeQL 命令创建包含以下参数的数据库:

    • 第一个参数是指向数据库目录的链接。 例如,C:\codeql-home\databases\MyDriverDatabase。 (如果目录已存在,此命令将失败。
    • --language-l 指定源代码所使用的语言或语言。 这可以是逗号分隔的列表,例如 [cpp, javascript]。
    • --source-s 指定源代码的路径。
    • --command-c 指定生成命令或生成文件的路径。
    codeql database create <database directory> --language=<language> --source=<path to source code> --command=<build command or path to build file>
    

例子

单个驱动程序示例。

C:\codeql-home\codeql> codeql database create D:\DriverDatabase --language=cpp --source-root=D:\Drivers\SingleDriver --command="msbuild /t:rebuild D:\Drivers\SingleDriver\SingleDriver.sln"

多个驱动程序示例。

C:\codeql-home\codeql> codeql database create D:\SampleDriversDatabase --language=cpp --source-root=D:\AllMyDrivers\SampleDrivers --command=D:\AllMyDrivers\SampleDrivers\BuildAllSampleDrivers.cmd

有关使用 database create 命令的详细信息或帮助,请参阅 创建 CodeQL 数据库 或使用 CodeQL 帮助

执行分析

此时,数据库创建已完成,下一步是对驱动程序源代码执行实际分析。

  1. 使用 CodeQL 命令使用以下参数分析数据库:

    • 第一个参数是指向数据库目录的链接。 例如 ,C:\codeql-home\databases\MyDriverDatabase。 (注意:如果目录不存在,此命令将失败。
    • --download 标志指示 CodeQL 在运行查询之前下载依赖项。
    • --format 是输出文件的文件类型。 选项包括:SARIF 和 CSV。 (对于 WHCP 用户 ,请使用 SARIF 格式。
    • --output 是所需输出文件的路径,请确保在文件名中包含格式。 (如果目录尚不存在,此命令将失败。
    • 查询说明符参数是一个空格分隔的参数列表,可以包括:
      • 查询文件的路径
      • 包含查询文件的目录的路径
      • 查询套件文件的路径
      • CodeQL 查询包的名称
    codeql database analyze --download <path to database> <path to query suite .qls file> --format=sarifv2.1.0 --output=<outputname>.sarif
    

    示例:

    codeql database analyze --download D:\DriverDatabase suites/windows\_driver_recommended.qls --format=sarifv2.1.0 --output=D:\DriverAnalysis1.sarif 
    

    有关使用 database analyze 命令的详细信息或帮助,请参阅使用 CodeQL CLI 分析数据库使用 CodeQL 包分析 CodeQL 数据库或使用 CodeQL 帮助

查看和解释结果

我们将重点介绍本部分的 SARIF 格式,因为它是以下步骤所需的内容,不过,如果 CSV 格式更适合你的需求,欢迎使用 CSV 格式。

静态分析结果交换格式(SARIF)是用于共享静态分析结果的 JSON 类型格式。 详细了解 OASIS 静态分析结果交换格式(SARIF)的标准、CodeQL 如何使用 SARIF 输出架构 json

有多种方法可用于解释分析结果,包括手动对对象进行排序。 以下是我们使用的一些:

  • Microsoft Sarif Viewer(Web)具有允许将 SARIF 文件拖放到查看器的功能,然后显示按规则分类的结果。 这是一种非常快速、简单的方法来查看冲突计数或哪些查询存在冲突,但除了行号之外,不太容易找到源代码信息。 请注意,如果没有冲突,页面将不会更新。

  • 适用于 Visual Studio 的 Microsoft SARIF 查看器非常适合在 Visual Studio 中显示结果,以便从结果无缝转换到源代码。

  • Visual Studio Code 的 SARIF 扩展将打开预览窗格,并显示 CodeQL 报告的任何错误、警告或问题。 若要以可读格式显示 Sarif 文件,请在 Visual Studio Code 中打开该文件,然后选择 Shift-Alt-F

SARIF 文件最重要的部分是 Results 对象中的 Run 属性。 每个查询都有一个 Results 属性,其中包含有关任何检测到的冲突及其发生位置的详细信息。 如果未找到冲突,则属性值将为空。

使用 错误警告问题等状态对查询进行分类。 但是,此分类与 Windows 硬件兼容性计划和静态工具徽标测试对结果进行评分的方式不同。 在 Must-Fix 套件中的任何查询中存在缺陷的任何驱动程序都不会通过静态工具徽标测试,并且无论原始查询文件中的查询分类(例如警告),都将无法进行认证

将 SARIF 转换为驱动程序验证日志格式(DVL)

静态工具徽标测试分析 驱动程序验证日志(DVL),这是在驱动程序源代码上运行的 CodeQL 静态分析的编译结果。 可通过三种方法将 SARIF 文件转换为 DVL 格式:Visual Studio、MSBuild,或使用 dvl.exe 工具从命令行转换。 有关完整步骤,请参阅 “创建驱动程序验证日志”。

有关静态工具徽标 HLK 测试的进一步说明和有关如何放置 DVL 文件的指南,请参阅 “运行静态工具徽标测试”。

故障排除

如果要使用 WHCP 进行认证,请先确保使用的是与目标 Windows 版本关联的 HLK 版本、Windows 驱动程序开发人员补充工具存储库中的关联分支以及后续 CodeQL CLI 版本。 有关 HLK/Windows 发布兼容性矩阵的信息,请参阅 Windows 硬件实验室工具包。有关 Windows Release/Windows 驱动程序开发者补充工具存储库分支/CodeQL CLI 版本的信息,请参阅 选择 CodeQL 版本 部分中的 WHCP 表。

错误和解决方法

对于 数据库版本 不匹配问题,以下工具可能会有所帮助。

使用 codeql version 命令显示 codeql exe 的版本。

C:\codeql-home\codeql\>codeql version
CodeQL command-line toolchain release 2.4.0.
Copyright (C) 2019-2020 GitHub, Inc.
Unpacked in: C:\codeql-home\codeql\
   Analysis results depend critically on separately distributed query and
   extractor modules. To list modules that are visible to the toolchain,
   use 'codeql resolve qlpacks' and 'codeql resolve languages'.

数据库升级命令将更新数据库。 请注意,这是一种单向升级,不可逆。 有关详细信息,请参阅 数据库升级

可选过程

(可选)可以在 Visual Studio 中抑制 CodeQL 结果或将生成和分析过程作为生成后的事件来运行。

禁止显示 CodeQL 结果

驱动程序的 CodeQL 支持抑制结果。 目前提供了抑制,以帮助开发人员分流问题并减少干扰,不应作为绕过 必修复 检查的方法。 它们不会影响生成驱动程序验证日志或目前通过静态工具徽标测试。 若要使用抑制,必须在运行其他查询或套件的同时运行 DriverAlertSuppression.ql 查询。 默认情况下,从 githubs main/development Branch 运行套件时,将启用此查询。

对于从代码分析迁移的规则,现有的代码分析屏蔽将被遵循。 有关详细信息,请参阅 C++警告杂注

  • Known limitation: 此时不能在同一行中合并 #pragma(禁用)和 #pragma(禁止)。

若要忽略 CodeQL 中的新检查,请通过以下两种方法之一来禁止它们:

  • 在违规的上方行编写#pragma(suppress:the-rule-id-here)批注(不含引号),就像对代码分析所做的那样。 将“the-rule-id-here”替换为查询元数据中@id的值,可以在文件顶部查看。

  • 在上面由文本“lgtm[the-rule-id-here]”(减引号)组成的行上编写注释。 需要运行标准 C/C++警报抑制查询 ,而不是驱动程序警报抑制查询。

出现并识别抑制后,生成的 SARIF 文件将包含已取消结果的数据,并且大多数结果查看器默认不会显示结果。

Visual Studio 生成后事件

如果要使用 Visual Studio 生成驱动程序,则可以将 CodeQL 查询配置为作为生成后事件运行。

在此示例中,在目标位置创建一个小批处理文件,并作为生成后事件调用。 有关 Visual Studio C++生成事件的详细信息,请参阅 指定生成事件

  1. 创建一个小批处理文件,该文件重新创建 CodeQL 数据库,然后对其运行所需的查询。 在此示例中,批处理文件将命名 RunCodeQLRebuildQuery.bat。 修改示例批处理文件中显示的路径以匹配目录位置。

    ECHO ">>> Running CodeQL Security Rule V 1.0 <<<"
    ECHO ">>> Removing previously created rules database <<<"
    rmdir /s/q C:\codeql-home\databases\kmdf
    CALL C:\codeql-home\codeql\codeql\codeql.cmd database create -l=cpp -s="C:\codeql-home\drivers\kmdf" -c "msbuild /p:Configuration=Release /p:Platform=x64 C:\codeql-home\drivers\kmdf\kmdfecho.sln /t:rebuild /p:PostBuildEventUseInBuild=false " "C:\codeql-home\databases\kmdf" -j 0
    CALL C:\codeql-home\codeql\codeql\codeql database analyze "C:\codeql-home\databases\kmdf" "<path to query suite .qls file>" --format=sarifv2.1.0 --output=C:\codeql-home\databases\kmdf.sarif -j 0 --rerun
    ECHO ">>> Loading SARIF Results in Visual Studio <<<"
    CALL devenv /Edit C:\codeql-home\databases\kmdf.sarif
    SET ERRORLEVEL = 0
    
  2. 批处理文件中使用 devenv.exe/编辑 选项在 Visual Studio 的现有实例中打开 SARIF 结果文件。 若要查看 SARIF 结果,请安装 适用于 Visual Studio 的 Microsoft SARIF 查看器 ,并参阅此处的说明了解详细信息。

  3. 在驱动程序项目中,导航到项目属性。 在 “配置” 下拉列表中,选择要与 CodeQL 一起检查的生成配置,我们建议选择 发布。 创建 CodeQL 数据库并运行查询需要几分钟时间,因此不建议在项目的调试配置上运行 CodeQL。

  4. 在驱动程序项目属性中选择 “生成事件 ”和 “生成后事件 ”。

  5. 提供批处理文件的路径以及生成后事件的说明。

Visual Studio 生成后事件配置,其中显示了配置为命令行选项的批处理文件。

  1. 批处理文件结果显示在生成输出的末尾。

    1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\MistypedFunctionArguments.ql.
    1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\TooManyArguments.ql.
    1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\TooFewArguments.ql.
    1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\ImplicitFunctionDeclaration.ql.
    1>[1/4 eval 4.4s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\TooManyArguments.bqrs.
    1>[2/4 eval 4.4s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\TooFewArguments.bqrs.
    1>[3/4 eval 4.5s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\ImplicitFunctionDeclaration.bqrs.
    1>[4/4 eval 5.2s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\MistypedFunctionArguments.bqrs.
    1>Shutting down query evaluator.
    1>Interpreting results.
    1>">>> Loading SARIF Results in Visual Studio <<<"