Skip to content

Commit

Permalink
refactor: Use cgroup_skb programs for payload inspection
Browse files Browse the repository at this point in the history
Before this change, we were using LSM programs attached to
`sock_recvmsg` and `sock_sendmsg` hooks for this purpose. We were
using `iov_iter` to read the payload.

Unfortunately, torvalds/linux@747b1f6 (which landed in kernel
6.4) broke the `iov_iter` API in completely backwards-incompatible
way, which can't be handled by any of CO-RE helpers while using
an `iov_iter` definition from any kernel.

Initially, we aimed to handle this incompatibility by
introducing a pre-6.4 compat header and trying to cast the types.
That seemed to work, but unfortunately, verifiers in 5.x kernels
are unhappy about this solution.

Therefore, this change drops the idea of intercepting payloads
with LSM all together and instead uses cgroup_skb for the same
purpose. There is no way `__sk_buff` is going to introduce
any breaking changes in regards to accessing the packet data.
  • Loading branch information
vadorovsky committed Nov 15, 2023
1 parent 6ddc920 commit 81c3372
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 168 deletions.
27 changes: 27 additions & 0 deletions crates/bpf-builder/include/buffer.bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,30 @@ static void buffer_append_user_memory(struct buffer *buffer,
index->len += len;
buffer->len += len;
}

static void buffer_append_skb_bytes(struct buffer *buffer,
struct buffer_index *index,
struct __sk_buff *skb,
__u32 offset, int len) {
int pos = (index->start + index->len);
if (pos >= HALF_BUFFER_MASK) {
LOG_ERROR("trying to write over half: %d+%d", index->start, index->len);
return;
}
if (len > HALF_BUFFER_MASK) {
len = HALF_BUFFER_MASK;
} else {
// include space for terminating 0
len = (len + 1) & HALF_BUFFER_MASK;
}

int r = bpf_skb_load_bytes(skb, offset, &((char*)buffer->buffer)[pos],
len & HALF_BUFFER_MASK);
if (r < 0) {
LOG_ERROR("reading failure: %d", r);
return;
}

index->len += len;
buffer->len += len;
}
36 changes: 35 additions & 1 deletion crates/bpf-common/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use aya::{
perf::{AsyncPerfEventArray, PerfBufferError},
Array, HashMap, Map, MapData,
},
programs::{KProbe, Lsm, RawTracePoint, TracePoint},
programs::{CgroupSkb, CgroupSkbAttachType, KProbe, Lsm, RawTracePoint, TracePoint},
util::online_cpus,
Bpf, BpfLoader, Btf, BtfError, Pod,
};
Expand Down Expand Up @@ -234,6 +234,18 @@ impl ProgramBuilder {
self
}

pub fn cgroup_skb_egress(mut self, name: &str) -> Self {
self.programs
.push(ProgramType::CgroupSkbEgress(name.to_string()));
self
}

pub fn cgroup_skb_ingress(mut self, name: &str) -> Self {
self.programs
.push(ProgramType::CgroupSkbIngress(name.to_string()));
self
}

pub async fn start(self) -> Result<Program, ProgramError> {
// We need to notify background tasks reading from maps that we're shutting down.
// We must use oneshot::Receiver as the main shut down machanism because it has
Expand Down Expand Up @@ -283,6 +295,8 @@ enum ProgramType {
Kprobe(String),
Kretprobe(String),
Lsm(String),
CgroupSkbEgress(String),
CgroupSkbIngress(String),
}

impl Display for ProgramType {
Expand All @@ -295,6 +309,10 @@ impl Display for ProgramType {
ProgramType::Kprobe(kprobe) => write!(f, "kprobe {kprobe}"),
ProgramType::Kretprobe(kretprobe) => write!(f, "kretprobe {kretprobe}"),
ProgramType::Lsm(lsm) => write!(f, "lsm {lsm}"),
ProgramType::CgroupSkbEgress(cgroup_skb) => write!(f, "cgroup_skb/egress {cgroup_skb}"),
ProgramType::CgroupSkbIngress(cgroup_skb) => {
write!(f, "cgroup_skb/ingress {cgroup_skb}")
}
}
}
}
Expand Down Expand Up @@ -330,6 +348,22 @@ impl ProgramType {
program.load(lsm, btf).map_err(load_err)?;
program.attach().map_err(attach_err)?;
}
ProgramType::CgroupSkbEgress(cgroup_skb) => {
let program: &mut CgroupSkb = extract_program(bpf, cgroup_skb)?;
let cgroup = std::fs::File::open("/sys/fs/cgroup").unwrap();
program.load().map_err(load_err)?;
program
.attach(cgroup, CgroupSkbAttachType::Egress)
.map_err(attach_err)?;
}
ProgramType::CgroupSkbIngress(cgroup_skb) => {
let program: &mut CgroupSkb = extract_program(bpf, cgroup_skb)?;
let cgroup = std::fs::File::open("/sys/fs/cgroup").unwrap();
program.load().map_err(load_err)?;
program
.attach(cgroup, CgroupSkbAttachType::Ingress)
.map_err(attach_err)?;
}
}
Ok(())
}
Expand Down
Loading

0 comments on commit 81c3372

Please sign in to comment.