W^X («write xor execute», произносится как W xor X ) — это функция безопасности в операционных системах и виртуальных машинах . Это политика защиты памяти , при которой каждая страница в адресном пространстве процесса или ядра может быть либо записываемой, либо исполняемой , но не одновременно. Без такой защиты программа может записывать (как данные «W») инструкции ЦП в область памяти, предназначенную для данных, а затем выполнять (как исполняемые «X»; или читать-выполнять «RX») эти инструкции. Это может быть опасно, если писатель памяти злонамерен. W^X — это терминология Unix, обозначающая строгое использование общей концепции защиты исполняемого пространства , контролируемой с помощью системного вызова.mprotect
W^X относительно прост на процессорных архитектурах , которые поддерживают детальные разрешения страниц, таких как SPARC и SPARC64 от Sun , x86-64 от AMD , PA-RISC от Hewlett-Packard , Alpha от HP (первоначально от Digital Equipment Corporation ) и ARM .
Термин W^X также применялся к разрешениям на запись/выполнение файловой системы для смягчения уязвимостей записи файлов (например, в памяти) и настойчивости злоумышленников. [1] Обеспечение ограничений на разрешения файлов также может закрыть пробелы в обеспечении W^X, вызванные файлами, отображенными в памяти. [2] [3] Прямой запрет на использование произвольного собственного кода также может смягчить уязвимости ядра и ЦП, не выявленные через существующий код на компьютере. [4] Менее интрузивный подход заключается в блокировке файла на время любого отображения в исполняемую память, что достаточно для предотвращения обходов после проверки.
В некоторых ранних процессорах Intel 64 отсутствовал бит NX , необходимый для W^X, но он появился в более поздних чипах. На более ограниченных процессорах, таких как Intel i386 , W^X требует использования предела сегмента кода CS как « линии на песке », точки в адресном пространстве, выше которой выполнение не разрешено и находятся данные, а ниже которой оно разрешено и размещаются исполняемые страницы. Эта схема использовалась в Exec Shield . [5]
Изменения в компоновщике обычно требуются для отделения данных от кода (например, трамплины , необходимые для компоновщика и функций времени выполнения библиотеки ). Переключатель, позволяющий смешивать, обычно вызывается в Unix-подобных системах [6]execstack
W^X также может представлять небольшую проблему для компиляции just-in-time , которая включает в себя генерацию интерпретатором машинного кода на лету и его последующий запуск. Простое решение, используемое большинством, включая Firefox , заключается в том, чтобы просто сделать страницу исполняемой после того, как интерпретатор закончит писать машинный код, используя VirtualProtect
Windows или mprotect
Unix-подобные операционные системы. Другое решение заключается в отображении одной и той же области памяти на две страницы, одну с RW, а другую с RX. [7] Нет простого консенсуса относительно того, какое решение безопаснее: сторонники последнего подхода считают, что разрешение выполнять страницу, которая когда-либо была доступна для записи, противоречит смыслу W^X (существует политика SELinux для управления такими операциями, называемая allow_execmod
), и что рандомизация макета адресного пространства сделает безопасным размещение обеих страниц в одном процессе. Сторонники первого подхода считают, что последний подход безопасен только тогда, когда две страницы предоставляются двум отдельным процессам, а межпроцессное взаимодействие будет более затратным, чем вызов mprotect
.
W^X впервые был реализован в OpenBSD 3.3, выпущенном в мае 2003 года. В 2004 году Microsoft представила похожую функцию под названием DEP ( Data Execution Prevention ) в Windows XP. Похожие функции доступны для других операционных систем, включая исправления PaX и Exec Shield для Linux , а также реализацию PaX в NetBSD. В Red Hat Enterprise Linux (и автоматически в CentOS ) версии 5 или Linux Kernel 2.6.18-8 SELinux получил политики allow_execmem
, allow_execheap
, и , allow_execmod
которые предоставляют W^X при отключении.
Хотя W^X (или DEP) на протяжении большей части своего существования защищал только пользовательские программы, в 2012 году Microsoft расширила его до ядра Windows на архитектурах x86 и ARM. [8] В конце 2014 и начале 2015 года W^X был добавлен в ядро OpenBSD на архитектуре AMD64. [9] В начале 2016 года W^X был полностью реализован в ядре AMD64 NetBSD и частично в ядре i386.
Компьютеры macOS , работающие на процессорах Apple Silicon, применяют политику W^X для всех программ. Компьютеры Mac на базе Intel применяют политику только для программ, использующих режим Hardened Runtime ОС. [10] [11]
Начиная с Firefox 46 в 2016 году и заканчивая Firefox 116 в 2023 году, виртуальная машина Firefox для JavaScript реализовала политику W^X. [7] Позднее это было отменено на некоторых платформах по соображениям производительности, хотя осталось на других, которые применяют W^X для всех программ. [12]
Начиная с .NET 6.0 в 2021 году, .NET теперь использует W^X. [13]