Статья опубликована в рамках: CLX Международной научно-практической конференции «Научное сообщество студентов XXI столетия. ТЕХНИЧЕСКИЕ НАУКИ» (Россия, г. Новосибирск, 06 апреля 2026 г.)
Наука: Информационные технологии
Скачать книгу(-и): Сборник статей конференции
дипломов
МОДУЛЬ ЯДРА LINUX ДЛЯ АВТОМАТИЧЕСКОГО РЕДАКТИРОВАНИЯ СОДЕРЖИМОГО ФАЙЛОВ, ПЕРЕДАВАЕМЫХ НА ВНЕШНИЕ USB-НАКОПИТЕЛИ С ФАЙЛОВОЙ СИСТЕМОЙ FAT32
A LINUX KERNEL MODULE FOR AUTOMATICALLY EDITING THE CONTENTS OF FILES TRANSFERRED TO EXTERNAL USB DRIVES WITH THE FAT32 FILE SYSTEM
Smirnov Peter Ilyich
Student, Department of IU7 "Computer Software and Technologies", Bauman Moscow State Technical University,
Russia, Moscow
АННОТАЦИЯ
В данной статье рассматривается алгоритм работы загружаемого модуля ядра, который перехватывает управление у USB (Universal Serial Bus) подсистемы Linux для получения доступа к полям структуры URB(USB Request Block), и последующего редактирования содержимого файлов.
ABSTRACT
This article discusses the algorithm of a loadable kernel module that intercepts control from the USB (Universal Serial Bus) subsystem of Linux to gain access to the fields of the URB (USB Request Block) structure and subsequently edit the contents of files.
Ключевые слова: DLP, USB, URB, FAT32, модуль ядра, Linux.
Keywords: DLP, USB, URB, FAT32, kernel module, Linux.
Для успешного ведения бизнеса компаниям необходимо обеспечить сохранность всей документации, от внутренних регламентов и бухгалтерской отчётности до рабочих записей и деловой переписки. Данные могут утечь из организации по нескольким причинам. Это может быть как систематическая халатность сотрудников, отсутствие налаженных бизнес-процессов, так и преднамеренная передача документов конкурентам нелояльными сотрудниками. Для минимизации рисков активно развиваются DLP-системы (Data Leak Prevention) — системы предотвращения утечек данных [1]. Они контролируют множество каналов передачи информации от рабочей станции, такие как сеть, устройства ввода-вывода и различные диски. Одними из самых часто используемых каналов являются USB-порты, через которые можно подключить внешний накопитель (жёсткий диск или флеш-карту), скопировать на него корпоративные документы и незаметно вынести за пределы организации. Простейший способ сделать невозможным такое событие, это отключить USB-порты. Однако это не всегда может быть удобно, так как они используются и устройствами ввода-вывода, например, мышью или клавиатурой. Более рациональным решением будет не полностью отключать порты, а программно менять их поведение для минимизации рисков утечек данных. В данной статье описывается алгоритм загружаемого модуля ядра, который позволяет динамически изменять данные, передаваемые на внешние накопители.
Основные компоненты, осуществляющие взаимодействие с USB-устройствами [3]:
- драйвер устройства;
- ядро USB (USB Core) — общий код, управляющий всей подсистемой;
- драйвер хост-контроллера (HCD) — реализует программно-аппаратное взаимодействие.
Схема взаимодействия драйверов USB:
- драйвер устройства создает или получает запрос на передачу информации;
- драйвер инициализирует запрос всей необходимой информацией, такой как тип запроса, адрес устройства, указатель на буфер данных;
- драйвер отправляет запрос в ядро USB;
- ядро и HCD выполняют необходимую низкоуровневую работу, чтобы выполнить этот запрос на физической шине USB;
- когда операция завершена (данные получены, отправлены или произошла ошибка), HCD вызывает функцию обратного вызова для этого запроса, чтобы уведомить драйвер устройства о результате.
Подсистема USB операционной системы Linux реализует общение с внешними устройствами посредством структуры URB — USB Request Block. Она инкапсулирует запрос на передачу данных, передаваемый драйвером USB-устройства низкоуровневому драйверу хост-контроллера. Данная структура содержит в себе сведения о подключенном устройстве, параметрах передачи, может хранить в себе как непосредственно данные копируемых файлов, так и различную служебную информацию. Ниже приведены поля данной структуры и их краткие характеристики, необходимые для реализации модуля.
- struct usb_device *udev — указатель на структуру, описывающий USB-устройство. В конфигурации устройства содержится описатель интерфейса дескриптора, необходимый для определения протокола передачи;
- void *transfer_buffer — указатель на область данных для передачи;
- u32 transfer_buffer_length — размер передаваемого буфера;
- struct scatterlist *sg — указатель на первый элемент списка разрозненных буферов для передачи;
- int num_sgs — длина списка разрозненных буферов.
URB поддерживает все четыре типа передач, определенные в спецификации USB [4]:
- управляющие посылки (Control Transfers), используемые для конфигурирования во время подключения и в процессе работы для управления устройствами;
- сплошные передачи (Bulk Data Transfers) сравнительно больших пакетов без жестких требований ко времени доставки. Приоритет этих передач самый низкий, они могут приостанавливаться при большой загрузке шины;
- прерывания (Interrupt) — короткие передачи, имеют спонтанный характер и должны обслуживаться не медленнее, чем того требует устройство;
- изохронные передачи (Isochronous Transfers) --- непрерывные передачи в реальном времени, занимающие предварительно согласованную часть пропускной способности шины и имеющие заданную задержку доставки.
Каждая операция ввода-вывода через USB шину оформляется в виде отдельного URB, что обеспечивает единый интерфейс для работы с различными типами USB-передач. В данной работе будут рассматриваться только сплошные передачи, составляющие основу BulkOnly протокола передачи.
Модуль использует механизм перехвата управления kprobes. Kprobes — это средство динамической отладки ядра, позволяющее ставить точки останова на доступные для записи участки памяти и самостоятельно обрабатывать их [2]. Для получения полностью инициализированной, готовой к отправке на хост контроллера структуры URB перехват осуществляется у функции usb_hcd_link_urb_to_ep, которая ставит URB в очередь конечной точки на уровне хост контроллера:

