use OwnedFd for object BTF file

this actually fixes a file descriptor leak since we were never closing it
reviewable/pr614/r6
Andrés Medina 2 years ago
parent 18ea23fff8
commit d3e6d9066f

@ -4,9 +4,8 @@ use std::{
ffi::CString, ffi::CString,
fs, io, fs, io,
os::{ os::{
fd::{AsFd, AsRawFd}, fd::{AsFd, AsRawFd, OwnedFd},
raw::c_int, raw::c_int,
unix::io::RawFd,
}, },
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -368,6 +367,9 @@ impl<'a> BpfLoader<'a> {
None None
}; };
// TODO (AM)
let raw_btf_fd = btf_fd.as_ref().map(|f| f.as_raw_fd());
if let Some(btf) = &self.btf { if let Some(btf) = &self.btf {
obj.relocate_btf(btf)?; obj.relocate_btf(btf)?;
} }
@ -400,7 +402,7 @@ impl<'a> BpfLoader<'a> {
obj, obj,
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd, btf_fd: raw_btf_fd,
}; };
match map.obj.pinning() { match map.obj.pinning() {
PinningType::ByName => { PinningType::ByName => {
@ -479,70 +481,90 @@ impl<'a> BpfLoader<'a> {
let program = if self.extensions.contains(name.as_str()) { let program = if self.extensions.contains(name.as_str()) {
Program::Extension(Extension { Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}) })
} else { } else {
match &section { match &section {
ProgramSection::KProbe { .. } => Program::KProbe(KProbe { ProgramSection::KProbe { .. } => Program::KProbe(KProbe {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
kind: ProbeKind::KProbe, kind: ProbeKind::KProbe,
}), }),
ProgramSection::KRetProbe { .. } => Program::KProbe(KProbe { ProgramSection::KRetProbe { .. } => Program::KProbe(KProbe {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
kind: ProbeKind::KRetProbe, kind: ProbeKind::KRetProbe,
}), }),
ProgramSection::UProbe { .. } => Program::UProbe(UProbe { ProgramSection::UProbe { .. } => Program::UProbe(UProbe {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
kind: ProbeKind::UProbe, kind: ProbeKind::UProbe,
}), }),
ProgramSection::URetProbe { .. } => Program::UProbe(UProbe { ProgramSection::URetProbe { .. } => Program::UProbe(UProbe {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
kind: ProbeKind::URetProbe, kind: ProbeKind::URetProbe,
}), }),
ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint { ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::SocketFilter { .. } => { ProgramSection::SocketFilter { .. } => {
Program::SocketFilter(SocketFilter { Program::SocketFilter(SocketFilter {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
}) })
} }
ProgramSection::Xdp { frags, .. } => { ProgramSection::Xdp { frags, .. } => {
let mut data = let mut data =
ProgramData::new(prog_name, obj, btf_fd, verifier_log_level); ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level);
if *frags { if *frags {
data.flags = BPF_F_XDP_HAS_FRAGS; data.flags = BPF_F_XDP_HAS_FRAGS;
} }
Program::Xdp(Xdp { data }) Program::Xdp(Xdp { data })
} }
ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg { ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::CgroupSysctl { .. } => { ProgramSection::CgroupSysctl { .. } => {
Program::CgroupSysctl(CgroupSysctl { Program::CgroupSysctl(CgroupSysctl {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
}) })
} }
ProgramSection::CgroupSockopt { attach_type, .. } => { ProgramSection::CgroupSockopt { attach_type, .. } => {
Program::CgroupSockopt(CgroupSockopt { Program::CgroupSockopt(CgroupSockopt {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
attach_type: *attach_type, attach_type: *attach_type,
}) })
} }
ProgramSection::SkSkbStreamParser { .. } => Program::SkSkb(SkSkb { ProgramSection::SkSkbStreamParser { .. } => Program::SkSkb(SkSkb {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
kind: SkSkbKind::StreamParser, kind: SkSkbKind::StreamParser,
}), }),
ProgramSection::SkSkbStreamVerdict { .. } => Program::SkSkb(SkSkb { ProgramSection::SkSkbStreamVerdict { .. } => Program::SkSkb(SkSkb {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
kind: SkSkbKind::StreamVerdict, kind: SkSkbKind::StreamVerdict,
}), }),
ProgramSection::SockOps { .. } => Program::SockOps(SockOps { ProgramSection::SockOps { .. } => Program::SockOps(SockOps {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::SchedClassifier { .. } => { ProgramSection::SchedClassifier { .. } => {
Program::SchedClassifier(SchedClassifier { Program::SchedClassifier(SchedClassifier {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
name: unsafe { name: unsafe {
CString::from_vec_unchecked(Vec::from(name.clone())) CString::from_vec_unchecked(Vec::from(name.clone()))
.into_boxed_c_str() .into_boxed_c_str()
@ -550,37 +572,47 @@ impl<'a> BpfLoader<'a> {
}) })
} }
ProgramSection::CgroupSkb { .. } => Program::CgroupSkb(CgroupSkb { ProgramSection::CgroupSkb { .. } => Program::CgroupSkb(CgroupSkb {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
expected_attach_type: None, expected_attach_type: None,
}), }),
ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb { ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
expected_attach_type: Some(CgroupSkbAttachType::Ingress), expected_attach_type: Some(CgroupSkbAttachType::Ingress),
}), }),
ProgramSection::CgroupSkbEgress { .. } => Program::CgroupSkb(CgroupSkb { ProgramSection::CgroupSkbEgress { .. } => Program::CgroupSkb(CgroupSkb {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
expected_attach_type: Some(CgroupSkbAttachType::Egress), expected_attach_type: Some(CgroupSkbAttachType::Egress),
}), }),
ProgramSection::CgroupSockAddr { attach_type, .. } => { ProgramSection::CgroupSockAddr { attach_type, .. } => {
Program::CgroupSockAddr(CgroupSockAddr { Program::CgroupSockAddr(CgroupSockAddr {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
attach_type: *attach_type, attach_type: *attach_type,
}) })
} }
ProgramSection::LircMode2 { .. } => Program::LircMode2(LircMode2 { ProgramSection::LircMode2 { .. } => Program::LircMode2(LircMode2 {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::PerfEvent { .. } => Program::PerfEvent(PerfEvent { ProgramSection::PerfEvent { .. } => Program::PerfEvent(PerfEvent {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::RawTracePoint { .. } => { ProgramSection::RawTracePoint { .. } => {
Program::RawTracePoint(RawTracePoint { Program::RawTracePoint(RawTracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
}) })
} }
ProgramSection::Lsm { sleepable, .. } => { ProgramSection::Lsm { sleepable, .. } => {
let mut data = let mut data =
ProgramData::new(prog_name, obj, btf_fd, verifier_log_level); ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level);
if *sleepable { if *sleepable {
data.flags = BPF_F_SLEEPABLE; data.flags = BPF_F_SLEEPABLE;
} }
@ -588,30 +620,45 @@ impl<'a> BpfLoader<'a> {
} }
ProgramSection::BtfTracePoint { .. } => { ProgramSection::BtfTracePoint { .. } => {
Program::BtfTracePoint(BtfTracePoint { Program::BtfTracePoint(BtfTracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
}) })
} }
ProgramSection::FEntry { .. } => Program::FEntry(FEntry { ProgramSection::FEntry { .. } => Program::FEntry(FEntry {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::FExit { .. } => Program::FExit(FExit { ProgramSection::FExit { .. } => Program::FExit(FExit {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::Extension { .. } => Program::Extension(Extension { ProgramSection::Extension { .. } => Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::SkLookup { .. } => Program::SkLookup(SkLookup { ProgramSection::SkLookup { .. } => Program::SkLookup(SkLookup {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, raw_btf_fd, verifier_log_level),
}), }),
ProgramSection::CgroupSock { attach_type, .. } => { ProgramSection::CgroupSock { attach_type, .. } => {
Program::CgroupSock(CgroupSock { Program::CgroupSock(CgroupSock {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
attach_type: *attach_type, attach_type: *attach_type,
}) })
} }
ProgramSection::CgroupDevice { .. } => { ProgramSection::CgroupDevice { .. } => {
Program::CgroupDevice(CgroupDevice { Program::CgroupDevice(CgroupDevice {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(
prog_name,
obj,
raw_btf_fd,
verifier_log_level,
),
}) })
} }
} }
@ -624,6 +671,7 @@ impl<'a> BpfLoader<'a> {
Ok(Bpf { Ok(Bpf {
maps: maps?, maps: maps?,
programs, programs,
_btf_fd: btf_fd,
}) })
} }
} }
@ -670,6 +718,7 @@ impl<'a> Default for BpfLoader<'a> {
pub struct Bpf { pub struct Bpf {
maps: HashMap<String, Map>, maps: HashMap<String, Map>,
programs: HashMap<String, Program>, programs: HashMap<String, Program>,
_btf_fd: Option<OwnedFd>,
} }
impl Bpf { impl Bpf {
@ -917,24 +966,21 @@ pub enum BpfError {
ProgramError(#[from] ProgramError), ProgramError(#[from] ProgramError),
} }
fn load_btf(raw_btf: Vec<u8>) -> Result<RawFd, BtfError> { fn load_btf(raw_btf: Vec<u8>) -> Result<OwnedFd, BtfError> {
let mut logger = VerifierLog::new(); let mut logger = VerifierLog::new();
let ret = retry_with_verifier_logs(10, &mut logger, |logger| { retry_with_verifier_logs(10, &mut logger, |logger| {
bpf_load_btf(raw_btf.as_slice(), logger) bpf_load_btf(raw_btf.as_slice(), logger)
}); })
match ret { .map_err(|(_, io_error)| {
Ok(fd) => Ok(fd as RawFd), logger.truncate();
Err((_, io_error)) => { BtfError::LoadError {
logger.truncate(); io_error,
Err(BtfError::LoadError { verifier_log: logger
io_error, .as_c_str()
verifier_log: logger .map(|s| s.to_string_lossy().to_string())
.as_c_str() .unwrap_or_else(|| "[none]".to_owned()),
.map(|s| s.to_string_lossy().to_string())
.unwrap_or_else(|| "[none]".to_owned()),
})
} }
} })
} }
/// Global data that can be exported to eBPF programs before they are loaded. /// Global data that can be exported to eBPF programs before they are loaded.

@ -563,7 +563,7 @@ pub(crate) fn bpf_raw_tracepoint_open(
Ok(unsafe { OwnedFd::from_raw_fd(fd) }) Ok(unsafe { OwnedFd::from_raw_fd(fd) })
} }
pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> SysResult { pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 }; let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = raw_btf.as_ptr() as *const _ as u64; u.btf = raw_btf.as_ptr() as *const _ as u64;
@ -574,7 +574,9 @@ pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> SysResult {
u.btf_log_buf = log_buf.as_mut_ptr() as u64; u.btf_log_buf = log_buf.as_mut_ptr() as u64;
u.btf_log_size = log_buf.capacity() as u32; u.btf_log_size = log_buf.capacity() as u32;
} }
sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) let fd = sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr)? as RawFd;
// SAFETY: BPF_BTF_LOAD returns a new fd
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
} }
pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> io::Result<RawFd> { pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> io::Result<RawFd> {

Loading…
Cancel
Save