Handle 与 Rights
OpenOS 采用基于能力(Capability)的访问控制模型。Handle 是用户空间与内核交互的唯一方式,每个 Handle 携带一个 Rights 位掩码,限制允许的操作。
Handle 结构
Section titled “Handle 结构”Handle 是一个 64 位的不透明令牌,引用内核对象:
bits [0:31] slot_id — 任务 Handle 表索引bits [32:47] rights — 能力权限位掩码(u16)bits [48:63] generation — 防止关闭后使用(u16)Rust 实现
Section titled “Rust 实现”#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub struct Handle(u64);
impl Handle { pub fn new(slot_id: u32, rights: Rights, generation: u16) -> Self { Self(slot_id as u64 | ((rights.raw() as u64) << 32) | ((generation as u64) << 48)) }
pub fn slot_id(self) -> u32 { self.0 as u32 }
pub fn rights(self) -> Rights { Rights::from_raw(((self.0 >> 32) & 0xFFFF) as u16) }
pub fn generation(self) -> u16 { ((self.0 >> 48) & 0xFFFF) as u16 }
pub fn as_u64(self) -> u64 { self.0 }
/// 创建具有收窄权限的派生 Handle pub fn with_rights(self, new_rights: Rights) -> Self { Self::new( self.slot_id(), self.rights().intersect(new_rights), self.generation(), ) }}Rights 系统
Section titled “Rights 系统”Rights 是一个 10 位的权限位掩码:
#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub struct Rights(u16);
impl Rights { pub const ALL: Self = Self(0x3FF); pub const BASIC: Self = Self(Self::TRANSFER.0 | Self::DUPLICATE.0 | Self::WAIT.0 | Self::DESTROY.0); pub const IO: Self = Self(Self::READ.0 | Self::WRITE.0);
// 权限位定义 pub const READ: Self = Self(1 << 0); // bit 0 pub const WRITE: Self = Self(1 << 1); // bit 1 pub const EXECUTE: Self = Self(1 << 2); // bit 2 pub const TRANSFER: Self = Self(1 << 3); // bit 3 pub const DUPLICATE: Self = Self(1 << 4); // bit 4 pub const SIGNAL: Self = Self(1 << 5); // bit 5 pub const WAIT: Self = Self(1 << 6); // bit 6 pub const DESTROY: Self = Self(1 << 7); // bit 7 pub const MAP: Self = Self(1 << 8); // bit 8 pub const CONFIGURE: Self = Self(1 << 9); // bit 9}| 位 | 名称 | 说明 |
|---|---|---|
| 0 | READ | 从对象读取数据 |
| 1 | WRITE | 向对象写入数据 |
| 2 | EXECUTE | 执行(用于内存对象) |
| 3 | TRANSFER | 通过 Channel 发送此 Handle |
| 4 | DUPLICATE | 在同一进程内克隆此 Handle |
| 5 | SIGNAL | 发送信号 |
| 6 | WAIT | 等待对象 |
| 7 | DESTROY | 关闭/销毁对象 |
| 8 | MAP | 映射到地址空间 |
| 9 | CONFIGURE | 修改对象属性 |
| 常量 | 值 | 说明 |
|---|---|---|
ALL | 0x3FF | 所有权限 |
BASIC | TRANSFER | DUPLICATE | WAIT | DESTROY | 基本权限 |
IO | READ | WRITE | 读写权限 |
Rights 只能通过 intersect 收窄,不能放大:
/// 交集(收窄)两个权限集 —— 单调特权递减pub fn intersect(self, other: Self) -> Self { Self(self.0 & other.0)}示例:
let original = Rights::ALL; // 0x3FFlet narrowed = original.intersect(Rights::IO); // READ | WRITEassert!(narrowed.contains(Rights::READ));assert!(!narrowed.contains(Rights::EXECUTE));KernelObject
Section titled “KernelObject”Handle 引用的内核对象类型:
pub enum KernelObject { /// Channel 的 A 端(通常是"客户端"端) ChannelEndA(Arc<Mutex<Channel>>), /// Channel 的 B 端(通常是"服务器"端) ChannelEndB(Arc<Mutex<Channel>>),}注意: ChannelEndA 和 ChannelEndB 都引用同一个 Channel,但代表相反的端点。
HandleTable
Section titled “HandleTable”每个任务都有一个 Handle 表:
pub struct HandleTable { slots: BTreeMap<u32, HandleEntry>, next_slot: u32, generation: u32,}
struct HandleEntry { handle: Handle, object: KernelObject,}insert
Section titled “insert”插入内核对象,返回新 Handle:
pub fn insert(&mut self, object: KernelObject, rights: Rights) -> Handle { let slot_id = self.next_slot; self.next_slot += 1; let gen = (self.generation & 0xFFFF) as u16; self.generation += 1; let handle = Handle::new(slot_id, rights, gen); self.slots.insert(slot_id, HandleEntry { handle, object }); handle}获取 Handle 引用的内核对象,验证 generation:
pub fn get(&self, handle: Handle) -> Option<&KernelObject> { self.slots.get(&handle.slot_id()).and_then(|entry| { if entry.handle.generation() == handle.generation() { Some(&entry.object) } else { None // generation 不匹配,Handle 已失效 } })}关闭 Handle:
pub fn close(&mut self, handle: Handle) -> bool { let gen = handle.generation(); match self.slots.get(&handle.slot_id()) { Some(entry) if entry.handle.generation() == gen => { self.slots.remove(&handle.slot_id()); true } _ => false, }}duplicate
Section titled “duplicate”克隆 Handle,可选择收窄权限:
pub fn duplicate(&mut self, handle: Handle, new_rights: Rights) -> Option<Handle> { // 检查 DUPLICATE 权限 if !handle.rights().contains(Rights::DUPLICATE) { return None; }
let entry = self.slots.get(&handle.slot_id())?; if entry.handle.generation() != handle.generation() { return None; }
// 克隆内核对象引用 let object = match &entry.object { KernelObject::ChannelEndA(ch) => KernelObject::ChannelEndA(Arc::clone(ch)), KernelObject::ChannelEndB(ch) => KernelObject::ChannelEndB(Arc::clone(ch)), };
let slot_id = self.next_slot; self.next_slot += 1; let gen = (self.generation & 0xFFFF) as u16; self.generation += 1;
// 权限收窄 let new_handle = Handle::new(slot_id, handle.rights().intersect(new_rights), gen); self.slots.insert(slot_id, HandleEntry { handle: new_handle, object }); Some(new_handle)}Handle 传递
Section titled “Handle 传递”handle_transfer
Section titled “handle_transfer”通过 Channel 将 Handle 发送给另一个进程:
fn handle_transfer(handle: u64, target_channel: u64, rights: u64) -> i64行为:
- 从发送方的 Handle 表中移除 Handle
- 将 Handle 值存储到 Channel 的
pending_handlesVec - 接收方在下一次 receive 时获取 Handle
权限收窄:
原始 Handle: READ | WRITE | TRANSFER | MAP传递 Rights: READ | MAP──────────────────────────────接收方获得: READ | MAP (交集)与 POSIX 对比
Section titled “与 POSIX 对比”| 方面 | POSIX | OpenOS |
|---|---|---|
| 访问令牌 | 文件描述符(小整数) | Handle(64 位不透明令牌) |
| 权限 | open() 时指定 | Handle 携带 Rights |
| 委托 | 传递 FD 号 | 通过 Channel 传递 Handle |
| 撤销 | 无法撤销 | 关闭 Handle |
| 全局性 | 进程全局 FD 表 | 进程本地 Handle 表 |
| 安全性 | 环境权限 | 显式能力 |
#[test]fn test_handle_packing() { let rights = Rights::ALL; // 0x3FF let h = Handle::new(42, rights, 7); assert_eq!(h.slot_id(), 42); assert_eq!(h.rights(), Rights::ALL); assert_eq!(h.generation(), 7);}
#[test]fn test_rights_monotonic_reduction() { let original = Rights::ALL; let narrowed = original.intersect(Rights::READ); assert!(narrowed.contains(Rights::READ)); assert!(!narrowed.contains(Rights::WRITE));}
#[test]fn test_handle_table_duplicate() { let mut table = HandleTable::new(); let ch = make_channel(); let handle = table.insert(KernelObject::ChannelEndA(ch), Rights::ALL);
let dup = table.duplicate(handle, Rights::READ); assert!(dup.is_some()); let dup = dup.unwrap(); assert_ne!(dup.slot_id(), handle.slot_id()); assert!(dup.rights().contains(Rights::READ)); assert!(!dup.rights().contains(Rights::WRITE)); // 收窄}- Channel IPC - Channel 通信机制
- 系统调用参考 - Handle 相关系统调用
- 安全模型 - 整体安全设计