Merge pull request #643 from aya-rs/procfs

Remove procfs dependency
reviewable/pr648/r1
Tamir Duberstein 1 year ago committed by GitHub
commit 6e9aba55fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -135,7 +135,7 @@ pub enum BtfError {
#[source] #[source]
io_error: std::io::Error, io_error: std::io::Error,
/// The error log produced by the kernel verifier. /// The error log produced by the kernel verifier.
verifier_log: Cow<'static, str>, verifier_log: String,
}, },
/// offset not found for symbol /// offset not found for symbol

@ -24,6 +24,7 @@ object = { version = "0.31", default-features = false, features = [
"elf", "elf",
] } ] }
parking_lot = { version = "0.12.0", features = ["send_guard"] } parking_lot = { version = "0.12.0", features = ["send_guard"] }
text_io = "0.1.12"
thiserror = "1" thiserror = "1"
tokio = { version = "1.24.0", features = [ tokio = { version = "1.24.0", features = [
"macros", "macros",
@ -31,7 +32,6 @@ tokio = { version = "1.24.0", features = [
"rt-multi-thread", "rt-multi-thread",
"net", "net",
], optional = true } ], optional = true }
procfs = { version = "0.15.1", default-features = false }
[dev-dependencies] [dev-dependencies]
futures = { version = "0.3.12", default-features = false, features = ["std"] } futures = { version = "0.3.12", default-features = false, features = ["std"] }

@ -47,9 +47,9 @@ use std::{
ptr, ptr,
}; };
use crate::util::KernelVersion;
use libc::{getrlimit, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; use libc::{getrlimit, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY};
use log::warn; use log::warn;
use procfs::KernelVersion;
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{

@ -1,6 +1,6 @@
//! Cgroup device programs. //! Cgroup device programs.
use procfs::KernelVersion; use crate::util::KernelVersion;
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsRawFd, RawFd};
use crate::{ use crate::{

@ -1,6 +1,6 @@
//! Cgroup skb programs. //! Cgroup skb programs.
use procfs::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},

@ -2,7 +2,7 @@
pub use aya_obj::programs::CgroupSockAttachType; pub use aya_obj::programs::CgroupSockAttachType;
use procfs::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},

@ -2,7 +2,7 @@
pub use aya_obj::programs::CgroupSockAddrAttachType; pub use aya_obj::programs::CgroupSockAddrAttachType;
use procfs::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},

@ -2,7 +2,7 @@
pub use aya_obj::programs::CgroupSockoptAttachType; pub use aya_obj::programs::CgroupSockoptAttachType;
use procfs::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},

@ -1,6 +1,6 @@
//! Cgroup sysctl programs. //! Cgroup sysctl programs.
use procfs::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},

