5.3 KiB
5.3 KiB
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
cnode.mint(src, dest, relation, rights)
src— исходный слот (должен иметь GRANT).dest— целевой слот (должен быть пустым).relation— как наследник связан с родителем.rights— права наследника (∩ с правами родителя).
Revoke — отзыв capability
cnode.revoke(slot_idx)
- Рекурсивно находит всех потомков и уничтожает их.
- Уничтожает сам capability.
- Отправляет
token_sigв глобальнуюMMU_REVOCATION_QUEUE. - VMM при следующем page fault обрабатывает все накопленные отзывы.
Lock Ranking — предотвращение дедлоков
В mint() захватываются две блокировки (src и dest). Чтобы избежать
инверсии блокировок, используется строгий порядок:
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, связанные с отозванным токеном. Для этого:
revoke()пушитtoken_sigв lock-free очередь.- При page fault:
process_pending_revocations()дренирует очередь. - VMA с
cap_token == token_sigудаляются из AddressSpace. - TLB flush для синхронизации MMU.
Использование в kmain()
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);