Предупреждение C30030
Вызов функции выделения памяти и передача параметра, указывающего исполняемую память
Некоторые API имеют параметры, которые задают, является ли память исполняемой. Эта ошибка указывает, что используются параметры, которые приводят к выделению исполняемого файла NonPagedPool.
Комментарии
Для запроса неисполняемой памяти следует использовать один из доступных вариантов. Список всех запрещенных функций и флагов, на которые распространяется эта ошибка, и рекомендуемые замены можно найти в нижней части этой страницы.
Имя анализа Cose: BANNED_MEM_ALLOCATION_UNSAFE
Для дефектов, связанных с типами параметров MM_PAGE_PRIORITY и POOL_TYPE
Используйте один из следующих методов.
- Укажите определение препроцессора POOL_NX_OPTIN_AUTO в параметрах источников или проекта.
- Укажите определение предварительного процессора POOL_NX_OPTIN в параметрах источника или проекта и вызовите ExInitializeDriverRuntime(DrvRtPoolNxOptIn) из функции инициализации драйвера (DriverEntry или DllInitialize).
Примечание Выбор того, следует ли использовать 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):
Следующий код в файле sources выдает предупреждение:
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 to 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: MmAllocateContiguousMemorySpecifyCache и MmAllocateContiguousMemorySpecifyCacheNode. Если используется тип кэша MmCached (см . MEMORY_CACHING_TYPE), то будет выделена исполняемая память. Чтобы устранить эту проблему, выберите другой тип кэширования или, если требуется кэшированная память, используйте API MmAllocateContiguousNodeMemory.
Изменить:
- MmCached в MmNonCached или MmWriteCombined , если кэшированная память не требуется
- 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() |
|
|
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 |