@ -64,10 +64,9 @@ pub mod uprobe;
mod utils; mod utils;
pub mod xdp; pub mod xdp;
use crate::util::KernelVersion;
use libc::ENOSPC; use libc::ENOSPC;
use procfs::KernelVersion;
use std::{ use std::{
borrow::Cow,
ffi::CString, ffi::CString,
io, io,
os::unix::io::{AsRawFd, RawFd}, os::unix::io::{AsRawFd, RawFd},
@ -143,7 +142,7 @@ pub enum ProgramError {
#[source] #[source]
io_error: io::Error, io_error: io::Error,
/// The error log produced by the kernel verifier. /// The error log produced by the kernel verifier.
verifier_log: Cow<'static, str>, verifier_log: String,
}, },
/// A syscall failed. /// A syscall failed.

@ -1,5 +1,5 @@
use crate::util::KernelVersion;
use libc::pid_t; use libc::pid_t;
use procfs::KernelVersion;
use std::{ use std::{
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io::{self, Write}, io::{self, Write},
@ -50,7 +50,7 @@ pub(crate) fn attach<T: Link + From<PerfLinkInner>>(
) -> Result<T::Id, ProgramError> { ) -> Result<T::Id, ProgramError> {
// https://github.com/torvalds/linux/commit/e12f03d7031a977356e3d7b75a68c2185ff8d155 // https://github.com/torvalds/linux/commit/e12f03d7031a977356e3d7b75a68c2185ff8d155
// Use debugfs to create probe // Use debugfs to create probe
if KernelVersion::current().unwrap() >= KernelVersion::new(4, 17, 0) { if KernelVersion::current().unwrap() < KernelVersion::new(4, 17, 0) {
let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?; let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?;
let link = T::from(perf_attach_debugfs( let link = T::from(perf_attach_debugfs(
program_data.fd_or_err()?, program_data.fd_or_err()?,

@ -1,8 +1,8 @@
//! eXpress Data Path (XDP) programs. //! eXpress Data Path (XDP) programs.
use crate::util::KernelVersion;
use bitflags; use bitflags;
use libc::if_nametoindex; use libc::if_nametoindex;
use procfs::KernelVersion;
use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::unix::io::RawFd}; use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::unix::io::RawFd};
use thiserror::Error; use thiserror::Error;

@ -1,5 +1,4 @@
use std::{ use std::{
borrow::Cow,
cmp::{self, min}, cmp::{self, min},
ffi::{CStr, CString}, ffi::{CStr, CString},
io, io,
@ -8,12 +7,12 @@ use std::{
slice, slice,
}; };
use crate::util::KernelVersion;
use libc::{c_char, c_long, close, ENOENT, ENOSPC}; use libc::{c_char, c_long, close, ENOENT, ENOSPC};
use obj::{ use obj::{
maps::{bpf_map_def, LegacyMap}, maps::{bpf_map_def, LegacyMap},
BpfSectionKind, BpfSectionKind,
}; };
use procfs::KernelVersion;
use crate::{ use crate::{
generated::{ generated::{
@ -993,13 +992,10 @@ pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, (c_long, io::
} }
} }
pub(crate) fn retry_with_verifier_logs<F>( pub(crate) fn retry_with_verifier_logs(
max_retries: usize, max_retries: usize,
f: F, f: impl Fn(&mut [u8]) -> SysResult,
) -> (SysResult, Cow<'static, str>) ) -> (SysResult, String) {
where
F: Fn(&mut [u8]) -> SysResult,
{
const MIN_LOG_BUF_SIZE: usize = 1024 * 10; const MIN_LOG_BUF_SIZE: usize = 1024 * 10;
const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize; const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize;
@ -1023,11 +1019,7 @@ where
if let Some(pos) = log_buf.iter().position(|b| *b == 0) { if let Some(pos) = log_buf.iter().position(|b| *b == 0) {
log_buf.truncate(pos); log_buf.truncate(pos);
} }
let log_buf = if log_buf.is_empty() { let log_buf = String::from_utf8(log_buf).unwrap();
"none".into()
} else {
String::from_utf8(log_buf).unwrap().into()
};
break (ret, log_buf); break (ret, log_buf);
} }

@ -1,11 +1,12 @@
//! Utility functions. //! Utility functions.
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
ffi::CString, error::Error,
ffi::{CStr, CString},
fs::{self, File}, fs::{self, File},
io::{self, BufReader}, io::{self, BufRead, BufReader},
mem, slice, mem, slice,
str::FromStr, str::{FromStr, Utf8Error},
}; };
use crate::{ use crate::{
@ -13,9 +14,136 @@ use crate::{
Pod, Pod,
}; };
use libc::{if_nametoindex, sysconf, _SC_PAGESIZE}; use libc::{if_nametoindex, sysconf, uname, utsname, _SC_PAGESIZE};
use io::BufRead; /// Represents a kernel version, in major.minor.release version.
// Adapted from https://docs.rs/procfs/latest/procfs/sys/kernel/struct.Version.html.
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd)]
pub struct KernelVersion {
pub(crate) major: u8,
pub(crate) minor: u8,
pub(crate) patch: u16,
}
/// An error encountered while fetching the current kernel version.
#[derive(thiserror::Error, Debug)]
pub enum CurrentKernelVersionError {
/// The kernel version string could not be read.
#[error("failed to read kernel version")]
IOError(#[from] io::Error),
/// The kernel version string could not be parsed.
#[error("failed to parse kernel version")]
ParseError(#[from] text_io::Error),
/// The kernel version string was not valid UTF-8.
#[error("kernel version string is not valid UTF-8")]
Utf8Error(#[from] Utf8Error),
}
impl KernelVersion {
/// Constructor.
pub fn new(major: u8, minor: u8, patch: u16) -> Self {
Self {
major,
minor,
patch,
}
}
/// Returns the kernel version of the currently running kernel.
pub fn current() -> Result<Self, impl Error> {
let kernel_version = Self::get_kernel_version();
// The kernel version is clamped to 4.19.255 on kernels 4.19.222 and above.
//
// See https://github.com/torvalds/linux/commit/a256aac.
const CLAMPED_KERNEL_MAJOR: u8 = 4;
const CLAMPED_KERNEL_MINOR: u8 = 19;
if let Ok(Self {
major: CLAMPED_KERNEL_MAJOR,
minor: CLAMPED_KERNEL_MINOR,
patch: 222..,
}) = kernel_version
{
return Ok(Self::new(CLAMPED_KERNEL_MAJOR, CLAMPED_KERNEL_MINOR, 255));
}
kernel_version
}
// This is ported from https://github.com/torvalds/linux/blob/3f01e9f/tools/lib/bpf/libbpf_probes.c#L21-L101.
fn get_ubuntu_kernel_version() -> Result<Option<Self>, CurrentKernelVersionError> {
const UBUNTU_KVER_FILE: &str = "/proc/version_signature";
let s = match fs::read(UBUNTU_KVER_FILE) {
Ok(s) => s,
Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
return Ok(None);
}
return Err(e.into());
}
};
let ubuntu: String;
let ubuntu_version: String;
let major: u8;
let minor: u8;
let patch: u16;
text_io::try_scan!(s.iter().copied() => "{} {} {}.{}.{}\n", ubuntu, ubuntu_version, major, minor, patch);
Ok(Some(Self::new(major, minor, patch)))
}
fn get_debian_kernel_version(
info: &utsname,
) -> Result<Option<Self>, CurrentKernelVersionError> {
// Safety: man 2 uname:
//
// The length of the arrays in a struct utsname is unspecified (see NOTES); the fields are
// terminated by a null byte ('\0').
let p = unsafe { CStr::from_ptr(info.version.as_ptr()) };
let p = p.to_str()?;
let p = match p.split_once("Debian ") {
Some((_prefix, suffix)) => suffix,
None => return Ok(None),
};
let major: u8;
let minor: u8;
let patch: u16;
text_io::try_scan!(p.bytes() => "{}.{}.{}", major, minor, patch);
Ok(Some(Self::new(major, minor, patch)))
}
fn get_kernel_version() -> Result<Self, CurrentKernelVersionError> {
if let Some(v) = Self::get_ubuntu_kernel_version()? {
return Ok(v);
}
let mut info = unsafe { mem::zeroed::<utsname>() };
if unsafe { uname(&mut info) } != 0 {
return Err(io::Error::last_os_error().into());
}
if let Some(v) = Self::get_debian_kernel_version(&info)? {
return Ok(v);
}
// Safety: man 2 uname:
//
// The length of the arrays in a struct utsname is unspecified (see NOTES); the fields are
// terminated by a null byte ('\0').
let p = unsafe { CStr::from_ptr(info.release.as_ptr()) };
let p = p.to_str()?;
// Unlike sscanf, text_io::try_scan! does not stop at the first non-matching character.
let p = match p.split_once(|c: char| c != '.' && !c.is_ascii_digit()) {
Some((prefix, _suffix)) => prefix,
None => p,
};
let major: u8;
let minor: u8;
let patch: u16;
text_io::try_scan!(p.bytes() => "{}.{}.{}", major, minor, patch);
Ok(Self::new(major, minor, patch))
}
}
const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online"; const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online";
pub(crate) const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible"; pub(crate) const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible";

@ -12,7 +12,6 @@ aya-obj = { path = "../../aya-obj" }
libc = { version = "0.2.105" } libc = { version = "0.2.105" }
log = "0.4" log = "0.4"
object = { version = "0.31", default-features = false, features = ["std", "read_core", "elf"] } object = { version = "0.31", default-features = false, features = ["std", "read_core", "elf"] }
procfs = "0.15.1"
rbpf = "0.2.0" rbpf = "0.2.0"
tempfile = "3.3.0" tempfile = "3.3.0"
tokio = { version = "1.24", features = ["rt", "rt-multi-thread", "sync", "time"] } tokio = { version = "1.24", features = ["rt", "rt-multi-thread", "sync", "time"] }

@ -1,9 +1,8 @@
use anyhow::{bail, Context as _, Result}; use anyhow::{bail, Context as _, Result};
use procfs::KernelVersion;
use std::{path::PathBuf, process::Command, thread::sleep, time::Duration}; use std::{path::PathBuf, process::Command, thread::sleep, time::Duration};
use tempfile::TempDir; use tempfile::TempDir;
use aya::{maps::Array, programs::TracePoint, BpfLoader, Btf, Endianness}; use aya::{maps::Array, programs::TracePoint, util::KernelVersion, BpfLoader, Btf, Endianness};
// In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no // In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no
// special meaning, they just have "nice" bit patterns that can be helpful while debugging. // special meaning, they just have "nice" bit patterns that can be helpful while debugging.

@ -1,4 +1,3 @@
use procfs::KernelVersion;
use std::{convert::TryInto as _, thread, time}; use std::{convert::TryInto as _, thread, time};
use aya::{ use aya::{
@ -8,6 +7,7 @@ use aya::{
links::{FdLink, PinnedLink}, links::{FdLink, PinnedLink},
loaded_programs, KProbe, TracePoint, Xdp, XdpFlags, loaded_programs, KProbe, TracePoint, Xdp, XdpFlags,
}, },
util::KernelVersion,
Bpf, Bpf,
}; };

@ -1,8 +1,7 @@
use procfs::KernelVersion;
use aya::{ use aya::{
include_bytes_aligned, include_bytes_aligned,
programs::{Extension, Xdp, XdpFlags}, programs::{Extension, Xdp, XdpFlags},
util::KernelVersion,
Bpf, BpfLoader, Bpf, BpfLoader,
}; };

Loading…
Cancel
Save