Компонентная модель и безопасность
Разбираем компонентную модель и устройство песочницы Wasm.
Компонентная модель — это надстройка над Wasm, позволяющая модулям из разных языков соединяться через богатые типы, а не только числа.
Проблема «всё через числа»
Базовый Wasm знает только четыре числа. Чтобы один модуль использовал другой и обменивался строками, списками, записями, приходится вручную согласовывать протокол памяти — и для каждой пары языков он свой. Это мешает собирать приложение из готовых Wasm-кусков на разных языках. Компонентная модель решает это: вводит общий язык описания интерфейсов (WIT) с богатыми типами (строки, списки, варианты), и компоненты соединяются по этим описаниям автоматически.
Интерфейс на WIT
Интерфейс компонента описывают на языке WIT — он напоминает объявление типов. Помечаем language-text:
// интерфейс компонента на WIT
interface greeter {
greet: func(name: string) -> string
add: func(a: s32, b: s32) -> s32
}
Тут уже есть настоящий string и понятные типы. Инструменты генерируют по этому описанию «клей» так, что Rust-компонент и Go-компонент сцепляются, не зная деталей памяти друг друга. Это как интерфейсы между микросервисами, но внутри одного быстрого рантайма.
Почему Wasm безопасен
Безопасность Wasm стоит на нескольких столпах, заложенных в дизайн:
- Песочница памяти — модуль видит только свою линейную память; выйти за неё нельзя (trap). Чужую память не прочитать.
- Никаких неявных возможностей — модуль не может ничего, кроме того, что ему импортировали. Нет импорта файлов — нет доступа к файлам.
- Защита потока управления — нельзя прыгнуть в произвольный адрес; вызовы только через проверенные функции и таблицы с проверкой сигнатур.
- Валидация перед запуском — модуль проверяется на корректность типов до исполнения; некорректный не запустится.
Песочница наглядно
+-------------------------------------+
| Хост (браузер/рантайм) |
| выдаёт ровно эти импорты --> |
| +-----------------------------+ |
| | Wasm-модуль (песочница) | |
| | - своя память (не выйти) | |
| | - только данные импорты | |
| | - проверенный поток вызовов| |
| +-----------------------------+ |
+-------------------------------------+
Как работает под капотом
Изоляция памяти обеспечивается тем, что вся «память» модуля — это один ArrayBuffer, и каждое обращение проверяется на границу (или, в продвинутых рантаймах, защищено аппаратными страницами памяти). Модуль физически не имеет указателя на что-либо вне своего буфера. Контроль возможностей — следствие того, что единственные «двери» наружу это импорты, а их задаёт хост. Поэтому даже вредоносный модуль не сможет прочитать чужие данные или вызвать то, что ему не дали.
Частые ошибки
- Считать компонентную модель частью базового Wasm — это надстройка, она ещё дозревает.
- Думать, что песочница — это про антивирус — нет, это про невозможность выйти за память и импорты.
- Полагать, что Wasm абсолютно безопасен — изоляция сильна, но логические уязвимости внутри импортированных функций остаются на совести хоста.
Итоги
- Компонентная модель соединяет Wasm-модули через богатые типы (WIT), а не числа.
- Безопасность: песочница памяти, только явные импорты, защита потока, валидация.
- Модуль не может выйти за свою память и вызвать то, что не импортировано.
- Это делает Wasm безопасным форматом для чужого кода и плагинов.