Rough solution for Tasks 1, 2, 3

main.go:

	- reading /proc
	- iteration over entries in NNN/maps
	- filter glob-search for "*python3*" in pathname
	- find symbol and its offset in pathnanme
	- calculate offset in memory
	- add pid and offset to map

	TODO: encapsulating this into a module

ebpf.go:

	- added type MapFD int, changing all function on a FD to methods
	  This allows us to enrich the data type going forward

	- added bpf_update_elem() from the manpage ebpf2.
	  .updateElement() is the verbatim wrapper to it.

	- added .Add/.Change/.Set methods, which call .updateElement
	  with specific flags

	TODO: re-implement ebpf.go with pure go, using direct syscalls.
This commit is contained in:
Özgür Kesim 2020-01-15 19:04:56 +01:00
parent 64f54c622d
commit a9f0f27ee2
2 changed files with 59 additions and 15 deletions

View File

@ -49,7 +49,17 @@ int bpf_lookup_elem(int fd, const void *key, void *value)
return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}
// TODO: add insert
int bpf_update_elem(int fd, const void *key, const void *value, uint64_t flags)
{
union bpf_attr attr = {
.map_fd = fd,
.key = (__u64) (unsigned long) key,
.value = (__u64) (unsigned long) value,
.flags = flags,
};
return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}
*/
import "C"
@ -59,18 +69,26 @@ import (
"unsafe"
)
type MapFD int
// CreateMap creates an eBPF map from int->uint64. The file descriptor of the
// created map is returned.
func CreateMap() (int, error) {
mapFD := C.bpf_create_map(C.BPF_MAP_TYPE_HASH, 4, 8, 64)
return int(mapFD), nil
func CreateMap() (MapFD, error) {
r, errno := C.bpf_create_map(C.BPF_MAP_TYPE_HASH, 4, 8, 64)
if r == -1 {
return MapFD(r), fmt.Errorf("bpf_create_map with errno %d", errno)
}
return MapFD(r), nil
}
// GetMap gets the key/value pairs from the specified eBPF map as a Go map
func GetMap(mapFD int) (map[int]uint64, error) {
func (mfd MapFD) GetMap() (map[int]uint64, error) {
retMap := make(map[int]uint64)
mapFDC := C.int(mapFD)
mapFDC := C.int(mfd)
keyC := C.int(0)
nextKeyC := C.int(0)
valC := C.uint64_t(0)
@ -94,3 +112,29 @@ func GetMap(mapFD int) (map[int]uint64, error) {
keyC = nextKeyC
}
}
func (mfd MapFD) Add(key int, value uint64) error {
return mfd.updateElement(key, value, C.BPF_NOEXIST)
}
func (mfd MapFD) Change(key int, value uint64) error {
return mfd.updateElement(key, value, C.BPF_EXIST)
}
func (mfd MapFD) Set(key int, value uint64) error {
return mfd.updateElement(key, value, C.BPF_ANY)
}
func (mfd MapFD) updateElement(key int, value uint64, flag C.uint64_t) error {
r, errno := C.bpf_update_elem(C.int(mfd),
unsafe.Pointer(&key),
unsafe.Pointer(&value),
flag)
if r == -1 {
return fmt.Errorf("bpf_update_elem failed with errno %d", errno)
}
return nil
}

View File

@ -56,11 +56,11 @@ func main() {
} else if offset, found := searchSymbolIn(pid_s, "*python3*", "_PyRuntime"); !found {
continue
} else {
fmt.Printf("going to set (%d -> 0x%x)\n\n", pid, offset)
mapFD.Add(pid, uint64(offset))
}
}
mapContents, err := ebpf.GetMap(mapFD)
mapContents, err := mapFD.GetMap()
if err != nil {
fmt.Printf("Failed to get the map contents: %s", err)
os.Exit(1)
@ -161,7 +161,7 @@ func searchSymbolIn(pid, glob, symbol string) (offset uint64, ok bool) {
memoff := sym.Value - section.Addr + alignedOffset(section)
fmt.Printf("pid: %s\nsym: %#v\nsection: %#v\nmemoff: 0x%x\narange: %#v\nmap-fileoffset: 0x%x\npathname: %s\n", pid, sym, section, memoff, arange, fileoffset, pathname)
// fmt.Printf("pid: %s\nsym: %#v\nsection: %#v\nmemoff: 0x%x\narange: %#v\nmap-fileoffset: 0x%x\npathname: %s\n", pid, sym, section, memoff, arange, fileoffset, pathname)
// stop when only _one_ is found
return arange.start + memoff - fileoffset, true