对象管理器:Process 对象

权限

内核对象的“权限”指定允许对内核对象进行哪些操作。权限与句柄相关联,并传达对关联句柄或与句柄关联的对象执行操作的特权。单个进程可能对具有不同权限的同一个内核对象有两个不同的句柄。

句柄

句柄是允许用户程序引用内核对象引用的一种内核结构,它可以被认为是与特定内核对象的会话或连接。

通常情况下,多个进程通过不同的句柄同时访问同一个对象。对象可能有多个句柄(在一个或多个进程中)引用它们。但单个句柄只能绑定到单个进程或绑定到内核。

当句柄绑定到内核时,我们说它是“在传输中”('in-transit')。

在用户模式下,句柄只是某个系统调用返回的特定数字。只有“不在传输中”的句柄对用户模式可见。

代表句柄的整数只对其所属的那个进程有意义。另一个进程中的相同数字可能不会映射到任何句柄,或者它可能映射到指向完全不同的内核对象的句柄。

句柄的整数值是任何 32 位数字,但对应于ZX_HANDLE_INVALID的值将始终为 0。除此之外,有效句柄的整数值将始终具有句柄集的两个最低有效位. 可以使用ZX_HANDLE_FIXED_BITS_MASK访问代表这些位的掩码。

句柄可以从一个进程移动到另一个进程,方法是将它们写入通道(使用channel_write()),或者使用 process_start()传递一个句柄作为新进程中第一个线程的参数。对于几乎所有的对象,当最后一个打开的引用对象的句柄关闭时,对象要么被销毁,要么被置于可能无法撤消的最终状态。

Cargo.toml 中加入 bitflags 库:

[dependencies]
bitflags = "1.2"

在 object 模块下定义两个子模块:

// src/object/mod.rs
mod handle;
mod rights;

pub use self::handle::*;
pub use self::rights::*;

定义权限:

// src/object/rights.rs
use bitflags::bitflags;

bitflags! {
    /// 句柄权限
    pub struct Rights: u32 {
        const DUPLICATE = 1 << 0;
        const TRANSFER = 1 << 1;
        const READ = 1 << 2;
        const WRITE = 1 << 3;
        const EXECUTE = 1 << 4;
        const MAP = 1 << 5;
        const GET_PROPERTY = 1 << 6;
        const SET_PROPERTY = 1 << 7;
        const ENUMERATE = 1 << 8;
        const DESTROY = 1 << 9;
        const SET_POLICY = 1 << 10;
        const GET_POLICY = 1 << 11;
        const SIGNAL = 1 << 12;
        const SIGNAL_PEER = 1 << 13;
        const WAIT = 1 << 14;
        const INSPECT = 1 << 15;
        const MANAGE_JOB = 1 << 16;
        const MANAGE_PROCESS = 1 << 17;
        const MANAGE_THREAD = 1 << 18;
        const APPLY_PROFILE = 1 << 19;
        const SAME_RIGHTS = 1 << 31;

        const BASIC = Self::TRANSFER.bits | Self::DUPLICATE.bits | Self::WAIT.bits | Self::INSPECT.bits;
        const IO = Self::READ.bits | Self::WRITE.bits;

        const DEFAULT_CHANNEL = Self::BASIC.bits & !Self::DUPLICATE.bits | Self::IO.bits | Self::SIGNAL.bits | Self::SIGNAL_PEER.bits;
        /// GET_PROPERTY | SET_PROPERTY
        const PROPERTY = Self::GET_PROPERTY.bits | Self::SET_PROPERTY.bits;
        /// BASIC | IO | PROPERTY | ENUMERATE | DESTROY | SIGNAL | MANAGE_PROCESS | MANAGE_THREAD
        const DEFAULT_PROCESS = Self::BASIC.bits | Self::IO.bits | Self::PROPERTY.bits | Self::ENUMERATE.bits | Self::DESTROY.bits | Self::SIGNAL.bits | Self::MANAGE_PROCESS.bits | Self::MANAGE_THREAD.bits;
    }
}

定义句柄:

// src/object/handle.rs
use super::{DummyObject, KernelObject, Rights};
use alloc::sync::Arc;

/// 内核对象句柄
#[derive(Clone)]
pub struct Handle {
    pub object: Arc<dyn KernelObject>,
    pub rights: Rights,
}

impl Handle {
    /// 创建一个新句柄
    pub fn new(object: Arc<dyn KernelObject>, rights: Rights) -> Self {
        Handle { object, rights }
    }
}

存储内核对象句柄

添加成员变量 handles: BTreeMap<HandleValue, Handle>

实现 create,add_handle,remove_handle 函数

使用上一节的方法,实现一个空的 Process 对象:

// src/task/process.rs
/// 进程对象
pub struct Process {
    base: KObjectBase,
    inner: Mutex<ProcessInner>,
}

impl_kobject!(Process);

struct ProcessInner {
    handles: BTreeMap<HandleValue, Handle>,
}

pub type HandleValue = u32;

impl Process {
    /// 创建一个新的进程对象
    pub fn new() -> Arc<Self> {
        Arc::new(Process {
            base: KObjectBase::default(),
            inner: Mutex::new(ProcessInner {
                handles: BTreeMap::default(),
            }),
        })
    }
}

插入、删除句柄函数:

// src/task/process.rs
impl Process {
    /// 添加一个新的对象句柄
    pub fn add_handle(&self, handle: Handle) -> HandleValue {
        let mut inner = self.inner.lock();
        let value = (0 as HandleValue..)
            .find(|idx| !inner.handles.contains_key(idx))
            .unwrap();
        inner.handles.insert(value, handle);
        value
    }

    /// 删除一个对象句柄
    pub fn remove_handle(&self, handle_value: HandleValue) {
        self.inner.lock().handles.remove(&handle_value);
    }
}

定义内核错误及 Result 类型

// src/error.rs
/// Zircon statuses are signed 32 bit integers. The space of values is
/// divided as follows:
/// - The zero value is for the OK status.
/// - Negative values are defined by the system, in this file.
/// - Positive values are reserved for protocol-specific error values,
///   and will never be defined by the system.
#[allow(non_camel_case_types, dead_code)]
#[repr(i32)]
#[derive(Debug, Clone, Copy)]
pub enum ZxError {
    OK = 0,

    // ======= Internal failures =======
    /// The system encountered an otherwise unspecified error
    /// while performing the operation.
    INTERNAL = -1,

    /// The operation is not implemented, supported,
    /// or enabled.
    NOT_SUPPORTED = -2,

    // ......

    /// Connection was aborted.
    CONNECTION_ABORTED = -76,
}
// src/error.rs
///
pub type ZxResult<T> = Result<T, ZxError>;

根据句柄查找内核对象

实现 get_object_with_rights 等其它相关函数

实现 handle 单元测试

// src/task/process.rs
impl Process {
    /// 根据句柄值查找内核对象,并检查权限
    pub fn get_object_with_rights<T: KernelObject>(
        &self,
        handle_value: HandleValue,
        desired_rights: Rights,
    ) -> ZxResult<Arc<T>> {
        let handle = self
            .inner
            .lock()
            .handles
            .get(&handle_value)
            .ok_or(ZxError::BAD_HANDLE)?
            .clone();
        // check type before rights
        let object = handle
            .object
            .downcast_arc::<T>()
            .map_err(|_| ZxError::WRONG_TYPE)?;
        if !handle.rights.contains(desired_rights) {
            return Err(ZxError::ACCESS_DENIED);
        }
        Ok(object)
    }
}