Рисунок 1. Регистрация точки останова
Алгоритм состоит из нескольких основных этапов. Разберём каждый их них.
1. Первоначально необходимо оставить только те URB, которые относятся к интерфейсу устройств хранения данных. Далее отбрасываются те URB, которые передаются не по протоколу BulkOnly, и те, которые не используют SCSI-подкласс передачи. Истинное значение функции usb_urb_dir_out свидетельствует о том, что URB идёт от компьютера на внешнее устройство, а не наоборот:

Рисунок 2. Фильтрация URB по протоколу, классу, подклассу, направлению
2. Фильтрация только тех URB, которые содержат непосредственно данные передаваемых файлов или служебную информацию для файловой системы FAT32.
Если поле transfer_buffer не пусто, то в нём содержится команда BulkOnly протокола. Для получения дополнительных сведений необходимо привести данное поле к указателю на структуру bulk_cb_wrap. В случае, если присутствует USBC сигнатура, поле Flags содержит флаги, указывающие на осмысленность передачи, значение её поля CDB равно одному из WRITE кодов SCSI, определённых в файле scsi_proto.h, а поле DataTransferLength ненулевое, то следующая за ней URB будет нести либо пользовательские данные, либо метаинформацию файловой системы FAT32.
В противном случае, если поле transfer_buffer пусто, а поле num_sgs — размер scatter-gather списка, ненулевое, значит, что структура несёт в себе данные файлов или информацию FAT32.

Рисунок 3. Фильтрация URB, содержащих данные передаваемых файлов или метаинформацию FAT32
3. Фильтрация тех URB, которые содержат только данные передаваемых файлов.
Необходимо обработать каждый узел scatter-gather списков. Для этого используется предописанный итератор for_each_sg, для каждого узла вызывается функция sg_page, которая возвращает указатель на структуру, описывающую страницу памяти. Для работы с ней необходимо транслировать регион в виртуальную память, и прибавить смещение, хранящееся в структуре списка, где фактически располагается информация. Получив содержательную часть, нужно отфильтровать непосредственно пользовательские данные. Для этого с использованием макросов из файла msdos_fs.h необходимо детектировать узлы, которые содержат такую FAT32 информацию, как описание корневого каталога, таблицу кластеров FAT, сигнатуру FS_INFO, описание путей, нулевые регионы и данные по удалённым файлам:

Рисунок 4. Получение виртуального адреса данных и фильтрация метаинформации FAT32

Рисунок 5. Функция определения данных как FAT-таблицы
4. Редактирование данных.
Здесь возможно применение алгоритмов шифрования, разрушения или точечной сигнатурной подмены данных. В данном модуле данные заменяются на произвольные с использованием функции get_random_bytes.
5. Синхронизация кэша процессора и освобождение использованных ресурсов.
При перехвате URB-запросов и модификации передаваемых данных необходимо обеспечить согласованность между кэшем центрального процессора и физической памятью. Драйвер хост-контроллера USB использует прямой доступ к памяти (DMA) для чтения данных непосредственно из физических адресов, минуя кэш процессора. Чтобы гарантировать, что контроллер получает актуальные модифицированные данные, требуется явная синхронизация кэша. Для этого используется функция dma_sync_single_for_device, которая обеспечивает запись изменений из кэша процессора в физическую память перед началом операции DMA от устройства. Функция kunmap_local отменяется временное отображение страницы памяти в виртуальное адресное пространство.

Рисунок 6. Синхронизация кэша процессора и отмена временного отображения страницы памяти
Полный код модуля доступен по ссылке: https://github.com/pitsmit/OS-Course-Project/blob/main/code/monitor.c.
Список литературы:
- Акцызов, И. Н. DLP-система как способ защиты от внутренних утечек информации / И. Н. Акцызов // Наука XXI века: проблемы, поиски, решения : материалы XLVIII научно-практической конференции, посвящённой 100-летию со дня рождения академика В. П. Макеева, Миасс, 26 апреля 2024 года. – Челябинск: Челябинский государственный университет, 2024. – С. 3-7. – EDN KKKSXB.
- Kernel Probes (Kprobes) // The Linux Kernel Documentation. — 2026. [электронный ресурс] — Режим доступа. — URL: https://docs.kernel.org/trace/kprobes.html (дата обращения 02.04.2026).
- Linux-USB Host Side API // The Linux Kernel Documentation. — 2026. [электронный ресурс] — Режим доступа. — URL: https://docs.kernel.org/driver-api/usb/usb.html (дата обращения 02.04.2026).
- Mass Storage Control/Bulk/Interrupt (CBI) Specification 1.1 // USB. — 2003. [электронный ресурс] — Режим доступа. — URL: https://www.usb.org/sites/default/files/usb_msc_cbi_1.1.pdf (дата обращения 02.04.2026).
дипломов

