kanit

Toy init system
Log | Files | Refs | README | LICENSE

sysfs.rs (3262B)


      1 use std::path::Path;
      2 
      3 use async_trait::async_trait;
      4 use blocking::unblock;
      5 use log::{info, warn};
      6 use nix::mount::{MsFlags, mount};
      7 
      8 use kanit_common::error::{Context, ErrorKind, Result, StaticError};
      9 use kanit_executor::join_all;
     10 use kanit_unit::{Dependencies, Unit};
     11 
     12 use crate::mounts::{is_fs_available, is_fs_mounted, try_mount_from_fstab};
     13 use crate::oneshot::ProcFs;
     14 use crate::unit_name;
     15 
     16 pub struct SysFs;
     17 
     18 async fn mount_misc_fs<P: AsRef<Path>>(path: P, name: &'static str) -> Result<()> {
     19     let path = path.as_ref().to_owned();
     20 
     21     if path.exists() && is_fs_available(name).await? && !is_fs_mounted(&path).await? {
     22         info!("mounting {name}");
     23 
     24         unblock(move || {
     25             mount(
     26                 Some("none"),
     27                 &path,
     28                 Some(name),
     29                 MsFlags::MS_NODEV | MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID,
     30                 Some(""),
     31             )
     32         })
     33         .await
     34         .with_context(move || format!("failed to mount {name}"))?;
     35     }
     36 
     37     Ok(())
     38 }
     39 
     40 impl SysFs {
     41     async fn mount_sys() -> Result<()> {
     42         // check if sysfs exists
     43         if !is_fs_available("sysfs").await? {
     44             Err(StaticError("failed to mount sysfs")).kind(ErrorKind::Unrecoverable)?;
     45         };
     46 
     47         // check if its mounted
     48         let path = Path::new("/sys");
     49 
     50         if is_fs_mounted(path).await? {
     51             return Ok(());
     52         }
     53 
     54         // create /sys if it doesn't exist
     55         if async_fs::metadata(path).await.is_err() {
     56             async_fs::create_dir(path)
     57                 .await
     58                 .context("failed to create /sys")?;
     59         }
     60 
     61         info!("mounting /sys");
     62 
     63         // try mount from fstab
     64         if try_mount_from_fstab(path).await? {
     65             return Ok(());
     66         }
     67 
     68         // mount with sysfs fs
     69         unblock(move || {
     70             mount(
     71                 Some("none"),
     72                 path,
     73                 Some("sysfs"),
     74                 MsFlags::MS_NODEV | MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID,
     75                 Some(""),
     76             )
     77         })
     78         .await
     79         .context("failed to mount sysfs")?;
     80 
     81         Ok(())
     82     }
     83 
     84     async fn mount_misc() -> Result<()> {
     85         join_all([
     86             mount_misc_fs("/sys/kernel/security", "securityfs"),
     87             mount_misc_fs("/sys/kernel/debug", "debugfs"),
     88             mount_misc_fs("/sys/kernel/config", "configfs"),
     89             mount_misc_fs("/sys/fs/fuse/connections", "fusectl"),
     90             mount_misc_fs("/sys/fs/pstore", "pstore"),
     91         ])
     92         .await
     93         .into_iter()
     94         .collect::<Result<Vec<_>>>()?;
     95 
     96         if Path::new("/sys/firmware/efi/efivars").exists()
     97             && mount_misc_fs("/sys/firmware/efi/efivars", "efivarfs")
     98                 .await
     99                 .is_err()
    100         {
    101             // efivarfs can be disabled in kernel parameters
    102             warn!("failed to mount efivarfs");
    103         }
    104 
    105         // TODO; SELinux
    106 
    107         Ok(())
    108     }
    109 }
    110 
    111 #[async_trait]
    112 impl Unit for SysFs {
    113     unit_name!("sysfs");
    114 
    115     fn dependencies(&self) -> Dependencies {
    116         Dependencies::new().need(ProcFs.name()).clone()
    117     }
    118 
    119     async fn start(&mut self) -> Result<()> {
    120         Self::mount_sys().await?;
    121         Self::mount_misc().await?;
    122 
    123         Ok(())
    124     }
    125 }