# 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); ```