Files
Elyz/kernel/docs/capability/introduction.md
2026-07-07 16:40:41 +03:00

127 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Capability-система: концептуальная модель
## Философия
**Capability** (дескриптор возможности) — это **неподделываемый токен**,
дающий право выполнить определённую операцию над определённым объектом.
В традиционных ОС (Linux, Windows) доступ контролируется через:
- PID + UID/GID + проверка при каждом системном вызове.
- MMU: page tables определяют, что отображено, но не кто отобразил.
В модели capabilities:
- **Если у вас нет capability — у вас нет доступа.**
- Capability хранятся в CNode — защищённой таблице, доступной только ядру.
- Capability можно создавать только от родительского capability
(иерархия наследования).
- Права можно только **урезать** (mint), но не расширить.
- Capability можно **отозвать** (revoke), что уничтожает его
и всех его потомков.
## Основные понятия
```
Capability {
object: CapObject, // на что указывает (Memory, CNode, PMActor...)
rights: CapRights, // права (R, W, X, G)
relation: Relation, // Strong (владеет), Borrow (заём), Transfer
token_sig: u64, // уникальный идентификатор (для revoke)
}
Relation {
Strong: владеет объектом (capability владеет памятью)
Borrow: заём — временный доступ без права распоряжаться
Transfer: передача — владение переходит получателю
}
CapRights {
READ = 0x1,
WRITE = 0x2,
EXECUTE = 0x4,
GRANT = 0x8, // разрешение создавать дочерние capability
}
```
## Иерархия и отзыв
```
CNode (массив слотов)
┌────────┬────────┬────────┬────────┐
│ slot 0 │ slot 1 │ slot 2 │ slot 3 │ ...
├────────┼────────┼────────┼────────┤
│ cap │ cap │ cap │ cap │
│ parent:│ parent:│ parent:│ parent:│
│ None │ Some(0)│ Some(0)│ Some(1)│
└────────┴────────┴────────┴────────┘
┌────────┴────────┐
▼ ▼
slot 1 slot 2
(mint from 0) (mint from 0)
revoke(0) → slot 0 уничтожается
→ рекурсивно: slot 1, slot 2 тоже уничтожаются
→ token_sig slot 0 отправляется в MMU_REVOCATION_QUEUE
→ VMM обработает отзыв при следующем page fault
```
### Mint — создание дочернего capability
```rust
cnode.mint(src, dest, relation, rights)
```
- `src` — исходный слот (должен иметь GRANT).
- `dest` — целевой слот (должен быть пустым).
- `relation` — как наследник связан с родителем.
- `rights` — права наследника (∩ с правами родителя).
### Revoke — отзыв capability
```rust
cnode.revoke(slot_idx)
```
1. Рекурсивно находит всех потомков и уничтожает их.
2. Уничтожает сам capability.
3. Отправляет `token_sig` в глобальную `MMU_REVOCATION_QUEUE`.
4. VMM при следующем page fault обрабатывает все накопленные отзывы.
## Lock Ranking — предотвращение дедлоков
В `mint()` захватываются две блокировки (src и dest). Чтобы избежать
инверсии блокировок, используется строгий порядок:
```rust
let (src_slot, dest_slot) = if src < dest {
// Захватываем меньший индекс первым
_guard_low = self.slots[src].lock();
_guard_high = self.slots[dest].lock();
} else {
_guard_low = self.slots[dest].lock();
_guard_high = self.slots[src].lock();
};
```
## Интеграция с VMM
При отзыве capability, VMM должна аннулировать все VMA, связанные
с отозванным токеном. Для этого:
1. `revoke()` пушит `token_sig` в lock-free очередь.
2. При page fault: `process_pending_revocations()` дренирует очередь.
3. VMA с `cap_token == token_sig` удаляются из AddressSpace.
4. TLB flush для синхронизации MMU.
## Использование в kmain()
```rust
let root_cnode = CNode::new(256);
// Вставка capability на фрейм
root_cnode.insert(0, mem_cap).unwrap();
// Mint с урезанными правами
root_cnode.mint(0, 10, Relation::Borrow, R | W).unwrap();
// Revoke — отзыв всех потомков
root_cnode.revoke(0);
```