Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ x86_64-linux-gnu-g++ -m32 -ffreestanding -fno-pie -fno-exceptions -fno-rtti -nos
x86_64-linux-gnu-ld -m elf_i386 -T user/user.ld user_crt0.o user_anim.o user_libc.a -o ANIM.ELF
mcopy -i data.img ANIM.ELF ::/tests/ANIM.ELF

x86_64-linux-gnu-g++ -m32 -ffreestanding -fno-pie -fno-exceptions -fno-rtti -nostdlib -nostdinc -Iuser -Iuser/libc/include -c user/tests/tetris.cpp -o user_tetris.o
x86_64-linux-gnu-ld -m elf_i386 -T user/user.ld user_crt0.o user_tetris.o user_libc.a -o TETRIS.ELF
mcopy -i data.img TETRIS.ELF ::/tests/TETRIS.ELF

x86_64-linux-gnu-g++ -m32 -ffreestanding -fno-pie -fno-exceptions -fno-rtti -nostdlib -nostdinc -Iuser -Iuser/libc/include -c user/tests/gfxedit.cpp -o user_gfxedit.o
x86_64-linux-gnu-ld -m elf_i386 -T user/user.ld user_crt0.o user_gfxedit.o user_libc.a -o GFXEDIT.ELF
mcopy -i data.img GFXEDIT.ELF ::/tests/GFXEDIT.ELF

x86_64-linux-gnu-g++ -m32 -ffreestanding -fno-pie -fno-exceptions -fno-rtti -nostdlib -nostdinc -Iuser -Iuser/libc/include -c user/ps2_driver.cpp -o user_ps2_driver.o
x86_64-linux-gnu-g++ -m32 -ffreestanding -fno-pie -fno-exceptions -fno-rtti -nostdlib -nostdinc -Iuser -Iuser/libc/include -c user/tests/ps2_test.cpp -o user_ps2_test.o
x86_64-linux-gnu-ld -m elf_i386 -T user/user.ld user_crt0.o user_ps2_test.o user_ps2_driver.o user_libc.a -o PS2TEST.ELF
Expand Down
181 changes: 181 additions & 0 deletions docs/DRIVER_API_STABILIZATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# DriverAPI — план стабилизации

> Цель: перевести текущий DriverAPI из режима «доверенной демо-модели» в режим предсказуемого и безопасного ABI для долгоживущих Ring3-драйверов.

## 1) Текущее состояние (по коду)

1. User-space `DriverAPI` задаёт только C++-интерфейс `init/read/write/seek/ioctl/stop` без ABI-версии, feature-flags и без стандартной модели ошибок.
2. Syscall-слой даёт прямой доступ к `inb/outb/inw/outw`, `wait_irq`, `map_mmio`, `grant_mmio`, `set_driver`.
3. Сейчас есть «временный» bypass: все ELF, загруженные через `elf_exec`, получают `is_driver = true`.
4. В `sys_map_mmio` есть логическая ошибка проверки grant-диапазонов: для `is_driver == true` доступ разрешается без проверки списка grant.
5. В DriverContext отсутствует жизненный цикл capability-хэндлов (IRQ/MMIO/PIO), поэтому драйвер не может безопасно «освобождать» возможности.
6. `PS2Driver` работает через busy-wait и не имеет явной state-машины и recovery-политики.

## 2) Главные риски стабильности

- **Эскалация привилегий**: auto-driver для любого ELF и широкие I/O syscalls.
- **Непредсказуемость ABI**: нет version negotiation для user driver binary.
- **Дрейф поведения ошибок**: разные syscalls возвращают `0`/`-1` без единой errno-модели.
- **Зависание в I/O**: нет timeout/error surface в ожидании IRQ и I/O handshakes.
- **Невозможность безопасного hot-restart**: нет единого stop/teardown протокола в ядре.

## 3) Реализации для стабилизации (рекомендуемый порядок)

## 3.1 Capability-first DriverAPI (MVP)

Вместо «глобального is_driver» ввести capability-токены, выдаваемые ядром:

- `cap_irq_wait(irq)`
- `cap_pio_read(port, width)` / `cap_pio_write(...)`
- `cap_mmio_map(cap_id, virt, pages)`

Идея: `sys_set_driver` переводится в «может запрашивать capabilities», а не «полный доступ к железу».

### Минимальные syscall-добавления

