blob: 5a67622d41f0b38ec470349ac6cfe046985535ce [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fuchsia_zircon::{self as zx, AsHandleRef};
use once_cell::sync::OnceCell;
use std::collections::HashSet;
use std::ffi::CStr;
use std::iter::FromIterator;
use std::sync::Arc;
use crate::device::{DeviceMode, DeviceRegistry};
use crate::fs::socket::SocketAddress;
use crate::fs::{FileOps, FileSystemHandle, FsNode};
use crate::lock::RwLock;
use crate::task::*;
use crate::types::{DeviceType, Errno, OpenFlags};
#[cfg(test)]
use std::ffi::CString;
pub struct Kernel {
/// The Zircon job object that holds the processes running in this kernel.
pub job: zx::Job,
/// The processes and threads running in this kernel, organized by pid_t.
pub pids: RwLock<PidTable>,
/// The default namespace for abstract AF_UNIX sockets in this kernel.
///
/// Rather than use this default namespace, abstract socket addresses
/// should be looked up in the AbstractSocketNamespace on each Task
/// object because some Task objects might have a non-default namespace.
pub default_abstract_socket_namespace: Arc<AbstractUnixSocketNamespace>,
/// The default namespace for abstract AF_VSOCK sockets in this kernel.
pub default_abstract_vsock_namespace: Arc<AbstractVsockSocketNamespace>,
/// The kernel command line. Shows up in /proc/cmdline.
pub cmdline: Vec<u8>,
// Owned by anon_node.rs
pub anon_fs: OnceCell<FileSystemHandle>,
// Owned by pipe.rs
pub pipe_fs: OnceCell<FileSystemHandle>,
/// Owned by socket.rs
pub socket_fs: OnceCell<FileSystemHandle>,
// Owned by devtmpfs.rs
pub dev_tmp_fs: OnceCell<FileSystemHandle>,
// Owned by devpts.rs
pub dev_pts_fs: OnceCell<FileSystemHandle>,
// Owned by procfs.rs
pub proc_fs: OnceCell<FileSystemHandle>,
// Owned by sysfs.rs
pub sys_fs: OnceCell<FileSystemHandle>,
// Owned by selinux.rs
pub selinux_fs: OnceCell<FileSystemHandle>,
/// The registry of device drivers.
pub device_registry: RwLock<DeviceRegistry>,
// The features enabled for the galaxy this kernel is associated with, as specified in
// the galaxy's configuration file.
pub features: HashSet<String>,
}
impl Kernel {
pub fn new(name: &CStr, features: &Vec<String>) -> Result<Kernel, zx::Status> {
let unix_address_maker = Box::new(|x: Vec<u8>| -> SocketAddress { SocketAddress::Unix(x) });
let vsock_address_maker = Box::new(|x: u32| -> SocketAddress { SocketAddress::Vsock(x) });
let job = fuchsia_runtime::job_default().create_child_job()?;
job.set_name(&name)?;
Ok(Kernel {
job,
pids: RwLock::new(PidTable::new()),
default_abstract_socket_namespace: AbstractUnixSocketNamespace::new(unix_address_maker),
default_abstract_vsock_namespace: AbstractVsockSocketNamespace::new(
vsock_address_maker,
),
cmdline: Vec::new(),
anon_fs: OnceCell::new(),
pipe_fs: OnceCell::new(),
dev_tmp_fs: OnceCell::new(),
dev_pts_fs: OnceCell::new(),
proc_fs: OnceCell::new(),
socket_fs: OnceCell::new(),
sys_fs: OnceCell::new(),
selinux_fs: OnceCell::new(),
device_registry: RwLock::new(DeviceRegistry::new_with_common_devices()),
features: HashSet::from_iter(features.iter().cloned()),
})
}
#[cfg(test)]
pub fn new_for_testing() -> Arc<Kernel> {
Arc::new(
Self::new(&CString::new("testing").unwrap(), &Vec::new())
.expect("Failed to create test kernel."),
)
}
/// Opens a device file (driver) identified by `dev`.
pub fn open_device(
&self,
current_task: &CurrentTask,
node: &FsNode,
flags: OpenFlags,
dev: DeviceType,
mode: DeviceMode,
) -> Result<Box<dyn FileOps>, Errno> {
let registry = self.device_registry.read();
registry.open_device(current_task, node, flags, dev, mode)
}
pub fn selinux_enabled(&self) -> bool {
self.features.contains("selinux_enabled")
}
}