From 9db7afd7200f19bb6e3eabd3c02345d07e1f27e1 Mon Sep 17 00:00:00 2001 From: Devidas Jadhav Date: Sat, 7 Sep 2019 21:29:25 +0530 Subject: [PATCH 1/2] Added Quick versions of AttachKprobe and AttchaKretProbe. --- bcc/module.go | 24 +++++ examples/bcc/quick_perf/.gitignore | 1 + examples/bcc/quick_perf/quick_perf.go | 136 ++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 examples/bcc/quick_perf/.gitignore create mode 100644 examples/bcc/quick_perf/quick_perf.go diff --git a/bcc/module.go b/bcc/module.go index 34a40e49..fcd1a405 100644 --- a/bcc/module.go +++ b/bcc/module.go @@ -269,6 +269,30 @@ func (bpf *Module) attachUProbe(evName string, attachType uint32, path string, a return nil } +// QuickAttachKprobe attaches a kprobe fd to a function. +func (bpf *Module) QuickAttachKretprobe(fnName string, maxActive int) error { + krName := "kretprobe__" + fnName + evName := "r_" + kprobeRegexp.ReplaceAllString(fnName, "_") + fd, err := bpf.LoadKprobe(krName) + if err != nil { + return err + } + + return bpf.attachProbe(evName, BPF_PROBE_RETURN, fnName, fd, maxActive) +} + +// QuickAttachKprobe attaches a kprobe fd to a function. +func (bpf *Module) QuickAttachKprobe(fnName string, maxActive int) error { + kpName := "kprobe__" + fnName + evName := "p_" + kprobeRegexp.ReplaceAllString(fnName, "_") + fd, err := bpf.LoadKprobe(kpName) + if err != nil { + return err + } + + return bpf.attachProbe(evName, BPF_PROBE_ENTRY, fnName, fd, maxActive) +} + // AttachKprobe attaches a kprobe fd to a function. func (bpf *Module) AttachKprobe(fnName string, fd int, maxActive int) error { evName := "p_" + kprobeRegexp.ReplaceAllString(fnName, "_") diff --git a/examples/bcc/quick_perf/.gitignore b/examples/bcc/quick_perf/.gitignore new file mode 100644 index 00000000..bd14107d --- /dev/null +++ b/examples/bcc/quick_perf/.gitignore @@ -0,0 +1 @@ +perf diff --git a/examples/bcc/quick_perf/quick_perf.go b/examples/bcc/quick_perf/quick_perf.go new file mode 100644 index 00000000..acb7e249 --- /dev/null +++ b/examples/bcc/quick_perf/quick_perf.go @@ -0,0 +1,136 @@ +// Copyright 2016 Kinvolk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "encoding/binary" + "fmt" + "os" + "os/signal" + "unsafe" + + bpf "github.com/iovisor/gobpf/bcc" +) + +import "C" + +const source string = ` +#include +#include + +typedef struct { + u32 pid; + uid_t uid; + gid_t gid; + int ret; + char filename[256]; +} chown_event_t; + +BPF_PERF_OUTPUT(chown_events); +BPF_HASH(chowncall, u64, chown_event_t); + +int kprobe__sys_fchownat(struct pt_regs *ctx, int dfd, const char *filename, + uid_t uid, gid_t gid, int flag) +{ + u64 pid = bpf_get_current_pid_tgid(); + chown_event_t event = { + .pid = pid >> 32, + .uid = uid, + .gid = gid, + }; + bpf_probe_read(&event.filename, sizeof(event.filename), (void *)filename); + chowncall.update(&pid, &event); + return 0; +} + +int kretprobe__sys_fchownat(struct pt_regs *ctx) +{ + int ret = PT_REGS_RC(ctx); + u64 pid = bpf_get_current_pid_tgid(); + chown_event_t *eventp = chowncall.lookup(&pid); + if (eventp == 0) { + return 0; + } + chown_event_t event = *eventp; + event.ret = ret; + chown_events.perf_submit(ctx, &event, sizeof(event)); + chowncall.delete(&pid); + return 0; +}; +` + +type chownEvent struct { + Pid uint32 + Uid uint32 + Gid uint32 + ReturnValue int32 + Filename [256]byte +} + +func main() { + m := bpf.NewModule(source, []string{}) + defer m.Close() + + syscallName := bpf.GetSyscallFnName("fchownat") + + // passing -1 for maxActive signifies to use the default + // according to the kernel kprobes documentation + err := m.QuickAttachKprobe(syscallName, -1) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to attach kprobe__sys_fchownat: %s\n", err) + os.Exit(1) + } + + // passing -1 for maxActive signifies to use the default + // according to the kernel kretprobes documentation + err = m.QuickAttachKretprobe(syscallName, -1) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to attach kretprobe__sys_fchownat: %s\n", err) + os.Exit(1) + } + + table := bpf.NewTable(m.TableId("chown_events"), m) + + channel := make(chan []byte) + + perfMap, err := bpf.InitPerfMap(table, channel) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to init perf map: %s\n", err) + os.Exit(1) + } + + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt, os.Kill) + + go func() { + var event chownEvent + for { + data := <-channel + err := binary.Read(bytes.NewBuffer(data), binary.LittleEndian, &event) + if err != nil { + fmt.Printf("failed to decode received data: %s\n", err) + continue + } + filename := (*C.char)(unsafe.Pointer(&event.Filename)) + fmt.Printf("uid %d gid %d pid %d called fchownat(2) on %s (return value: %d)\n", + event.Uid, event.Gid, event.Pid, C.GoString(filename), event.ReturnValue) + } + }() + + perfMap.Start() + <-sig + perfMap.Stop() +} From 6c2ed14a4f165ed587ca57ad7c1d49726776d722 Mon Sep 17 00:00:00 2001 From: Devidas Jadhav Date: Sat, 7 Sep 2019 21:38:42 +0530 Subject: [PATCH 2/2] added typo in comment --- bcc/module.go | 4 ++-- examples/bcc/quick_perf/.gitignore | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bcc/module.go b/bcc/module.go index fcd1a405..fb7040e4 100644 --- a/bcc/module.go +++ b/bcc/module.go @@ -269,7 +269,7 @@ func (bpf *Module) attachUProbe(evName string, attachType uint32, path string, a return nil } -// QuickAttachKprobe attaches a kprobe fd to a function. +// QuickAttachKretprobe attaches a kretprobe to a function. func (bpf *Module) QuickAttachKretprobe(fnName string, maxActive int) error { krName := "kretprobe__" + fnName evName := "r_" + kprobeRegexp.ReplaceAllString(fnName, "_") @@ -281,7 +281,7 @@ func (bpf *Module) QuickAttachKretprobe(fnName string, maxActive int) error { return bpf.attachProbe(evName, BPF_PROBE_RETURN, fnName, fd, maxActive) } -// QuickAttachKprobe attaches a kprobe fd to a function. +// QuickAttachKprobe attaches a kprobe to a function. func (bpf *Module) QuickAttachKprobe(fnName string, maxActive int) error { kpName := "kprobe__" + fnName evName := "p_" + kprobeRegexp.ReplaceAllString(fnName, "_") diff --git a/examples/bcc/quick_perf/.gitignore b/examples/bcc/quick_perf/.gitignore index bd14107d..a23bc987 100644 --- a/examples/bcc/quick_perf/.gitignore +++ b/examples/bcc/quick_perf/.gitignore @@ -1 +1 @@ -perf +quick_perf