- `SYS_CAP_ACQUIRE(type, arg0, arg1)` -> `cap_id | <0`
- `SYS_CAP_RELEASE(cap_id)`
- `SYS_CAP_PIO_RW(cap_id, op, value)`
- `SYS_CAP_IRQ_WAIT(cap_id, timeout_ms)`
- `SYS_CAP_MMIO_MAP(cap_id, virt, pages)`

Это сразу решает гранулярность прав и даёт обратимый teardown.

## 3.2 Исправление политики MMIO (обязательный hotfix)

Текущее поведение: `if (cur.is_driver) allowed = true;`.

Исправление:

- Разрешать `map_mmio` **только** если диапазон входит в `allowed_mmio[]`.
- Исключение только для `tid==0` (kernel bootstrap thread), и то под compile-time флагом `RE36_DEV_TRUST_BOOT=1`.

## 3.3 Driver manifest + trust policy

Для ELF-драйвера рядом класть `*.drv.json`:

```json
{
"name": "ps2kbd",
"abi": 1,
"caps": {
"irq": [1],
"pio": [{"start":96,"end":100}],
"mmio": []
},
"restart": "on-failure"
}
```

Kernel loader:

1. читает manifest,
2. валидирует ABI,
3. выдаёт caps,
4. только после этого запускает driver thread.

## 3.4 DriverContext v2 (ABI-stable)

Предлагаемая структура:

```c
struct DriverContextV2 {
uint32_t abi_version; // = 2
uint32_t driver_tid;
uint32_t device_id;
uint32_t flags;

uint32_t irq_caps[8];
uint32_t pio_caps[8];
uint32_t mmio_caps[8];

void* shared_cfg;
uint32_t shared_cfg_size;

int32_t last_error; // errno-like
};
```

Плюс `ioctl`-контракт:

- `DRV_IOCTL_GET_VERSION`
- `DRV_IOCTL_GET_HEALTH`
- `DRV_IOCTL_RESET`
- `DRV_IOCTL_QUIESCE`

## 3.5 Единая ошибка/диагностика

Ввести таблицу для драйверного слоя:

- `DRV_OK = 0`
- `DRV_EPERM`, `DRV_EINVAL`, `DRV_ETIMEDOUT`, `DRV_EIO`, `DRV_EBUSY`, `DRV_EAGAIN`, `DRV_ENOTSUP`.

Правило: syscall всегда возвращает `<0` при ошибке и заполняет `last_error`.

## 3.6 Надёжный lifecycle драйвера

Ядро должно поддерживать единый протокол:

1. `probe` (resource check)
2. `init`
3. `run`
4. `quiesce`
5. `stop`
6. `recover` (опционально)

Технически: watchdog-счётчик heartbeat + restart policy (`never`, `on-failure`, `always`).

## 3.7 Стабилизация PS/2 как эталонного драйвера

Для `PS2Driver` внедрить:

- state-machine (`Reset -> SelfTest -> Config -> Streaming`),
- timeout-aware `wait_read/write` с кодами ошибок,
- retry budget (например, 3 попытки для ACK),
- отдельный ring buffer событий,
- `ioctl(GET_STATS)` для диагностики (timeouts, parity, overruns).

## 4) План внедрения (по PR)

### PR-1 (без ломки API)

- Hotfix `sys_map_mmio` policy.
- Убрать auto `is_driver=true` для всех ELF, оставить whitelist (shell/testdriver).
- Унифицировать return codes (`-1`/negative errno).

### PR-2 (новые syscall capabilities)

- Добавить `SYS_CAP_*`.
- Обернуть существующие `sys_inb/outb/...` через capability checks.
- Добавить revoke path в `thread_cleanup`.

### PR-3 (manifest + loader)

- Парсинг `.drv.json`.
- Выдача caps из manifest.
- Запуск/перезапуск по policy.

### PR-4 (DriverContext v2 + PS2 refactor)

- Ввести `DriverContextV2`.
- Перенести PS2 driver на v2 + telemetry.

## 5) Критерии готовности (Definition of Done)

- Драйвер без capability не может:
- делать PIO,
- ждать IRQ,
- map/unmap MMIO.
- После `thread_cleanup` все caps ревокнуты и MMIO unmapped.
- Driver ABI version check обязателен при старте.
- Watchdog фиксирует зависшие драйверы и применяет policy без kernel panic.
- Нагрузочный тест (10k циклов init/stop) без утечек и зависаний.

