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 }