delve/vendor/github.com/aquasecurity/libbpfgo/helpers/kernel_features.go
2021-07-31 17:16:26 +02:00

229 lines
7.5 KiB
Go

package helpers
import (
"bufio"
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"os"
"strings"
"golang.org/x/sys/unix"
)
// These constants are a limited number of the total kernel config options,
// but are provided because they are most relevant for BPF
// development.
const (
CONFIG_BPF uint32 = iota + 1
CONFIG_BPF_SYSCALL
CONFIG_HAVE_EBPF_JIT
CONFIG_BPF_JIT
CONFIG_BPF_JIT_ALWAYS_ON
CONFIG_CGROUPS
CONFIG_CGROUP_BPF
CONFIG_CGROUP_NET_CLASSID
CONFIG_SOCK_CGROUP_DATA
CONFIG_BPF_EVENTS
CONFIG_KPROBE_EVENTS
CONFIG_UPROBE_EVENTS
CONFIG_TRACING
CONFIG_FTRACE_SYSCALLS
CONFIG_FUNCTION_ERROR_INJECTION
CONFIG_BPF_KPROBE_OVERRIDE
CONFIG_NET
CONFIG_XDP_SOCKETS
CONFIG_LWTUNNEL_BPF
CONFIG_NET_ACT_BPF
CONFIG_NET_CLS_BPF
CONFIG_NET_CLS_ACT
CONFIG_NET_SCH_INGRESS
CONFIG_XFRM
CONFIG_IP_ROUTE_CLASSID
CONFIG_IPV6_SEG6_BPF
CONFIG_BPF_LIRC_MODE2
CONFIG_BPF_STREAM_PARSER
CONFIG_NETFILTER_XT_MATCH_BPF
CONFIG_BPFILTER
CONFIG_BPFILTER_UMH
CONFIG_TEST_BPF
CONFIG_HZ
CONFIG_DEBUG_INFO_BTF
CONFIG_DEBUG_INFO_BTF_MODULES
CONFIG_BPF_LSM
CONFIG_BPF_PRELOAD
CONFIG_BPF_PRELOAD_UMD
)
var KernelConfigKeyStringToID map[string]uint32 = map[string]uint32{
"CONFIG_BPF": CONFIG_BPF,
"CONFIG_BPF_SYSCALL": CONFIG_BPF_SYSCALL,
"CONFIG_HAVE_EBPF_JIT": CONFIG_HAVE_EBPF_JIT,
"CONFIG_BPF_JIT": CONFIG_BPF_JIT,
"CONFIG_BPF_JIT_ALWAYS_ON": CONFIG_BPF_JIT_ALWAYS_ON,
"CONFIG_CGROUPS": CONFIG_CGROUPS,
"CONFIG_CGROUP_BPF": CONFIG_CGROUP_BPF,
"CONFIG_CGROUP_NET_CLASSID": CONFIG_CGROUP_NET_CLASSID,
"CONFIG_SOCK_CGROUP_DATA": CONFIG_SOCK_CGROUP_DATA,
"CONFIG_BPF_EVENTS": CONFIG_BPF_EVENTS,
"CONFIG_KPROBE_EVENTS": CONFIG_KPROBE_EVENTS,
"CONFIG_UPROBE_EVENTS": CONFIG_UPROBE_EVENTS,
"CONFIG_TRACING": CONFIG_TRACING,
"CONFIG_FTRACE_SYSCALLS": CONFIG_FTRACE_SYSCALLS,
"CONFIG_FUNCTION_ERROR_INJECTION": CONFIG_FUNCTION_ERROR_INJECTION,
"CONFIG_BPF_KPROBE_OVERRIDE": CONFIG_BPF_KPROBE_OVERRIDE,
"CONFIG_NET": CONFIG_NET,
"CONFIG_XDP_SOCKETS": CONFIG_XDP_SOCKETS,
"CONFIG_LWTUNNEL_BPF": CONFIG_LWTUNNEL_BPF,
"CONFIG_NET_ACT_BPF": CONFIG_NET_ACT_BPF,
"CONFIG_NET_CLS_BPF": CONFIG_NET_CLS_BPF,
"CONFIG_NET_CLS_ACT": CONFIG_NET_CLS_ACT,
"CONFIG_NET_SCH_INGRESS": CONFIG_NET_SCH_INGRESS,
"CONFIG_XFRM": CONFIG_XFRM,
"CONFIG_IP_ROUTE_CLASSID": CONFIG_IP_ROUTE_CLASSID,
"CONFIG_IPV6_SEG6_BPF": CONFIG_IPV6_SEG6_BPF,
"CONFIG_BPF_LIRC_MODE2": CONFIG_BPF_LIRC_MODE2,
"CONFIG_BPF_STREAM_PARSER": CONFIG_BPF_STREAM_PARSER,
"CONFIG_NETFILTER_XT_MATCH_BPF": CONFIG_NETFILTER_XT_MATCH_BPF,
"CONFIG_BPFILTER": CONFIG_BPFILTER,
"CONFIG_BPFILTER_UMH": CONFIG_BPFILTER_UMH,
"CONFIG_TEST_BPF": CONFIG_TEST_BPF,
"CONFIG_HZ": CONFIG_HZ,
"CONFIG_DEBUG_INFO_BTF": CONFIG_DEBUG_INFO_BTF,
"CONFIG_DEBUG_INFO_BTF_MODULES": CONFIG_DEBUG_INFO_BTF_MODULES,
"CONFIG_BPF_LSM": CONFIG_BPF_LSM,
"CONFIG_BPF_PRELOAD": CONFIG_BPF_PRELOAD,
"CONFIG_BPF_PRELOAD_UMD": CONFIG_BPF_PRELOAD_UMD,
}
var KernelConfigKeyIDToString map[uint32]string = map[uint32]string{
CONFIG_BPF: "CONFIG_BPF",
CONFIG_BPF_SYSCALL: "CONFIG_BPF_SYSCALL",
CONFIG_HAVE_EBPF_JIT: "CONFIG_HAVE_EBPF_JIT",
CONFIG_BPF_JIT: "CONFIG_BPF_JIT",
CONFIG_BPF_JIT_ALWAYS_ON: "CONFIG_BPF_JIT_ALWAYS_ON",
CONFIG_CGROUPS: "CONFIG_CGROUPS",
CONFIG_CGROUP_BPF: "CONFIG_CGROUP_BPF",
CONFIG_CGROUP_NET_CLASSID: "CONFIG_CGROUP_NET_CLASSID",
CONFIG_SOCK_CGROUP_DATA: "CONFIG_SOCK_CGROUP_DATA",
CONFIG_BPF_EVENTS: "CONFIG_BPF_EVENTS",
CONFIG_KPROBE_EVENTS: "CONFIG_KPROBE_EVENTS",
CONFIG_UPROBE_EVENTS: "CONFIG_UPROBE_EVENTS",
CONFIG_TRACING: "CONFIG_TRACING",
CONFIG_FTRACE_SYSCALLS: "CONFIG_FTRACE_SYSCALLS",
CONFIG_FUNCTION_ERROR_INJECTION: "CONFIG_FUNCTION_ERROR_INJECTION",
CONFIG_BPF_KPROBE_OVERRIDE: "CONFIG_BPF_KPROBE_OVERRIDE",
CONFIG_NET: "CONFIG_NET",
CONFIG_XDP_SOCKETS: "CONFIG_XDP_SOCKETS",
CONFIG_LWTUNNEL_BPF: "CONFIG_LWTUNNEL_BPF",
CONFIG_NET_ACT_BPF: "CONFIG_NET_ACT_BPF",
CONFIG_NET_CLS_BPF: "CONFIG_NET_CLS_BPF",
CONFIG_NET_CLS_ACT: "CONFIG_NET_CLS_ACT",
CONFIG_NET_SCH_INGRESS: "CONFIG_NET_SCH_INGRESS",
CONFIG_XFRM: "CONFIG_XFRM",
CONFIG_IP_ROUTE_CLASSID: "CONFIG_IP_ROUTE_CLASSID",
CONFIG_IPV6_SEG6_BPF: "CONFIG_IPV6_SEG6_BPF",
CONFIG_BPF_LIRC_MODE2: "CONFIG_BPF_LIRC_MODE2",
CONFIG_BPF_STREAM_PARSER: "CONFIG_BPF_STREAM_PARSER",
CONFIG_NETFILTER_XT_MATCH_BPF: "CONFIG_NETFILTER_XT_MATCH_BPF",
CONFIG_BPFILTER: "CONFIG_BPFILTER",
CONFIG_BPFILTER_UMH: "CONFIG_BPFILTER_UMH",
CONFIG_TEST_BPF: "CONFIG_TEST_BPF",
CONFIG_HZ: "CONFIG_HZ",
CONFIG_DEBUG_INFO_BTF: "CONFIG_DEBUG_INFO_BTF",
CONFIG_DEBUG_INFO_BTF_MODULES: "CONFIG_DEBUG_INFO_BTF_MODULES",
CONFIG_BPF_LSM: "CONFIG_BPF_LSM",
CONFIG_BPF_PRELOAD: "CONFIG_BPF_PRELOAD",
CONFIG_BPF_PRELOAD_UMD: "CONFIG_BPF_PRELOAD_UMD",
}
type KernelConfig map[uint32]string
// InitKernelConfig populates the passed KernelConfig
// by attempting to read the kernel config into it from:
// /proc/config-$(uname -r)
// or
// /boot/config.gz
func (k KernelConfig) InitKernelConfig() error {
x := unix.Utsname{}
err := unix.Uname(&x)
if err != nil {
return fmt.Errorf("could not determine uname release: %v", err)
}
bootConfigPath := fmt.Sprintf("/boot/config-%s", bytes.Trim(x.Release[:], "\x00"))
err = k.getBootConfigByPath(bootConfigPath)
if err == nil {
return nil
}
err2 := k.getProcGZConfigByPath("/proc/config.gz")
if err != nil {
return fmt.Errorf("%v %v", err, err2)
}
return nil
}
// GetKernelConfigValue retrieves a value from the kernel config
// If the config value does not exist an error will be returned
func (k KernelConfig) GetKernelConfigValue(key uint32) (string, error) {
v, exists := k[key]
if !exists {
return "", errors.New("kernel config value does not exist, it's possible this option is not present in your kernel version or the KernelConfig has not been initialized")
}
return v, nil
}
func (k KernelConfig) getBootConfigByPath(bootConfigPath string) error {
configFile, err := os.Open(bootConfigPath)
if err != nil {
return fmt.Errorf("could not open %s: %v", bootConfigPath, err)
}
k.readConfigFromScanner(configFile)
return nil
}
func (k KernelConfig) getProcGZConfigByPath(procConfigPath string) error {
configFile, err := os.Open(procConfigPath)
if err != nil {
return fmt.Errorf("could not open %s: %v", procConfigPath, err)
}
return k.getProcGZConfig(configFile)
}
func (k KernelConfig) getProcGZConfig(reader io.Reader) error {
zreader, err := gzip.NewReader(reader)
if err != nil {
return err
}
k.readConfigFromScanner(zreader)
return nil
}
func (k KernelConfig) readConfigFromScanner(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
kv := strings.Split(scanner.Text(), "=")
if len(kv) != 2 {
continue
}
configKeyID := KernelConfigKeyStringToID[kv[0]]
if configKeyID == 0 {
continue
}
k[configKeyID] = kv[1]
}
}