1use nix::sys::statfs::{statfs, PROC_SUPER_MAGIC};
3use std::path::Path;
4use thiserror::Error as ThisError;
5
6#[cfg(feature = "serde")]
7use crate::serde_ext;
8#[cfg(feature = "serde")]
9use bpf_rs_macros::SerializeFromDisplay;
10#[cfg(feature = "serde")]
11use serde::Serialize;
12
13#[non_exhaustive]
14#[derive(ThisError, Debug)]
15#[cfg_attr(feature = "serde", derive(SerializeFromDisplay))]
16pub enum RuntimeError {
17 #[error("procfs at /proc was not detected")]
18 ProcfsNonExistent,
19 #[error("parse failure: {0}")]
20 ParseIntError(#[from] std::num::ParseIntError),
21 #[error("io: {0}")]
22 IO(#[from] std::io::Error),
23}
24
25type ProcfsResult = Result<usize, RuntimeError>;
26
27#[derive(Debug)]
28#[cfg_attr(feature = "serde", derive(Serialize))]
29pub struct Runtime {
30 #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
31 pub unprivileged_disabled: ProcfsResult,
32 #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
33 pub jit_enable: ProcfsResult,
34 #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
35 pub jit_harden: ProcfsResult,
36 #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
37 pub jit_kallsyms: ProcfsResult,
38 #[cfg_attr(feature = "serde", serde(serialize_with = "serde_ext::flatten_result"))]
39 pub jit_limit: ProcfsResult,
40}
41
42impl Runtime {
43 fn verify_procfs_exists() -> Result<(), RuntimeError> {
44 match statfs("/proc") {
45 Err(_) => Err(RuntimeError::ProcfsNonExistent),
46 Ok(stat) => {
47 if stat.filesystem_type() != PROC_SUPER_MAGIC {
48 Err(RuntimeError::ProcfsNonExistent)
49 } else {
50 Ok(())
51 }
52 }
53 }
54 }
55
56 fn procfs_read(path: &Path) -> ProcfsResult {
57 Ok(std::fs::read_to_string(path)?.trim().parse()?)
58 }
59}
60
61pub fn features() -> Result<Runtime, RuntimeError> {
62 Runtime::verify_procfs_exists()?;
63
64 Ok(Runtime {
65 unprivileged_disabled: Runtime::procfs_read(Path::new(
66 "/proc/sys/kernel/unprivileged_bpf_disabled",
67 )),
68 jit_enable: Runtime::procfs_read(Path::new("/proc/sys/net/core/bpf_jit_enable")),
69 jit_harden: Runtime::procfs_read(Path::new("/proc/sys/net/core/bpf_jit_harden")),
70 jit_kallsyms: Runtime::procfs_read(Path::new("/proc/sys/net/core/bpf_jit_kallsyms")),
71 jit_limit: Runtime::procfs_read(Path::new("/proc/sys/net/core/bpf_jit_limit")),
72 })
73}