mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-28 09:41:57 +00:00
90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
// +build linux
|
|
|
|
package elf
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"github.com/iovisor/gobpf/pkg/bpffs"
|
|
)
|
|
|
|
/*
|
|
#include <linux/unistd.h>
|
|
#include <linux/bpf.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
extern __u64 ptr_to_u64(void *);
|
|
|
|
int bpf_pin_object(int fd, const char *pathname)
|
|
{
|
|
union bpf_attr attr = {};
|
|
|
|
attr.pathname = ptr_to_u64((void *)pathname);
|
|
attr.bpf_fd = fd;
|
|
|
|
return syscall(__NR_bpf, BPF_OBJ_PIN, &attr, sizeof(attr));
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
const (
|
|
BPFDirGlobals = "globals" // as in iproute2's BPF_DIR_GLOBALS
|
|
BPFFSPath = "/sys/fs/bpf/"
|
|
)
|
|
|
|
func validPinPath(PinPath string) bool {
|
|
if !strings.HasPrefix(PinPath, BPFFSPath) {
|
|
return false
|
|
}
|
|
|
|
return filepath.Clean(PinPath) == PinPath
|
|
}
|
|
|
|
func pinObject(fd int, pinPath string) error {
|
|
mounted, err := bpffs.IsMounted()
|
|
if err != nil {
|
|
return fmt.Errorf("error checking if %q is mounted: %v", BPFFSPath, err)
|
|
}
|
|
if !mounted {
|
|
return fmt.Errorf("bpf fs not mounted at %q", BPFFSPath)
|
|
}
|
|
err = os.MkdirAll(filepath.Dir(pinPath), 0755)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating directory %q: %v", filepath.Dir(pinPath), err)
|
|
}
|
|
_, err = os.Stat(pinPath)
|
|
if err == nil {
|
|
return fmt.Errorf("aborting, found file at %q: %v", pinPath, err)
|
|
}
|
|
if err != nil && !os.IsNotExist(err) {
|
|
return fmt.Errorf("failed to stat %q: %v", pinPath, err)
|
|
}
|
|
pinPathC := C.CString(pinPath)
|
|
defer C.free(unsafe.Pointer(pinPathC))
|
|
ret, err := C.bpf_pin_object(C.int(fd), pinPathC)
|
|
if ret != 0 {
|
|
return fmt.Errorf("error pinning object to %q: %v", pinPath, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PinObjectGlobal pins and object to a name in a namespaces
|
|
// e.g. `/sys/fs/bpf/my-namespace/globals/my-name`
|
|
func PinObjectGlobal(fd int, namespace, name string) error {
|
|
pinPath := filepath.Join(BPFFSPath, namespace, BPFDirGlobals, name)
|
|
return pinObject(fd, pinPath)
|
|
}
|
|
|
|
// PinObject pins an object to a path
|
|
func PinObject(fd int, pinPath string) error {
|
|
if !validPinPath(pinPath) {
|
|
return fmt.Errorf("not a valid pin path: %s", pinPath)
|
|
}
|
|
return pinObject(fd, pinPath)
|
|
}
|