Модель безопасности памяти WebAssembly
Я слышал о безопасности WebAssembly, предоставляя линейную память. Интересно, что содержит эта линейная память? находится ли стек и куча wasm в этом пространстве памяти? Если да, я думаю, что стек wasm и стек связующего кода (например, js python и т. Д.) Разделены, верно?
Я могу понять безопасность памяти wasm, используя таблицу импорта. Другими словами, функция wasm не может вызывать какую-либо функцию вне линейной памяти, потому что она может использовать только индекс для вызова импортированных функций. Какую еще безопасность обеспечивает wasm? Возможно, это из-за проблемы со стеком выше.
Похоже, в wasm тоже есть целостность потока управления. То есть адрес возврата каждой функции фиксирован и не может быть изменен внутри этой функции. Это правильное понимание?
Большое спасибо!
1 ответ
(1) Линейная память представляет собой один большой массив байтов, и WebAssembly предлагает инструкции загрузки и сохранения для управления байтами в этом массиве. В WebAssembly нет инструкций, которые работают с нативными указателями, код Wasm может загружать/сохранять только в линейной памяти (в будущем, когда будет добавлена поддержка нескольких памяти, любая из линейных памяти).
(2) WebAssembly — это, по сути, песочница. Код WebAssembly не является собственным кодом ЦП ни на одной платформе, у нас есть спецификация поведения инструкций WebAssembly для их интерпретации или компиляции. Вы можете делать только то, что указано в спецификации.
Нет указателя инструкций, который можно перемещать (в WebAssembly вообще нет регистров). У вас никогда не может быть указателя на стек (другими словами, стек содержит значения WebAssembly, а не байты, и не имеет никакого адреса, который вы могли бы взять). Вы не можете инициировать системные вызовы или прерывания (в WebAssembly таких инструкций нет). Вы не можете видоизменять или даже читать свой собственный код, вы не можете JIT и создавать новый код. Доступ кода Wasm к внешнему миру ограничен именно тем интерфейсом, который ему предоставляет хост-эмбеддер.
WebAssembly не защищает от проблем внутри песочницы. Если у вас есть код C++, который выполняет неопределенное поведение, он может делать все, что ему заблагорассудится, внутри этой песочницы, любым возможным способом подключая интерфейс к хосту, но полный опыт C++ UB не передается встраивающему устройству. Таким образом, его можно рассматривать как мини-процесс в вашем процессе или как контейнер для библиотеки.
(3) В WebAssembly нет инструкций, которые позволили бы вам читать/записывать стек возврата функции, поэтому его невозможно изменить.