警告 C30030

调用内存分配函数并传递指示可执行内存的参数

某些 API 具有用于配置内存是否可执行的参数。 此错误指示使用了导致分配可执行 NonPagedPool 的参数。

注解

应使用其中一个可用选项来请求非可执行内存。 可在此页面底部找到此错误涵盖的所有受禁函数和标志以及建议的替换项的列表。

Cose 分析名称:BANNED_MEM_ALLOCATION_UNSAFE

对于涉及参数类型的缺陷 ,MM_PAGE_PRIORITYPOOL_TYPE

使用以下选项之一:

  • 在源/项目设置 中指定预 处理器定义POOL_NX_OPTIN_AUTO。
  • 在 sources/project 设置指定预处理器定义POOL_NX_OPTIN,并从驱动程序初始化函数 (DriverEntryDllInitialize) 调用 ExInitializeDriverRuntime (DrvRtPoolNxOptIn) 。

注意 选择是使用 POOL_NX_OPTIN_AUTO 还是 POOL_NX_OPTIN 在很大程度上取决于所面向的平台以及要创建的二进制文件数量。 这两个选项都会导致编译器 (更改这两种类型,或者在运行时) 其 NX 等效项。 有关详细信息,请参阅主题链接。

注意 如果满足以下条件之一,可能会显示误报警告:

  • 驱动程序初始化函数调用另一个调用 ExInitializeDriverRuntime (DrvRtPoolNxOptIn)
  • 你正在创建 一个DRIVER_LIBRARY ,并且已指定 POOL_NX_OPTIN 但没有初始化函数。
  • 将分配类型更改为非可执行类型。

示例 (POOL_NX_OPTIN_AUTO) :

如果 API 调用中提供了可执行参数,源文件中的以下设置将允许发出警告:

C_DEFINES=$(C_DEFINES)

源文件中的以下设置可避免警告:

C_DEFINES=$(C_DEFINES) -DPOOL_NX_OPTIN_AUTO=1

示例 (POOL_NX_OPTIN) :

源文件中的以下代码生成警告:

C_DEFINES=$(C_DEFINES)

源文件中的以下代码可避免警告:

C_DEFINES=$(C_DEFINES) -DPOOL_NX_OPTIN=1

DriverEntry () 中,在进行任何内存分配之前:

NTSTATUS
DriverEntry (
    _In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS status;

    ExInitializeDriverRuntime( DrvRtPoolNxOptIn );
…

示例 (更改分配类型) :

对于 MM_PAGE_PRIORITY 类型,可以通过将 MdlMappingNoExecute 标志添加到优先级类型来解决此问题。 这仅在 Windows 8 及更高版本上受支持。

以下代码生成警告:

pPtr = MmGetSystemAddressForMdlSafe( pMdl, NormalPagePriority);

以下代码可避免警告:

pPtr = MmGetSystemAddressForMdlSafe( pMdl, NormalPagePriority | MdlMappingNoExecute);

示例 (POOL_TYPE)

对于 POOL_TYPE 类型,可以通过将请求类型更改为该类型的非可执行版本来解决此问题。 这仅在 Windows 8 及更高版本上受支持。

以下代码生成警告:

ExAllocatePoolWithTag(NonPagedPool, numberOfBytes, 'xppn');

以下代码可避免警告:

ExAllocatePoolWithTag(NonPagedPoolNx, numberOfBytes, 'xppn');

其他特殊情况:

ExInitializeNPagedLookasideList 例程中已发生更改,现在允许你指定非可执行的非分页池内存。 例如,以下代码生成此警告:

ExInitializeNPagedLookasideList(pLookaside,
                NULL,
                NULL,
                0,
                size,
                tag,
                depth);

以下代码可避免此警告:

ExInitializeNPagedLookasideList(pLookaside,
                NULL,
                NULL,
                POOL_NX_ALLOCATION,
                size,
                tag,
                depth);

对于涉及页面保护的缺陷:

某些 API 允许指定页面保护, ZwMapViewOfSection 就是其中之一。 在这些情况下,请使用保护类型的非可执行版本。

更改:

  • PAGE_EXECUTE以下任一替代项或PAGE_NOACCESS
  • PAGE_EXECUTE_READ PAGE_READONLY
  • PAGE_EXECUTE_READWRITE到PAGE_READWRITE
  • PAGE_EXECUTE_WRITECOPY PAGE_WRITECOPY

以下代码生成警告:

Status = ZwMapViewOfSection(   handle,
                NtCurrentProcess(),
                Address,
                0,
                0,
                &SectionOffset,
                Size,
                ViewUnmap,
                MEM_LARGE_PAGES,
                PAGE_EXECUTE_READWRITE
                ); 

以下代码可避免此警告:

Status = ZwMapViewOfSection(   handle,
                NtCurrentProcess(),
                Address,
                0,
                0,
                &SectionOffset,
                Size,
                ViewUnmap,
                MEM_LARGE_PAGES,
                PAGE_READWRITE
                ); 

对于涉及缓存类型的缺陷:

某些 API 根据缓存类型分配具有可执行权限的内存。 两个此类 API 是 MmAllocateContiguousMemorySpecifyCacheMmAllocateContiguousMemorySpecifyCacheNode。 如果使用 MmCached 缓存类型 (查看 MEMORY_CACHING_TYPE) ,则将分配可执行内存。 若要解决此问题,请选择其他缓存类型,或者如果需要缓存内存,请使用 API MmAllocateContiguousNodeMemory

更改:

  • MmCachedMmNonCachedMmWriteCombined (如果不需要缓存的内存)
  • API 到 MmAllocateContiguousNodeMemory (如果需要缓存内存)

以下代码生成警告:

MmAllocateContiguousMemorySpecifyCache(       numberOfBytes,
                                              lowestAddress,
                                              highestAddress,
                                              NULL,
                                              MmCached,
                                              ); 

如果不需要缓存内存,则以下代码可避免此警告:

MmAllocateContiguousMemorySpecifyCache(       numberOfBytes,
                                              lowestAddress,
                                              highestAddress,
                                              NULL,
                                              MmNonCached,
                                              ); 

以下代码生成警告:

MmAllocateContiguousMemorySpecifyCacheNode(   numberOfBytes,
                                              lowestAddress,
                                              highestAddress,
                                              NULL,
                                              MmCached,
                                              MM_ANY_NODE_OK
                                              ); 

如果需要缓存内存,以下代码可避免此警告:

MmAllocateContiguousNodeMemory(       numberOfBytes,
                                      lowestAddress,
                                      highestAddress,
                                      NULL,
                                      PAGE_READWRITE,
                                      MM_ANY_NODE_OK
                                      ); 

当不需要缓存内存时,以下代码使用备用 API:

MmAllocateContiguousNodeMemory(       numberOfBytes,
                                      lowestAddress,
                                      highestAddress,
                                      NULL,
                                      PAGE_READWRITE | PAGE_NOCACHE,
                                      MM_ANY_NODE_OK
                                      ); 

禁止的函数

禁止的 API 替换 () 理由/备注
ExInitializeNPagedLookasideList()
  • 请或/将标志参数设置为/以 POOL_NX_ALLOCATION
  • 或者使用上述POOL_NX_OPTIN_AUTO / POOL_NX_OPTIN方法
MmAllocateContiguousMemorySpecifyCache() MmAllocateContiguousNodeMemory() 有关详细信息,请参阅上文

禁止标志

禁止标志 替换 () 理由/备注
MM_PAGE_PRIORITY

有关详细信息,请参阅上文
POOL_NX_OPTIN_AUTO 这支持为不同版本的 Windows 创建多个二进制文件
POOL_NX_OPTIN (+ ExInitializeDriverRuntime(DrvRtPoolNxOptIn)) 这支持在不同版本的 Windows 上运行的单个二进制文件
PagePriority / MdlMappingNoExecute 这将适用于 Windows 8 及更高版本
PAGE_EXECUTE PAGE_NOACCESS 有关详细信息,请参阅上文
PAGE_EXECUTE_READ PAGE_READONLY
PAGE_EXECUTE_READWRITE PAGE_READWRITE
PAGE_EXECUTE_WRITECOPY PAGE_WRITECOPY

POOL_TYPE