В предыдущих постах мы освещали некоторые элементы реализации подсистемы Linux в Windows 10 (WSL). При этом речь шла о механизмах имплементации системных сервисов Linux на основе системных модулей Windows 10. Мы указывали, что такие драйверы как LXss.sys и LXCore.sys отвечают за реализацию семантики системных вызовов Linux с использованием ядра Windows. В случае совпадения семантики системного сервиса Linux и Windows, вышеупомянутые драйверы просто перенаправляют системный вызов Linux в соответствующий эквивалент Windows.
В этом посте речь пойдет о реализации виртуальной файловой системы VFS в WSL, которая используется как уровень абстракции в Linux при доступе как к дисковым файлам, так и другим объектам ОС, включая, устройства, порты, процессы, микропроцессор и т. д. Так как ядро Windows 10 имеет структуру подсистем и изначально рассчитано на реализацию различных типов окружения, включая POSIX, отвечающий за семантику VFS драйвер LXCore.sys обращается к этим подсистемам ядра, реализуя соответствующую семантику и директории типа /dev, /proc, /sys.
Рис. Общая схема реализации VFS в WSL. На верхнем уровне находятся приложения Linux, которые вызывают API ОС, за их реализацию отвечает драйвер режима ядра LXCore.sys. Для реализации семантики VFS драйвер обращается к различным подсистемам ядра Windows, включая, диспетчер объектов (ObMgr) для работы с системой имен Windows и пространством имен диспетчера объектов, диспетчер ввода/вывода (IoMgr) для реализации директории типа /dev, а также драйвер файловой системы NTFS для работы с дисковыми файлами.
WSL обепечивает приложения Linux необходимой семантикой VFS, при этом выполняется поддержка системы разрешений (permissions) файлов и директорий, символьных ссылок, специальных файлов типа FIFO, а также вышеупомянутых директорий /dev, /proc, /sys и др. Когда приложение вызывает одну из функций типа open, read, chmod, stat, соответствующий системный вызов берется за ее обработку и передает управление слою реализации VFS (LXCore.sys). Далее, при обработке путей файлов (например, при выполнении функций open и stat), VFS преобразует его во внутренний формат с использованием специального кэша (directory entry cache). В случае отсутствия искомого элемента пути в кэше, осуществляется вызов одного или нескольких специальных плагинов (см. ниже) для создания известной структуры inode этого элемента. Эта структура будет представлять открытый приложением файл в WSL.
Windows не имеет структуры типа inode для представления дескриптора открытого файла, вместо этого используется известная структура под названием file object, которая хранит некоторую информацию о файле (размер, атрибуты, маска доступа и т. д.). На нее внутренне и опирается LXCore.sys при реализации inode. Однако, и Linux и Windows используют файловые дескрипторы для представления открытого файла, детали работы с которыми скрывает LXCore.sys. Он определяет уровни так называемых плагинов под названиями VolFs и DrvFs, которые отвечают за работу с дисковыми файлами, TmpFs для работы с данными файловой системы в памяти (in-memory file system), а также псевдо-ФС ProcFs, SysFs, и CgroupFs.
VolFs
Плагин VolFs используется VFS для работы с дисковой файловой системой, он используется для хранения системных файлов Linux, а также содержимого директории /home. VolFs поддерживает работу с разрешениями файлов Linux, символьными ссылками, сокетами, файлами устройств, а также FIFO. Монтирование директорий /root и /home осуществляется в директории %LocalAppData%lxssroot и %LocalAppData%lxsshome. При удалении подсистемы WSL хранимые в этих директориях файлы не удаляются. Как видно из пути, директории монтирования каталогов Linux зависят от конкретного пользователя, т. е. каждый пользователь Windows имеет свою директории WSL. Поэтому, установка приложений Linux в WSL одним пользователем не коснется других.
WSL обеспечивает приложения двумя особенностями файловой системы Linux, поддержка которых отсутствует в Windows напрямую. Первой такой особенностью является чувствительность ФС к регистру имен файлов, в таком случае VolFs просто обращается к диспетчеру объектов, указывая определенный флаг для проведения операции. Так как NTFS внутренне различает регистр символов имен файлов, реализация этой особенности является достаточно простой задачей.
Второй особенностью является поддержка почти всех возможных символов в качестве применимых к названиям файлов. Windows имеет более строгие ограничения на названия файлов, при этом некоторые символы в именах файлов являются недопустимыми, а другие могут иметь особое значение, например, символ двоеточия ":", обозначающий альтернативный поток данных в файле. При реализации этой особенности, VolFS избегает использования недопустимых символов в названиях.
Структуры inode в Linux имеют ряд атрибутов, которые отсутствуют в Windows, включая, информацию о владельце и группе, а также режим (mode). Эти атрибуты хранятся в структуре расширенных атрибутов NTFS Ea, которые ассоциированы с файлами на диске. В этом атрибуте файла NTFS Ea хранится следующая информация:
- Режим файла (mode): включает в себя тип файла (обычный, символьная ссылка, FIFO, и т. д.), а также биты разрешений для файла.
- Информация о владельце: идентификатор группы и пользователя владельцев файла.
- Device ID: для файлов, которые представляют устройства, старший и младший номера устройств. Пока WSL не позволяет пользователям создавать файлы устройств на VolFS.
- Временные метки файла: временные метки последнего доступа к файлу и его модификации. В Linux используется иной формат временных меток, поэтому информация о них хранится в расширенных атрибутах.
DrvFs
Для облегчения взаимодействия с Windows, WLS использует плагин DrvFs. WSL автоматически монтирует все дисковые устройства с поддерживаемыми файловыми системами в директорию /mnt, например, /mnt/c, /mnt/d. На текущий момент поддерживаются тома с файловыми системами NTFS и ReFS. DrvFs работает таким же образом, что и VolFs. При открытии потоком файлового дескриптора, создаются структуры file object и inode. Тем не менее, в отличие от VolFs, DrvFs придерживается правил Windows при работе с файловой системой. Он использует разрешения для файлов от Windows, только легальные названия файлов NTFS, при этом такие специальные файлы как FIFO и сокеты не разрешены.
Известно, что Linux использует достаточно простую модель разрешений, когда владельцу файла, группе или кому-либо еще разрешается исполнять его, читать или записывать данные. В Windows используется более сложная модель на основе списков управления доступом Access Control List (ACL), которые определяют сложные правила доступа для каждого отдельного файла или директории (Linux также обладает возможностью поддержки ACL, но в настоящий момент эта функция не поддерживается WSL).
Когда происходит открытие файла через плагин DrvFs, он использует механизм разрешений Windows, основанный на маркере доступа того пользователя, в контексте которого был запущен процесс командного интерпретатора bash.exe. Таким образом, для получения доступа к файлам в системной директории C:Windows, недостаточно просто использовать команду sudo, которая может предоставить права root в WSL. Последняя не изменяет маркер доступа процесса, поэтому для выполнения указанной операции следует запустить приложение bash с повышенными привилегиями в Windows.
WSL может дать пользователю подсказку о тех разрешениях, которые он имеет при доступе к файлам, при этом DrvFs проверяет действующие разрешения пользователя и конвертирует их в биты read/write/execute, которые можно увидеть при выполнении команды «ls -l». Однако, не всегда существует возможность прямого преобразования; например, у Windows есть отдельные разрешения на возможность создания файлов или подкаталогов в директории. В случае присутствия у пользователя таких разрешений, DrvFs укажет ему на присутствие write-доступа к директории, в то время как некоторые операции с ней для него могут быть недоступны.
Поскольку указанный WLS доступ к файлу может различаться в зависимости от того, какими правами обладает запущенный в Windows процесс bash.exe, указываемые разрешения на доступ к файлам будут изменяться при переключениями между копиями bash.exe с различными правами (один запущен от простого пользователя, а второй от администратора). При расчете разрешений на доступ к файлу, DrvFs принимает во внимание атрибут read-only. Файл с атрибутом read-only будет отображаться в WSL как не имеющий разрешения на запись. Команда chmod может быть использована для установки атрибута read-only (путем удаления всех разрешений на запись, т. е. chmod a-w some_file) или удаления его (установкой любого разрешения на запись, т. е. chmod u+w some_file). Такое поведение WSL схоже с файловой системой CIFS в Linux, которая используется при доступе к общим ресурсам Windows SMB.
В отличие от VolFs, DrvFs не хранит никакой дополнительной информации о файлах. Вместо этого, все атрибуты inode формируются на основе информации, которая используется в Windows, путем запроса действующих атрибутов файлов, действующих разрешений и другой информации. DrvFs также запрещает использование специального кэша директорий (directory entry cache). Это делается для постоянного его поддержания в состоянии актуальности, даже в том случае, когда один из других процессов Windows модифицирует содержимое директории. Таким образом, не существует ограничений на то, что процессы Windows могут делать с файлами, пока DrvFs также имеет к ним доступ. DrvFs также использует семантику Windows при удалении файлов, так что над файлом не может быть осуществлена операция unlink в случае присутствия каких-либо открытых дескрипторов на него.
ProcFs и SysFs
В случае с Linux данные типы специальных директорий не работают с дисковыми файлами, вместо этого предоставляя информацию, которая имеется у ядра ОС о запущенных процессах, потоках, используемых устройствах. Эти директории динамически генерируются при попытке их чтения клиентом. В некоторых случаях, информация для этих директорий целиком хранится в памяти LXCore.sys. В других случаях, например, использование микропроцессора каким-либо из процессов, WSL запрашивает эту информацию у ядра Windows. Однако, в обоих случаях плагины не взаимодействуют с дисковыми файловыми системами Windows.
Автор: ESET NOD32