bpf_feature/
runtime.rs

1//! Features available and configurable through procfs
2use 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}