跳转到内容

Handle 与 Rights

OpenOS 采用基于能力(Capability)的访问控制模型。Handle 是用户空间与内核交互的唯一方式,每个 Handle 携带一个 Rights 位掩码,限制允许的操作。

Handle 是一个 64 位的不透明令牌,引用内核对象:

bits [0:31] slot_id — 任务 Handle 表索引
bits [32:47] rights — 能力权限位掩码(u16)
bits [48:63] generation — 防止关闭后使用(u16)
#[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 是一个 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
}
名称说明
0READ从对象读取数据
1WRITE向对象写入数据
2EXECUTE执行(用于内存对象)
3TRANSFER通过 Channel 发送此 Handle
4DUPLICATE在同一进程内克隆此 Handle
5SIGNAL发送信号
6WAIT等待对象
7DESTROY关闭/销毁对象
8MAP映射到地址空间
9CONFIGURE修改对象属性
常量说明
ALL0x3FF所有权限
BASICTRANSFER | DUPLICATE | WAIT | DESTROY基本权限
IOREAD | WRITE读写权限

Rights 只能通过 intersect 收窄,不能放大:

/// 交集(收窄)两个权限集 —— 单调特权递减
pub fn intersect(self, other: Self) -> Self {
Self(self.0 & other.0)
}

示例:

let original = Rights::ALL; // 0x3FF
let narrowed = original.intersect(Rights::IO); // READ | WRITE
assert!(narrowed.contains(Rights::READ));
assert!(!narrowed.contains(Rights::EXECUTE));

Handle 引用的内核对象类型:

pub enum KernelObject {
/// Channel 的 A 端(通常是"客户端"端)
ChannelEndA(Arc<Mutex<Channel>>),
/// Channel 的 B 端(通常是"服务器"端)
ChannelEndB(Arc<Mutex<Channel>>),
}

注意: ChannelEndA 和 ChannelEndB 都引用同一个 Channel,但代表相反的端点。

每个任务都有一个 Handle 表:

pub struct HandleTable {
slots: BTreeMap<u32, HandleEntry>,
next_slot: u32,
generation: u32,
}
struct HandleEntry {
handle: Handle,
object: KernelObject,
}

插入内核对象,返回新 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,
}
}

克隆 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)
}

通过 Channel 将 Handle 发送给另一个进程:

fn handle_transfer(handle: u64, target_channel: u64, rights: u64) -> i64

行为:

  1. 从发送方的 Handle 表中移除 Handle
  2. 将 Handle 值存储到 Channel 的 pending_handles Vec
  3. 接收方在下一次 receive 时获取 Handle

权限收窄:

原始 Handle: READ | WRITE | TRANSFER | MAP
传递 Rights: READ | MAP
──────────────────────────────
接收方获得: READ | MAP (交集)
方面POSIXOpenOS
访问令牌文件描述符(小整数)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)); // 收窄
}