Выпуск Rust 1.81. Препятствия при продвижении Rust в ядро Linux
Опубликован релиз языка программирования общего назначения Rust 1.81, основанного проектом Mozilla, но ныне развиваемого под покровительством независимой некоммерческой организации Rust Foundation. Язык сфокусирован на безопасной работе с памятью и предоставляет средства для достижения высокого параллелизма выполнения заданий, при этом обходясь без использования сборщика мусора и runtime (runtime сводится к базовой инициализации и сопровождению стандартной библиотеки).
Методы работы с памятью в Rust избавляют разработчика от ошибок при манипулировании указателями и защищают от проблем, возникающих из-за низкоуровневой работы с памятью, таких как обращение к области памяти после её освобождения, разыменование нулевых указателей, выход за границы буфера и т.п. Для распространения библиотек, обеспечения сборки и управления зависимостями проектом развивается пакетный менеджер Cargo. Для размещения библиотек поддерживается репозиторий crates.io.
Безопасная работа с памятью обеспечивается в Rust во время компиляции через проверку ссылок, отслеживание владения объектами, учёт времени жизни объектов (области видимости) и оценку корректности доступа к памяти во время выполнения кода. Rust также предоставляет средства для защиты от целочисленных переполнений, требует обязательной инициализации значений переменных перед использованием, лучше обрабатывает ошибки в стандартной библиотеке, применяет концепцию неизменяемости (immutable) ссылок и переменных по умолчанию, предлагает сильную статическую типизацию для минимизации логических ошибок.
Основные новшества:
Стабилизирован типаж core: error: Error, определяющий выводимые описания ошибок. Изменение позволяет использовать единый типаж Error в различных библиотеках, независимо от окружения, в том числе и в библиотеках не привязанных к стандартной библиотеке, использующих атрибут »#![no_std]».
Стабильные и нестабильные функции сортировки в стандартной библиотеке переведены на использование новых алгоритмов, демонстрирующих более высокую скорость работы и меньшее время компиляции. В реализации новых алгоритмов сортировки обеспечено определение некорректно определённых типажей Ord и вывод в таких случаях ошибки (panic) вместо случайным образом сгруппированных данных.
В linter-е реализован новый уровень проверки «expect» (»#[expect (lint)]»), позволяющий удостовериться в выполнении проверки и вывести предупреждение, если проверка не выполнена (из-за ошибки в реализации или отключения проверки). Например, при переводе кодовой базы на использование проверки undocumented_unsafe_blocks через Clippy можно указать »#[expect (clippy: undocumented_unsafe_blocks)]» для того, чтобы удостовериться, что в процессе перехода все unsafe-блоки будут документированы. В Clippy также реализованы проверки clippy: allow_attributes и clippy: allow_attributes_without_reason, упрощающие замену атрибутов »#[allow]» на »#[expect (lint)]».
- Предоставлена возможность документирования причины замены уровней проверки (lint), предоставляющая новым разработчикам информацию о причинах добавления той или иной проверки, выводимую в виде сообщения компилятора. Например:
#![deny(clippy::float_arithmetic, reason = "no hardware float support")]
В разряд стабильных переведена новая порция API, в том числе стабилизированы методы и реализации типажей:
core::error
hint::assert_unchecked
fs::exists
AtomicBool::fetch_not
Duration::abs_diff
IoSlice::advance
IoSlice::advance_slices
IoSliceMut::advance
IoSliceMut::advance_slices
PanicHookInfo
PanicInfo::message
PanicMessage
Признак «const», определяющий возможность использования в любом контексте вместо констант, применён в функциях:
char::from_u32_unchecked
(функция)char::from_u32_unchecked
(метод)CStr::count_bytes
CStr::from_ptr
Тип std: panic: PanicInfo переименован в std: panic: PanicHookInfo (работа старого имени сохранена, но начиная со следующей версии его использование будет приводить к выводу предупреждения). При этом core: panic: PanicInfo останется как есть, но будет развиваться как отдельный тип. Разделение типов позволит реализовать в них разные методы, специфичные для выполнения в контексте snd и no_std.
Завершён переход на ABI C-unwind ('extern «C-unwind»'), который отличается от ABI без суффикса »-unwind» ('extern «C»') сохранением безопасного поведения (safe), если процесс «размотки» (unwinding), инициируемый при аварийном завершении программы или генерации исключения в стиле C++, пересекает границу ABI (например, когда исключение, возникшее в коде на одном языке программирования, при размотке затрагивает стек, связанный с кодом на другом языке программирования). Начиная с выпуска Rust 1.81 в ABI 'extern «C»' задействовано аварийное завершение при неперехваченной размотке.
Реализован третий уровень поддержки для платформ i686-unknown-redox, xtensa-esp32-none-elf, xtensa-esp32s2-none-elf, xtensa-esp32s3-none-elf, xtensa-esp32-espidf, xtensa-esp32s2-espidf, xtensa-esp32s3-espidf. Третий уровень подразумевает базовую поддержку, но без автоматизированного тестирования, публикации официальных сборок и проверки возможности сборки кода.
Реализован второй уровень поддержки целевых платформ loongarch64-unknown-linux-musl и arm64ec-pc-windows-msvc. Второй уровень поддержки подразумевает гарантию сборки.
Для Linux-систем на платформе LoongArch предоставлен полный инструментарий и профилировщик.
Устранена уязвимость (CVE-2024–43402) в std: process: Command, проявляющаяся только на платформе Windows и устраняющая обходной путь эксплуатации ранее исправленной уязвимости BatBadBut, связанной с обработкой спецсимволов при использовании вызовов Command: arg и Command: args, рассчитанных на прямую передачу процессу аргументов, без их обработки командным интерпретатором. На деле при запуске bat- и cmd-сценариев запускался процесс cmd.exe, имеющий собственную логику разделения аргументов. Обход защиты основан на том, что Windows удаляет лидирующие пробелы и точки в путях, т.е. файл с расширением ».bat. .» обрабатывается как ».bat».
Кроме того, можно отметить уход Уэдсона Алмейда Фильо (Wedson Almeida Filho) с поста сопровождающего проект Rust for Linux, занимающийся внедрением в ядро Linux средств для разработки на языке Rust. После ухода Уэдсона у проекта остались ещё два сопровождающих — Мигель Охеда (Miguel Ojeda), автор и основной разработчик проекта Rust-for-Linux, и Алекс Гейнор (Alex Gaynor), бывший директор организации Python Software Foundation, переключившийся на продвижение Rust. Ушедший сопровождающий, который подключился к проекту 4 года назад, является сотрудником компании Microsoft и автором экспериментального драйвера с реализацией ФС EXT2, написанного на языке Rust. Последнее время работа Алмейда была сосредоточена на создании средств для разработки файловых систем на языке Rust. В этом году Алмейда внёс в репозиторий Rust-for-Linux 17 коммитов (для сравнения Мигель Охеда добавил 53 коммита).
В качестве причины ухода упоминается нехватка сил и энтузиазма, которые когда-то были для реагирования на некоторые бредни нетехнического характера (nontechnical nonsense). По мнению Алмейда, разработчики вынуждены тратить много сил на споры по несущественным вопросам, сводящим на нет более важную глобальную цель. Алмейда продолжает верить, что будущее ядер за использованием языков, обеспечивающих безопасную работу с памятью, и если сообщество разработчиков Linux не поймёт это, то Linux будет вытеснен каким-то другим ядром, как в своё время произошло с Unix.
Сторонники проекта Rust-for-Linux столкнулись с необходимостью преодолевать сопротивление со стороны маститых старых разработчиков ядра, которые не видят необходимости в изучении нового языка. В своём письме об отставке Алмейда в качестве примера приводит ссылку на дискуссию, которая состоялась во время выступления Алмейда и Кента Оверстрита (Kent Overstreet) на конференции «Linux Storage, Filesystem, Memory-Management, and BPF Summit» и была посвящена использованию Rust для разработки файловых систем. Деятельность по внедрению Rust раскритиковал Тед Цо (Ted Ts’o), автор файловых систем ext2/ext3/ext4, который сравнил инициативу Rust-for-Linux c попыткой заставить всех принять религию Rust.
В ответ на намерение Алмейда создать обвязку над написанными на языке Си интерфейсами файловых систем для их использования в коде на языке Rust, Тед Цо указал на то, что подобная обвязка неминуемо приведёт к проблемам, так как любое изменение Си-интерфейсов и проведение рефакторинга потребует изменения обвзяки для Rust и он не хочет брать на себя лишней ответственности за исправление возникающих проблем в коде на Rust и отслеживании состояния Rust-обвязки. Код на Си постоянно развивается и если его изменение нарушит работу обвязки для Rust, это приведёт к нарушению работы и всех завязанных на эту обвязку файловых систем.
Тед также считает, что в обозримом будущем обвязка для Rust останется второстепенной и возникновение проблем в биндингах будет головной болью только для разработчиков Rust-for-Linux, а не для сообщества разработчиков файловых систем в ядре. Указано, что не все разработчики собираются изучать Rust и поэтому после внесения влияющих на другой код изменений, они смогут обновить только зависящий код на Си, но не смогут исправить Rust-обвязки, так как не знают Rust. К дискуссии также присоединился Джеймс Боттомли (James Bottomley), сопровождающий подсистему SCSI, который сказал, что чем больше семантики кодируется в обвязках, тем они становятся более ломкими с точки зрения обеспечения синхронизации.
Тем временем, компания Google, которая в прошлом году переписала на языке Rust прошивку pvmfm, используемую в виртуальных машинах, запускаемых в платформе Android, поделилась опытом постепенного включения кода на языке Rust в существующие прошивки, изначально написанные на C или C++. Показано, как можно существенно повысить защищённость прошивок, создавая идентичные по функциональности компоненты-замены, написанные на языке Rust. Основное внимание при внедрении Rust предлагается удалять использованию Rust для нового кода и кода, выполняющего функции, критические с точки зрения безопасности (например, код по обработке внешних данных, получаемых из не заслуживающих доверия источников). Для интеграции кода на Rust и C предлагается использовать прослойки (shim), транслирующие вызовы между API на Rust и C (C API экспортируется для использования в коде на Rust и наоборот), которые позволяют поэтапно переписывать элементы API на Rust.
Источник: http://www.opennet.ru/opennews/art.shtml? num=61819
© OpenNet