## 6) Быстрые точечные изменения прямо сейчас

1. В `sys_map_mmio` убрать unconditional `allowed=true` для `is_driver`.
2. В `elf_exec` убрать выдачу driver-флага всем ELF.
3. В `PS2Driver::wait_read/write` возвращать код таймаута и прокидывать его в `read/write/init`.
4. Ввести единый `driver_errno.h` для user-space драйверов.

Эти четыре пункта дадут максимум прироста стабильности при минимальном размере изменений.
61 changes: 61 additions & 0 deletions docs/TOP10_CRITICAL_FIXES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# TOP-10 критичных мест для исправления в первую очередь

Ниже — приоритетный список мест, которые дают наибольший риск по безопасности/стабильности и должны исправляться первыми.

## 1. Эскалация прав: любой ELF получает `is_driver=true`
- Где: `elf_exec()`.
- Почему критично: любой загруженный ELF получает привилегии драйвера (PIO/MMIO/IRQ), что ломает модель изоляции Ring3.
- Минимальный фикс: убрать auto-grant, оставить только whitelist/manifest-driven выдачу прав.

## 2. Ошибка политики MMIO в `sys_map_mmio`
- Где: `sys_map_mmio`.
- Почему критично: для `is_driver` сейчас доступ разрешается без проверки grant-диапазонов.
- Минимальный фикс: всегда проверять `allowed_mmio[]` (кроме строго ограниченного bootstrap-исключения).

## 3. Грубая модель DriverAPI через флаг `is_driver`
- Где: `sys_inb/outb/inw/outw`, `sys_wait_irq`, `sys_set_driver`.
- Почему критично: нет capability-гранулярности (порт/IRQ/диапазон), одна ошибка в policy = полный доступ.
- Минимальный фикс: capability tokens + revoke на cleanup.

## 4. VFS ABI-хак: `vnode*` возвращается как `int`
- Где: `vfs_open()` и использование в syscall-слое.
- Почему критично: риск UB/переполнений/разъезда ABI, усложнение безопасного управления lifetime.
- Минимальный фикс: нормальный контракт `file*`/fd без pointer-cast.

## 5. VFS не поддерживает реальные mountpoint-префиксы
- Где: `vfs_resolve_path` (жёстко `mount_points[0]`).
- Почему критично: расширение на несколько ФС/дисков фактически блокировано; возможны неверные резолвы пути.
- Минимальный фикс: выбрать superblock по самому длинному совпавшему mount-prefix.

## 6. Неконсистентные коды ошибок в syscalls
- Где: `sys_outb/sys_outw` возвращают `0` даже при запрете; часть API возвращает `-1`, часть `0`.
- Почему критично: user-space не может надёжно отличить success/failure, ошибки теряются.
- Минимальный фикс: единая negative errno-модель для всех driver-related syscalls.

## 7. Отсутствие timeout/error surface в ожидании IRQ
- Где: `sys_wait_irq` + user-driver loops.
- Почему критично: зависания драйвера в вечном ожидании и непрозрачные deadlock-сценарии.
- Минимальный фикс: `wait_irq(irq, timeout_ms)` + диагностируемые коды таймаута.

## 8. Busy-wait без явного результата в PS/2 драйвере
- Где: `PS2Driver::wait_read/write`.
- Почему критично: функции "молча" выходят по timeout, а вызывающий код продолжает I/O как будто всё ок.
- Минимальный фикс: возвращать статус/ошибку, пробрасывать в `init/read/write`.

## 9. Shell запускается как driver-thread
- Где: `kernel_main` выставляет `threads[shell_tid].is_driver = true`.
- Почему критично: CLI-процесс получает повышенные привилегии по умолчанию; высокий blast radius.
- Минимальный фикс: убрать broad privilege, выдавать только минимальные capabilities.

## 10. `sys_set_driver` без строгой trust-цепочки
- Где: `sys_set_driver`.
- Почему критично: при компромете одного driver-thread можно массово повышать привилегии другим потокам.
- Минимальный фикс: policy check (manifest owner/signature/ACL) + аудит вызовов.

---

## Рекомендуемый порядок внедрения (коротко)
1) Пункты 1+2+9 (быстрое снижение риска эскалации).
2) Пункты 3+6+7 (формализация API и ошибок).
3) Пункты 4+5 (архитектурная чистка VFS).
4) Пункты 8+10 (драйверная надёжность и trust policy).
Loading