Skip to content

Commit 47289c3

Browse files
committed
Support tracking skb clones
With --filter-track-skb option, we're able to track sbk by its address. Then, as for skb's clones/copies, we're able to track them too. We track the skb clones/copies by kprobing `__skb_clone()` and `skb_copy_header()`, whose callers include `skb_clone()` and `skb_copy()`. Signed-off-by: Leon Hwang <[email protected]>
1 parent 76019d2 commit 47289c3

2 files changed

Lines changed: 50 additions & 11 deletions

File tree

bpf/kprobe_pwru.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,28 @@ int kprobe_skb_lifetime_termination(struct pt_regs *ctx) {
344344

345345
bpf_map_delete_elem(&skb_addresses, &skb);
346346

347-
return 0;
347+
return BPF_OK;
348+
}
349+
350+
static __always_inline int
351+
track_skb_clone(struct pt_regs *ctx) {
352+
u64 new = (u64) PT_REGS_PARM1(ctx);
353+
u64 old = (u64) PT_REGS_PARM2(ctx);
354+
355+
if (bpf_map_lookup_elem(&skb_addresses, &old))
356+
bpf_map_update_elem(&skb_addresses, &new, &TRUE, BPF_ANY);
357+
358+
return BPF_OK;
359+
}
360+
361+
SEC("kprobe/__skb_clone")
362+
int kprobe___skb_clone(struct pt_regs *ctx) {
363+
return track_skb_clone(ctx);
364+
}
365+
366+
SEC("kprobe/skb_copy_header")
367+
int kprobe_skb_copy_header(struct pt_regs *ctx) {
368+
return track_skb_clone(ctx);
348369
}
349370

350371
SEC("fentry/tc")

main.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,10 @@ func main() {
121121
}
122122

123123
for name, program := range bpfSpec.Programs {
124-
if name == "kprobe_skb_lifetime_termination" {
124+
// Skip the skb-tracking ones that should not inject pcap-filter.
125+
if name == "kprobe_skb_lifetime_termination" ||
126+
name == "kprobe___skb_clone" ||
127+
name == "kprobe_skb_copy_header" {
125128
continue
126129
}
127130
if err = libpcap.InjectFilters(program, flags.FilterPcap); err != nil {
@@ -152,8 +155,12 @@ func main() {
152155
// deleted from the spec.
153156
delete(bpfSpec.Programs, "fentry_tc")
154157

158+
// If not tracking skb, deleting the skb-tracking programs to reduce loading
159+
// time.
155160
if !flags.FilterTrackSkb {
156161
delete(bpfSpec.Programs, "kprobe_skb_lifetime_termination")
162+
delete(bpfSpec.Programs, "kprobe___skb_clone")
163+
delete(bpfSpec.Programs, "kprobe_skb_copy_header")
157164
}
158165

159166
coll, err := ebpf.NewCollectionWithOptions(bpfSpec, opts)
@@ -216,17 +223,28 @@ func main() {
216223
bar := pb.StartNew(len(funcs))
217224

218225
if flags.FilterTrackSkb {
219-
kp, err := link.Kprobe("kfree_skbmem", coll.Programs["kprobe_skb_lifetime_termination"], nil)
220-
bar.Increment()
221-
if err != nil {
222-
if !errors.Is(err, os.ErrNotExist) {
223-
log.Fatalf("Opening kprobe kfree_skbmem: %s\n", err)
226+
progs := []struct {
227+
hook string
228+
prog *ebpf.Program
229+
hint string
230+
}{
231+
{"kfree_skbmem", coll.Programs["kprobe_skb_lifetime_termination"], "skb lifetime termination"},
232+
{"__skb_clone", coll.Programs["kprobe___skb_clone"], "skb clone tracking"},
233+
{"skb_copy_header", coll.Programs["kprobe_skb_copy_header"], "skb copy tracking"},
234+
}
235+
for _, prog := range progs {
236+
kp, err := link.Kprobe(prog.hook, prog.prog, nil)
237+
bar.Increment()
238+
if err != nil {
239+
if !errors.Is(err, os.ErrNotExist) {
240+
log.Fatalf("Opening kprobe %s: %s\n", prog.hook, err)
241+
} else {
242+
ignored += 1
243+
log.Printf("Warn: %s not found, pwru is likely to mismatch skb due to lack of %s\n", prog.hook, prog.hint)
244+
}
224245
} else {
225-
ignored += 1
226-
log.Printf("Warn: kfree_skbmem not found, pwru is likely to mismatch skb due to lack of skb lifetime management\n")
246+
kprobes = append(kprobes, kp)
227247
}
228-
} else {
229-
kprobes = append(kprobes, kp)
230248
}
231249
}
232250

0 commit comments

Comments
 (0)