├── .gitignore
├── .dockerignore
├── CODEOWNERS
├── .gitattributes
├── internal
├── bpf
│ ├── arch
│ │ ├── common.go
│ │ ├── common_test.go
│ │ ├── arm64.go
│ │ ├── amd64.go
│ │ ├── 386.go
│ │ └── arm.go
│ ├── consumer.go
│ ├── whitelist_attacher.go
│ ├── event.go
│ ├── kprobe_attacher.go
│ ├── tracepoint_attacher.go
│ ├── event_processor.go
│ └── attacher.go
├── logger
│ └── logger.go
├── workload
│ ├── runtime.go
│ ├── runtime_handlers.go
│ ├── resolve.go
│ └── sha_resolver.go
├── profile
│ ├── pprof.go
│ └── pyroscope.go
├── app
│ ├── delete_pods.go
│ └── app.go
├── sig
│ └── handler.go
├── metrics
│ ├── server.go
│ └── counters.go
└── kernel
│ └── version.go
├── SECURITY.md
├── .goreleaser.yml
├── cmd
└── bpfsnitch
│ └── main.go
├── .github
└── workflows
│ ├── lint.yml
│ └── release.yml
├── bpf
├── main.c
├── tracepoint
│ └── trace_syscall.c
├── build.sh
├── core.h
└── kprobe
│ ├── trace_udp.c
│ └── trace_tcp.c
├── LICENSE
├── go.mod
├── Makefile
├── .golangci.yml
├── deployments
├── Dockerfile
└── daemonset.yaml
├── pkg
├── network
│ ├── converter.go
│ └── converter_test.go
└── lru
│ ├── lru.go
│ └── lru_test.go
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── go.sum
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | *.o
3 | dev/
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .*/
2 | *.o
3 | dev
4 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @nullswan @gmarcha @naofel1
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | bpf/vmlinux.h linguist-vendored
2 |
--------------------------------------------------------------------------------
/internal/bpf/arch/common.go:
--------------------------------------------------------------------------------
1 | package bpfarch
2 |
3 | // TODO: build with the same target as bpf/build.sh
4 | const bpfProgramName = "bpfsnitch_lib"
5 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | | Version | Supported |
6 | | ------- | ------------------ |
7 | | ^1.0.0 | :white_check_mark: |
8 |
9 | ## Reporting a Vulnerability
10 |
11 | Email me at [email](mailto:pro@nullswan.io)
12 |
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | before:
4 | hooks:
5 | - go mod tidy
6 |
7 | builds:
8 | - id: bpfsnitch
9 | goos:
10 | - linux
11 | goarch:
12 | - arm
13 | - arm64
14 | - amd64
15 | goarm:
16 | - "7"
17 | binary: bpfsnitch
18 | main: ./cmd/bpfsnitch/main.go
19 |
20 | checksum:
21 | algorithm: sha256
22 |
--------------------------------------------------------------------------------
/cmd/bpfsnitch/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/nullswan/bpfsnitch/internal/app"
7 | "github.com/nullswan/bpfsnitch/internal/logger"
8 | )
9 |
10 | func main() {
11 | log := logger.Init()
12 |
13 | if err := app.Run(log); err != nil {
14 | log.With("error", err).Error("Failed to run app")
15 | os.Exit(1)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/internal/logger/logger.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "log/slog"
5 | "os"
6 | )
7 |
8 | func Init() *slog.Logger {
9 | loggerHandlerOpts := &slog.HandlerOptions{
10 | Level: slog.LevelInfo,
11 | }
12 |
13 | if os.Getenv("DEBUG") != "" {
14 | loggerHandlerOpts.Level = slog.LevelDebug
15 | }
16 |
17 | return slog.New(
18 | slog.NewTextHandler(os.Stdout, loggerHandlerOpts),
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/internal/workload/runtime.go:
--------------------------------------------------------------------------------
1 | package workload
2 |
3 | import "os"
4 |
5 | var runtimeSockets = []string{
6 | "/run/containerd/containerd.sock",
7 | "/run/crio/crio.sock",
8 | "/var/run/cri-dockerd.sock",
9 | }
10 |
11 | func IsSocketPresent() bool {
12 | for _, endpoint := range runtimeSockets {
13 | if _, err := os.Stat(endpoint); err == nil {
14 | return true
15 | }
16 | }
17 |
18 | return false
19 | }
20 |
--------------------------------------------------------------------------------
/internal/profile/pprof.go:
--------------------------------------------------------------------------------
1 | package profile
2 |
3 | import (
4 | "net/http"
5 | "net/http/pprof"
6 | )
7 |
8 | func SetupPprof() {
9 | http.HandleFunc("/debug/pprof/", pprof.Index)
10 | http.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
11 | http.HandleFunc("/debug/pprof/profile", pprof.Profile)
12 | http.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
13 | http.HandleFunc("/debug/pprof/trace", pprof.Trace)
14 | }
15 |
--------------------------------------------------------------------------------
/internal/app/delete_pods.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "context"
5 | "log/slog"
6 |
7 | "github.com/nullswan/bpfsnitch/internal/metrics"
8 | )
9 |
10 | func deletePods(
11 | ctx context.Context,
12 | logger *slog.Logger,
13 | deletedPodsChan chan string,
14 | ) {
15 | for {
16 | select {
17 | case <-ctx.Done():
18 | return
19 | case podID := <-deletedPodsChan:
20 | for _, counter := range metrics.PodBasedMetrics {
21 | logger.With("pod", podID).Info("Deleted pod-based metrics")
22 | counter.DeleteLabelValues(podID)
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 |
3 | on:
4 | pull_request:
5 | push:
6 |
7 | permissions:
8 | contents: read
9 |
10 | jobs:
11 | lint:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout the repository
15 | uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0
18 |
19 | - uses: actions/setup-go@v5
20 | with:
21 | go-version-file: go.mod
22 |
23 | - name: Download Go module dependencies
24 | run: go mod download
25 |
26 | - name: golangci-lint
27 | uses: golangci/golangci-lint-action@v3
28 | with:
29 | skip-cache: true
30 | version: v1.61.0
31 |
--------------------------------------------------------------------------------
/bpf/main.c:
--------------------------------------------------------------------------------
1 | //go:build exclude
2 |
3 | #include "tracepoint/trace_syscall.c"
4 | #include "kprobe/trace_udp.c"
5 | #include "kprobe/trace_tcp.c"
6 |
7 | static inline int is_local_ip(__be32 ip) {
8 | // Check for 127.0.0.0/8
9 | if ((ip & 0xFF000000) == 0x7F000000) {
10 | return 1;
11 | }
12 |
13 | // Check for 10.0.0.0/8
14 | if ((ip & 0xFF000000) == 0x0A000000) {
15 | return 1;
16 | }
17 |
18 | // Check for 172.16.0.0/12
19 | if ((ip & 0xFFF00000) == 0xAC100000) {
20 | return 1;
21 | }
22 |
23 | // Check for 192.168.0.0/16
24 | if ((ip & 0xFFFF0000) == 0xC0A80000) {
25 | return 1;
26 | }
27 |
28 | return 0;
29 | }
30 |
31 | char _license[] SEC("license") = "GPL";
32 | #define KBUILD_MODNAME "bpfsnitch"
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2024 @nullswan
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
--------------------------------------------------------------------------------
/internal/bpf/arch/common_test.go:
--------------------------------------------------------------------------------
1 | package bpfarch
2 |
3 | import "testing"
4 |
5 | func TestSyscallDefs(t *testing.T) {
6 | t.Parallel()
7 |
8 | for name, number := range SyscallToId {
9 | if mappedName, present := IdToSyscall[number]; !present ||
10 | mappedName != name {
11 | t.Errorf(
12 | "Mismatch or missing entry: syscall name %s with number %d not found in reverse map",
13 | name,
14 | number,
15 | )
16 | }
17 | }
18 |
19 | for number, name := range IdToSyscall {
20 | if mappedNumber, present := SyscallToId[name]; !present ||
21 | mappedNumber != number {
22 | t.Errorf(
23 | "Mismatch or missing entry: syscall number %d with name %s not found in forward map",
24 | number,
25 | name,
26 | )
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/internal/sig/handler.go:
--------------------------------------------------------------------------------
1 | package sig
2 |
3 | import (
4 | "context"
5 | "log/slog"
6 | "os"
7 | "os/signal"
8 | "syscall"
9 |
10 | "github.com/nullswan/bpfsnitch/internal/bpf"
11 | )
12 |
13 | func SetupHandler(
14 | cancel context.CancelFunc,
15 | bpfCtx *bpf.KBContext,
16 | log *slog.Logger,
17 | ) {
18 | sigChan := make(chan os.Signal, 1)
19 | signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
20 | go func() {
21 | sig := <-sigChan
22 | log.With("signal", sig).Info("Received signal, cancelling context")
23 |
24 | cancel()
25 | for _, tp := range bpfCtx.Tps {
26 | tp.Close()
27 | }
28 | for _, kp := range bpfCtx.Kps {
29 | kp.Close()
30 | }
31 |
32 | bpfCtx.SyscallRingBuffer.Close()
33 | bpfCtx.NetworkRingBuffer.Close()
34 |
35 | log.Info("Closed event reader")
36 | }()
37 | }
38 |
--------------------------------------------------------------------------------
/bpf/tracepoint/trace_syscall.c:
--------------------------------------------------------------------------------
1 | #include "bpf/core.h"
2 |
3 | struct syscall_trace_enter_args {
4 | unsigned long long unused;
5 | long syscall_nr;
6 | long arg0;
7 | long arg1;
8 | long arg2;
9 | long arg3;
10 | long arg4;
11 | long arg5;
12 | };
13 |
14 | SEC("tracepoint/syscalls/sys_enter")
15 | int tracepoint_sys_enter(struct syscall_trace_enter_args *ctx) {
16 | int syscall_nr = ctx->syscall_nr;
17 |
18 | if (bpf_map_lookup_elem(&syscall_whitelist, &syscall_nr) == NULL) {
19 | return 0;
20 | }
21 |
22 | u32 pid = bpf_get_current_pid_tgid() >> 32;
23 | u64 cgroup_id = bpf_get_current_cgroup_id();
24 |
25 | struct syscall_event syscall_event = {
26 | .syscall_nr = ctx->syscall_nr,
27 | .cgroup_id = cgroup_id,
28 | .pid = pid
29 | };
30 |
31 | bpf_ringbuf_output(&syscall_events_rb, &syscall_event, sizeof(syscall_event), BPF_RB_FORCE_WAKEUP);
32 | return 0;
33 | }
--------------------------------------------------------------------------------
/bpf/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | SOURCE_FILE=bpf/main.c
5 | LIBNAME=bpfsnitch_lib
6 | CFLAGS="-g -O2 -target bpf"
7 |
8 | if [ -n "$DEBUG" ]; then
9 | CFLAGS="$CFLAGS -DDEBUG"
10 | fi
11 |
12 | if [ -z "$TARGETARCH" ]; then
13 | echo "TARGETARCH is not set"
14 | exit 1
15 | fi
16 |
17 | case "$TARGETARCH" in
18 | "amd64")
19 | ARCH_FLAGS="-D__TARGET_ARCH_x86"
20 | OUTPUT_FILE="${LIBNAME}_amd64.o"
21 | ;;
22 | "arm64")
23 | ARCH_FLAGS="-D__TARGET_ARCH_arm64"
24 | OUTPUT_FILE="${LIBNAME}_arm64.o"
25 | ;;
26 | "arm")
27 | ARCH_FLAGS="-D__TARGET_ARCH_arm"
28 | OUTPUT_FILE="${LIBNAME}_arm.o"
29 | ;;
30 | "386")
31 | ARCH_FLAGS="-D__TARGET_ARCH_x86"
32 | OUTPUT_FILE="${LIBNAME}_x86.o"
33 | ;;
34 | *)
35 | echo "Unknown architecture: `$TARGETARCH`"
36 | exit 1
37 | ;;
38 | esac
39 |
40 | clang $CFLAGS $ARCH_FLAGS -c $SOURCE_FILE -o $OUTPUT_FILE -I.
41 |
--------------------------------------------------------------------------------
/internal/bpf/consumer.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import (
4 | "bytes"
5 | "context"
6 | "encoding/binary"
7 | "log/slog"
8 |
9 | "github.com/cilium/ebpf/ringbuf"
10 | )
11 |
12 | func ConsumeEvents[T Event](
13 | ctx context.Context,
14 | log *slog.Logger,
15 | evReader *ringbuf.Reader,
16 | evCh chan *T,
17 | ) {
18 | log.Info("Starting event reader")
19 |
20 | for {
21 | select {
22 | case <-ctx.Done():
23 | log.Info("Context done, stopping event reader")
24 | return
25 | default:
26 | record, err := evReader.Read()
27 | if err != nil {
28 | log.With("error", err).Error("Failed to read event")
29 | continue
30 | }
31 |
32 | ev := new(T)
33 | err = binary.Read(
34 | bytes.NewReader(record.RawSample),
35 | binary.LittleEndian,
36 | ev,
37 | )
38 | if err != nil {
39 | log.With("error", err).Error("Failed to decode event")
40 | continue
41 | }
42 |
43 | evCh <- ev
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/bpf/core.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "vmlinux.h"
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #define DIRECTION_INBOUND 0
11 | #define DIRECTION_OUTBOUND 1
12 |
13 | #define PROTOCOL_TCP 6
14 | #define PROTOCOL_UDP 17
15 |
16 | static inline int is_local_ip(__be32 ip);
17 |
18 | struct {
19 | __uint(type, BPF_MAP_TYPE_HASH);
20 | __type(key, __u32);
21 | __type(value, 0);
22 | __uint(max_entries, 1024);
23 | } syscall_whitelist SEC(".maps");
24 |
25 | struct syscall_event {
26 | long syscall_nr;
27 | u64 cgroup_id;
28 | u64 pid;
29 | };
30 |
31 | struct network_event {
32 | u64 pid;
33 | u64 cgroup_id;
34 | u64 size;
35 |
36 | u32 saddr;
37 | u32 daddr;
38 |
39 | u16 sport;
40 | u16 dport;
41 |
42 | u8 direction;
43 | u8 protocol;
44 | };
45 |
46 | struct {
47 | __uint(type, BPF_MAP_TYPE_RINGBUF);
48 | __uint(max_entries, 1<<25); // 32MB
49 | } network_events_rb SEC(".maps");
50 |
51 | struct {
52 | __uint(type, BPF_MAP_TYPE_RINGBUF);
53 | __uint(max_entries, 1<<24); // 16MB
54 | } syscall_events_rb SEC(".maps");
55 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/nullswan/bpfsnitch
2 |
3 | go 1.22.0
4 |
5 | toolchain go1.22.4
6 |
7 | require (
8 | github.com/cilium/ebpf v0.16.0
9 | github.com/grafana/pyroscope-go v1.2.0
10 | github.com/prometheus/client_golang v1.20.4
11 | google.golang.org/grpc v1.66.2
12 | k8s.io/cri-api v0.31.1
13 | )
14 |
15 | require (
16 | github.com/beorn7/perks v1.0.1 // indirect
17 | github.com/cespare/xxhash/v2 v2.3.0 // indirect
18 | github.com/gogo/protobuf v1.3.2 // indirect
19 | github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
20 | github.com/klauspost/compress v1.17.9 // indirect
21 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
22 | github.com/prometheus/client_model v0.6.1 // indirect
23 | github.com/prometheus/common v0.59.1 // indirect
24 | github.com/prometheus/procfs v0.15.1 // indirect
25 | golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
26 | golang.org/x/net v0.29.0 // indirect
27 | golang.org/x/sys v0.25.0 // indirect
28 | golang.org/x/text v0.18.0 // indirect
29 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
30 | google.golang.org/protobuf v1.34.2 // indirect
31 | )
32 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Automatically include environment variables from .env file
2 | ifneq (,$(wildcard ./.env))
3 | include .env
4 | export $(shell sed 's/=.*//' .env)
5 | endif
6 |
7 | .PHONY: build-local
8 | build-local:
9 | DEBUG=1 TARGETARCH=$(shell go env GOARCH) ./bpf/build.sh
10 | go build -o ./dist/ -v ./...
11 |
12 | .PHONY: build-docker
13 | build-docker:
14 | docker build \
15 | -t bpfsnitch:latest \
16 | . -f deployments/Dockerfile
17 |
18 | .PHONY: build-docker-multiarch
19 | build-docker-multiarch:
20 | docker buildx build \
21 | --platform linux/amd64,linux/arm64,linux/arm/v7 \
22 | -t nullswan/bpfsnitch-dev:latest \
23 | --push \
24 | . -f deployments/Dockerfile
25 |
26 | .PHONY: build
27 | build: build-local build-docker
28 |
29 | .PHONY: build-binaries
30 | build-binaries: clean
31 | goreleaser build --snapshot
32 |
33 | .PHONY: build-multiarch
34 | build-multiarch: build-binaries build-docker-multiarch
35 |
36 | .PHONY: clean
37 | clean:
38 | rm -rf dist
39 | docker rmi bpfsnitch || true
40 |
41 | .PHONY: fmt
42 | fmt:
43 | golines . --write-output --max-len=80 --base-formatter="gofmt" --tab-len=2
44 | golangci-lint run --fix
45 |
46 | .PHONY: test
47 | test:
48 | go test -v -cover ./...
49 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | linters:
2 | disable-all: true
3 | enable:
4 | - bodyclose
5 | - containedctx
6 | - contextcheck
7 | - durationcheck
8 | - errcheck
9 | - exhaustive
10 | - gocheckcompilerdirectives
11 | - gochecknoinits
12 | - goconst
13 | - gocritic
14 | - gocyclo
15 | - gofumpt
16 | - gosec
17 | - gosimple
18 | - govet
19 | - ineffassign
20 | - mnd
21 | - nilerr
22 | - nilnil
23 | - noctx
24 | - paralleltest
25 | - perfsprint
26 | - prealloc
27 | - protogetter
28 | - reassign
29 | - revive
30 | - rowserrcheck
31 | - sloglint
32 | - spancheck
33 | - sqlclosecheck
34 | - staticcheck
35 | - staticcheck
36 | - thelper
37 | - typecheck
38 | - unconvert
39 | - unparam
40 | - unused
41 | - unused
42 | - usestdlibvars
43 | - whitespace
44 | - whitespace
45 | - wrapcheck
46 |
47 | linters-settings:
48 | exhaustive:
49 | check:
50 | - switch
51 | - map
52 | default-signifies-exhaustive: true
53 | ignore-enum-members: ".+UNSPECIFIED"
54 |
55 | severity:
56 | default-severity: error
57 |
58 | run:
59 | timeout: 5m
60 | modules-download-mode: readonly
61 |
--------------------------------------------------------------------------------
/deployments/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use Golang alpine image as the build environment
2 | FROM golang:1.22-alpine AS builder
3 |
4 | # Set the target architecture
5 | ARG TARGETARCH
6 | ENV TARGETARCH=${TARGETARCH}
7 | ENV CGO_ENABLED=1 GOOS=linux GOARCH=${TARGETARCH} BPF_TARGET=${TARGETARCH}
8 |
9 | # Install necessary packages
10 | RUN apk add --no-cache clang llvm-dev libbpf-dev build-base
11 |
12 | # Set the working directory
13 | WORKDIR /build
14 |
15 | # Copy and build BPF artifacts
16 | COPY ./bpf ./bpf
17 | RUN chmod +x ./bpf/build.sh && TARGETARCH=${TARGETARCH} sh ./bpf/build.sh
18 |
19 | # Download Go module dependencies
20 | COPY go.mod go.sum ./
21 | RUN go mod download
22 |
23 | # Copy the rest of the source code and build the project
24 | COPY . .
25 | RUN go build -o ./dist/ -v ./...
26 |
27 | # Use a minimal alpine image for the runtime environment
28 | FROM alpine:latest
29 |
30 | # Set the working directory
31 | WORKDIR /root/
32 |
33 | # Copy the built executable from the builder stage
34 | COPY --from=builder /build/dist .
35 | COPY --from=builder /build/bpfsnitch_lib_*.o .
36 |
37 | # Ensure the main executable has the right permissions
38 | RUN chmod +x ./bpfsnitch
39 |
40 | # Specify the default command to run the executable
41 | CMD ["./bpfsnitch"]
--------------------------------------------------------------------------------
/pkg/network/converter.go:
--------------------------------------------------------------------------------
1 | package network
2 |
3 | import "net"
4 |
5 | const SubnetMask24 = 0xFFFFFF00 // nolint:mnd
6 |
7 | func IntToIP(ip uint32) net.IP {
8 | return net.IPv4(
9 | byte(ip>>24), // nolint:mnd
10 | byte(ip>>16), // nolint:mnd
11 | byte(ip>>8), // nolint:mnd
12 | byte(ip),
13 | )
14 | }
15 |
16 | func IntToSubnet(ip uint32, mask uint32) *net.IPNet {
17 | ipMask := net.IPv4Mask(
18 | byte(mask>>24), // nolint:mnd
19 | byte(mask>>16), // nolint:mnd
20 | byte(mask>>8), // nolint:mnd
21 | byte(mask),
22 | )
23 | maskLength, _ := ipMask.Size() // Get the mask length in bits
24 |
25 | networkPart := ip & (0xFFFFFFFF << (32 - maskLength)) // nolint:mnd
26 | ipAddr := net.IPv4(
27 | byte(networkPart>>24), // nolint:mnd
28 | byte(networkPart>>16), // nolint:mnd
29 | byte(networkPart>>8), // nolint:mnd
30 | byte(networkPart),
31 | )
32 | return &net.IPNet{
33 | IP: ipAddr,
34 | Mask: ipMask,
35 | }
36 | }
37 |
38 | func Ntohs(val uint16) uint16 {
39 | return (val<<8)&0xff00 | val>>8 // nolint:mnd
40 | }
41 |
42 | func Ntohl(val uint32) uint32 {
43 | return (val<<24)&0xff000000 | // nolint:mnd
44 | (val<<8)&0x00ff0000 | // nolint:mnd
45 | (val>>8)&0x0000ff00 | // nolint:mnd
46 | (val>>24)&0x000000ff // nolint:mnd
47 | }
48 |
--------------------------------------------------------------------------------
/internal/bpf/whitelist_attacher.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import (
4 | "encoding/binary"
5 | "fmt"
6 | "log/slog"
7 |
8 | "github.com/cilium/ebpf"
9 | bpfarch "github.com/nullswan/bpfsnitch/internal/bpf/arch"
10 | )
11 |
12 | const (
13 | // Map name for the whitelist of syscalls.
14 | syscallsWhitelistMapName = "syscall_whitelist"
15 | intSz = 4
16 | )
17 |
18 | func registerWhitelistedSyscalls(
19 | log *slog.Logger,
20 | maps map[string]*ebpf.Map,
21 | ) error {
22 | syscallMap, ok := maps[syscallsWhitelistMapName]
23 | if !ok {
24 | return fmt.Errorf(
25 | "failed to find map %s",
26 | syscallsWhitelistMapName,
27 | )
28 | }
29 |
30 | for _, nbr := range bpfarch.WhitelistedSyscalls {
31 | syscallName := bpfarch.IdToSyscall[nbr]
32 | buf := make([]byte, intSz)
33 | binary.LittleEndian.PutUint32(buf, uint32(nbr)) //nolint: gosec
34 |
35 | placeholder := make([]byte, intSz)
36 | if err := syscallMap.Update(
37 | buf,
38 | placeholder,
39 | ebpf.UpdateAny,
40 | ); err != nil {
41 | return fmt.Errorf(
42 | "failed to update map %s: %w",
43 | syscallsWhitelistMapName,
44 | err,
45 | )
46 | }
47 |
48 | log.With("syscall_name", syscallName).Info("Registered syscall")
49 | }
50 |
51 | return nil
52 | }
53 |
--------------------------------------------------------------------------------
/internal/bpf/event.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import bpfarch "github.com/nullswan/bpfsnitch/internal/bpf/arch"
4 |
5 | type Event interface {
6 | SyscallEvent | NetworkEvent
7 | }
8 |
9 | type SyscallEvent struct {
10 | SyscallNr int64
11 | CgroupID uint64
12 | Pid uint64
13 | }
14 |
15 | func (s SyscallEvent) GetSyscallName() string {
16 | return bpfarch.IdToSyscall[int(s.SyscallNr)]
17 | }
18 |
19 | type NetworkEvent struct {
20 | Pid uint64
21 | CgroupID uint64
22 | Size uint64
23 |
24 | Saddr uint32
25 | Daddr uint32
26 |
27 | Sport uint16
28 | Dport uint16
29 |
30 | Direction NetworkEventDirection
31 | Protocol NetworkEventProtocol
32 | }
33 |
34 | type NetworkEventDirection uint8
35 |
36 | const (
37 | NetworkEventDirectionInbound NetworkEventDirection = 0
38 | NetworkEventDirectionOutbound NetworkEventDirection = 1
39 | )
40 |
41 | func (d NetworkEventDirection) String() string {
42 | if d == NetworkEventDirectionInbound {
43 | return "inbound"
44 | }
45 | return "outbound"
46 | }
47 |
48 | type NetworkEventProtocol uint8
49 |
50 | const (
51 | NetworkEventProtocolTCP NetworkEventProtocol = 6
52 | NetworkEventProtocolUDP NetworkEventProtocol = 17
53 | )
54 |
55 | func (p NetworkEventProtocol) String() string {
56 | if p == NetworkEventProtocolTCP {
57 | return "tcp"
58 | }
59 | return "udp"
60 | }
61 |
--------------------------------------------------------------------------------
/internal/profile/pyroscope.go:
--------------------------------------------------------------------------------
1 | package profile
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "log/slog"
7 | "os"
8 |
9 | "github.com/grafana/pyroscope-go"
10 | )
11 |
12 | func SetupProfiling(log *slog.Logger) error {
13 | serverAddress := os.Getenv("PYROSCOPE_SERVER")
14 | if serverAddress == "" {
15 | return errors.New("PYROSCOPE_SERVER is not set")
16 | }
17 |
18 | user := os.Getenv("PYROSCOPE_USER")
19 | if user == "" {
20 | log.Warn("PYROSCOPE_USER is not set")
21 | }
22 |
23 | password := os.Getenv("PYROSCOPE_PASSWORD")
24 | if password == "" {
25 | log.Warn("PYROSCOPE_PASSWORD is not set")
26 | }
27 |
28 | _, err := pyroscope.Start(pyroscope.Config{
29 | ApplicationName: "bpfsnitch",
30 | ServerAddress: serverAddress,
31 | BasicAuthUser: user,
32 | BasicAuthPassword: password,
33 | Logger: pyroscope.StandardLogger,
34 | Tags: map[string]string{"hostname": os.Getenv("HOSTNAME")},
35 | ProfileTypes: []pyroscope.ProfileType{
36 | pyroscope.ProfileCPU,
37 | pyroscope.ProfileAllocObjects,
38 | pyroscope.ProfileAllocSpace,
39 | pyroscope.ProfileInuseObjects,
40 | pyroscope.ProfileInuseSpace,
41 | pyroscope.ProfileGoroutines,
42 | pyroscope.ProfileMutexCount,
43 | pyroscope.ProfileMutexDuration,
44 | pyroscope.ProfileBlockCount,
45 | pyroscope.ProfileBlockDuration,
46 | },
47 | })
48 | if err != nil {
49 | return fmt.Errorf("failed to start pyroscope: %w", err)
50 | }
51 |
52 | return nil
53 | }
54 |
--------------------------------------------------------------------------------
/internal/metrics/server.go:
--------------------------------------------------------------------------------
1 | package metrics
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log/slog"
7 | "net/http"
8 |
9 | "github.com/prometheus/client_golang/prometheus"
10 | "github.com/prometheus/client_golang/prometheus/collectors"
11 | "github.com/prometheus/client_golang/prometheus/promhttp"
12 | )
13 |
14 | func StartServer(log *slog.Logger, cancel context.CancelFunc, port uint64) {
15 | http.Handle("/metrics", promhttp.Handler())
16 |
17 | log.With("port", port).Info("Starting metrics server")
18 | err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) // nolint:gosec
19 | if err != nil {
20 | log.With("error", err).Error("Failed to start metrics server")
21 | cancel()
22 | }
23 | }
24 |
25 | const promPrefix = "bpfsnitch_"
26 |
27 | func RegisterMetrics() {
28 | // Remove all builtin metrics that are produced by prometheus client.
29 | // TODO: Remove promhttp_metric_handler_requests_total && promhttp_metric_handler_requests_in_flight
30 | prometheus.Unregister(collectors.NewGoCollector())
31 | prometheus.Unregister(collectors.NewProcessCollector(
32 | collectors.ProcessCollectorOpts{},
33 | ))
34 |
35 | // Create a custom registerer with a prefix
36 | registerer := prometheus.WrapRegistererWithPrefix(
37 | promPrefix,
38 | prometheus.DefaultRegisterer,
39 | )
40 |
41 | registerer.MustRegister(SyscallCounter)
42 | registerer.MustRegister(DNSQueryCounter)
43 | registerer.MustRegister(NetworkReceivedBytesCounter)
44 | registerer.MustRegister(NetworkReceivedPacketsCounter)
45 | registerer.MustRegister(NetworkSentBytesCounter)
46 | registerer.MustRegister(NetworkSentPacketsCounter)
47 | }
48 |
--------------------------------------------------------------------------------
/internal/metrics/counters.go:
--------------------------------------------------------------------------------
1 | package metrics
2 |
3 | import "github.com/prometheus/client_golang/prometheus"
4 |
5 | var DNSQueryCounter = prometheus.NewCounterVec(
6 | prometheus.CounterOpts{
7 | Name: "dns_query_counter",
8 | Help: "Number of DNS queries",
9 | },
10 | []string{"pod"},
11 | )
12 |
13 | var SyscallCounter = prometheus.NewCounterVec(
14 | prometheus.CounterOpts{
15 | Name: "syscall_counter",
16 | Help: "Number of syscalls",
17 | },
18 | []string{"syscall", "pod"},
19 | )
20 |
21 | var NetworkReceivedBytesCounter = prometheus.NewCounterVec(
22 | prometheus.CounterOpts{
23 | Name: "network_received_bytes_counter",
24 | Help: "Number of bytes received",
25 | },
26 | []string{"pod", "remote_subnet"},
27 | )
28 |
29 | var NetworkSentBytesCounter = prometheus.NewCounterVec(
30 | prometheus.CounterOpts{
31 | Name: "network_sent_bytes_counter",
32 | Help: "Number of bytes sent",
33 | },
34 | []string{"pod", "remote_subnet"},
35 | )
36 |
37 | var NetworkSentPacketsCounter = prometheus.NewCounterVec(
38 | prometheus.CounterOpts{
39 | Name: "network_sent_packets_counter",
40 | Help: "Number of packets sent",
41 | },
42 | []string{"pod", "remote_subnet"},
43 | )
44 |
45 | var NetworkReceivedPacketsCounter = prometheus.NewCounterVec(
46 | prometheus.CounterOpts{
47 | Name: "network_received_packets_counter",
48 | Help: "Number of packets received",
49 | },
50 | []string{"pod", "remote_subnet"},
51 | )
52 |
53 | var PodBasedMetrics = []*prometheus.CounterVec{
54 | DNSQueryCounter,
55 | SyscallCounter,
56 | NetworkReceivedBytesCounter,
57 | NetworkSentBytesCounter,
58 | NetworkSentPacketsCounter,
59 | NetworkReceivedPacketsCounter,
60 | }
61 |
--------------------------------------------------------------------------------
/internal/bpf/kprobe_attacher.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import (
4 | "fmt"
5 | "log/slog"
6 |
7 | "github.com/cilium/ebpf"
8 | "github.com/cilium/ebpf/link"
9 | )
10 |
11 | // Struct that holds bpf kprobe required metadata
12 | type KProbeMeta struct {
13 | function string
14 | section string
15 | }
16 |
17 | var kpsMeta = []KProbeMeta{
18 | {
19 | function: "udp_recvmsg",
20 | section: "trace_udp_recvmsg",
21 | },
22 | {
23 | function: "udp_sendmsg",
24 | section: "trace_udp_sendmsg",
25 | },
26 | {
27 | function: "tcp_recvmsg",
28 | section: "trace_tcp_recvmsg",
29 | },
30 | {
31 | function: "tcp_sendmsg",
32 | section: "trace_tcp_sendmsg",
33 | },
34 | }
35 |
36 | func attachKProbes(
37 | log *slog.Logger,
38 | coll *ebpf.Collection,
39 | ) ([]link.Link, error) {
40 | kps := make([]link.Link, 0, len(kpsMeta))
41 | for _, kp := range kpsMeta {
42 | kpLink, err := attachKProbe(coll, kp, log)
43 | if err != nil {
44 | return nil, fmt.Errorf(
45 | "failed to attach kprobe %s: %w",
46 | kp.section,
47 | err,
48 | )
49 | }
50 |
51 | kps = append(kps, kpLink)
52 | }
53 |
54 | return kps, nil
55 | }
56 |
57 | func attachKProbe(
58 | coll *ebpf.Collection,
59 | kp KProbeMeta,
60 | log *slog.Logger,
61 | ) (link.Link, error) {
62 | prog := coll.Programs[kp.section]
63 | if prog == nil {
64 | return nil, fmt.Errorf("failed to find program %s", kp.section)
65 | }
66 |
67 | kpLink, err := link.Kprobe(kp.function, prog, nil)
68 | if err != nil {
69 | return nil, fmt.Errorf(
70 | "failed to attach kprobe %s: %w",
71 | kp.function,
72 | err,
73 | )
74 | }
75 |
76 | log.Info("Attached kprobe", "section", kp.section, "function", kp.function)
77 |
78 | return kpLink, nil
79 | }
80 |
--------------------------------------------------------------------------------
/internal/kernel/version.go:
--------------------------------------------------------------------------------
1 | package kernel
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strconv"
7 | "strings"
8 | )
9 |
10 | // GetKernelVersion fetches the Linux kernel version without using exec commands.
11 | // It reads the version directly from /proc/sys/kernel/osrelease.
12 | func GetKernelVersion() (string, error) {
13 | data, err := os.ReadFile("/proc/sys/kernel/osrelease")
14 | if err != nil {
15 | return "", fmt.Errorf("failed to read kernel version: %w", err)
16 | }
17 | version := strings.TrimSpace(string(data))
18 | return version, nil
19 | }
20 |
21 | // CompareVersions compares two kernel version strings.
22 | // It returns 1 if v1 > v2, -1 if v1 < v2, and 0 if they are equal.
23 | func CompareVersions(v1, v2 string) int {
24 | v1Parts := strings.Split(v1, ".")
25 | v2Parts := strings.Split(v2, ".")
26 |
27 | maxLen := len(v1Parts)
28 | if len(v2Parts) > maxLen {
29 | maxLen = len(v2Parts)
30 | }
31 |
32 | for i := 0; i < maxLen; i++ {
33 | var v1Num, v2Num int
34 |
35 | if i < len(v1Parts) {
36 | v1Num = extractLeadingNumber(v1Parts[i])
37 | }
38 | if i < len(v2Parts) {
39 | v2Num = extractLeadingNumber(v2Parts[i])
40 | }
41 |
42 | if v1Num > v2Num {
43 | return 1
44 | } else if v1Num < v2Num {
45 | return -1
46 | }
47 | }
48 | return 0
49 | }
50 |
51 | // extractLeadingNumber extracts the leading numeric part of a version string segment.
52 | func extractLeadingNumber(s string) int {
53 | numStr := strings.TrimLeftFunc(s, func(r rune) bool {
54 | return r < '0' || r > '9'
55 | })
56 | numStr = strings.TrimRightFunc(numStr, func(r rune) bool {
57 | return r < '0' || r > '9'
58 | })
59 | num, err := strconv.Atoi(numStr)
60 | if err != nil {
61 | return 0
62 | }
63 | return num
64 | }
65 |
--------------------------------------------------------------------------------
/internal/bpf/tracepoint_attacher.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "log/slog"
7 |
8 | "github.com/cilium/ebpf"
9 | "github.com/cilium/ebpf/link"
10 | bpfarch "github.com/nullswan/bpfsnitch/internal/bpf/arch"
11 | )
12 |
13 | // Struct that holds bpf tracepoint required metadata
14 | type TpMeta struct {
15 | family string
16 | section string
17 | name string
18 | }
19 |
20 | func attachTracepoints(
21 | log *slog.Logger,
22 | coll *ebpf.Collection,
23 | ) ([]link.Link, error) {
24 | tps := make([]link.Link, 0, len(bpfarch.WhitelistedSyscalls))
25 | for _, nbr := range bpfarch.WhitelistedSyscalls {
26 | syscallName := bpfarch.IdToSyscall[nbr]
27 | tp := TpMeta{
28 | family: "syscalls",
29 | section: "tracepoint_sys_enter",
30 | name: "sys_enter_" + syscallName,
31 | }
32 |
33 | logCtx := log.With(
34 | "family",
35 | tp.family,
36 | "section",
37 | tp.section,
38 | "name",
39 | tp.name,
40 | )
41 |
42 | tpLink, err := attachTracepoint(coll, tp)
43 | if err != nil {
44 | logCtx.Error(
45 | "Failed to attach tracepoint",
46 | "error",
47 | err,
48 | )
49 | continue
50 | }
51 |
52 | logCtx.Info(
53 | "Attached tracepoint",
54 | )
55 |
56 | tps = append(tps, tpLink)
57 | }
58 |
59 | if len(tps) == 0 {
60 | return nil, errors.New("failed to attach any tracepoints")
61 | }
62 |
63 | log.Info("Attached tracepoints", "count", len(tps))
64 |
65 | return tps, nil
66 | }
67 |
68 | func attachTracepoint(
69 | coll *ebpf.Collection,
70 | tp TpMeta,
71 | ) (link.Link, error) {
72 | prog := coll.Programs[tp.section]
73 | if prog == nil {
74 | return nil, fmt.Errorf("failed to find program %s", tp.section)
75 | }
76 |
77 | tpLink, err := link.Tracepoint(tp.family, tp.name, prog, nil)
78 | if err != nil {
79 | return nil, fmt.Errorf(
80 | "failed to attach tracepoint %s: %w",
81 | tp.section,
82 | err,
83 | )
84 | }
85 |
86 | return tpLink, nil
87 | }
88 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # https://goreleaser.com/ci/actions/
2 | name: release
3 |
4 | on:
5 | push:
6 | tags:
7 | - "*"
8 |
9 | permissions:
10 | contents: write
11 | packages: write
12 | issues: write
13 |
14 | jobs:
15 | goreleaser:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@v4
20 | with:
21 | fetch-depth: 0
22 |
23 | - name: Set up Go
24 | uses: actions/setup-go@v5
25 | with:
26 | go-version-file: go.mod
27 |
28 | - name: Download Go module dependencies
29 | run: go mod download
30 |
31 | - name: Run GoReleaser
32 | uses: goreleaser/goreleaser-action@v6
33 | with:
34 | distribution: goreleaser
35 | version: "~> v2"
36 | args: release --clean
37 | env:
38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39 |
40 | docker-push:
41 | runs-on: ubuntu-latest
42 | needs: goreleaser
43 | steps:
44 | - name: Checkout
45 | uses: actions/checkout@v4
46 | with:
47 | fetch-depth: 0
48 |
49 | - name: Set up QEMU
50 | uses: docker/setup-qemu-action@v2
51 |
52 | - name: Set up Docker Buildx
53 | uses: docker/setup-buildx-action@v3
54 |
55 | - name: Login to DockerHub
56 | uses: docker/login-action@v2
57 | with:
58 | username: ${{ secrets.DOCKER_USERNAME }}
59 | password: ${{ secrets.DOCKER_PASSWORD }}
60 |
61 | - name: Docker meta
62 | id: meta
63 | uses: docker/metadata-action@v4
64 | with:
65 | images: ${{ secrets.DOCKERHUB_REPO}}/bpfsnitch
66 |
67 | - name: Build and push
68 | uses: docker/build-push-action@v5
69 | with:
70 | context: .
71 | file: ./deployments/Dockerfile
72 | platforms: linux/amd64,linux/arm64, linux/arm/v7
73 | push: ${{ github.event_name != 'pull_request' }}
74 | tags: ${{ steps.meta.outputs.tags }}
75 | labels: ${{ steps.meta.outputs.labels }}
76 |
--------------------------------------------------------------------------------
/internal/workload/runtime_handlers.go:
--------------------------------------------------------------------------------
1 | package workload
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "fmt"
7 | "os"
8 |
9 | "google.golang.org/grpc"
10 | "google.golang.org/grpc/credentials/insecure"
11 | runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
12 | )
13 |
14 | func getRuntimeServiceClient() (runtimeapi.RuntimeServiceClient, *grpc.ClientConn, error) {
15 | var runtimeEndpoint string
16 | for _, endpoint := range runtimeSockets {
17 | if _, err := os.Stat(endpoint); err == nil {
18 | runtimeEndpoint = endpoint
19 | break
20 | }
21 | }
22 |
23 | if runtimeEndpoint == "" {
24 | return nil, nil, errors.New("no runtime socket found")
25 | }
26 |
27 | serverAddr := "unix://" + runtimeEndpoint
28 | conn, err := grpc.NewClient(
29 | serverAddr,
30 | grpc.WithTransportCredentials(insecure.NewCredentials()),
31 | )
32 | if err != nil {
33 | return nil, nil, fmt.Errorf(
34 | "failed to connect to %s: %w",
35 | serverAddr,
36 | err,
37 | )
38 | }
39 |
40 | runtimeClient := runtimeapi.NewRuntimeServiceClient(conn)
41 | return runtimeClient, conn, nil
42 | }
43 |
44 | func getContainers(
45 | ctx context.Context,
46 | runtimeClient runtimeapi.RuntimeServiceClient,
47 | ) ([]*runtimeapi.Container, error) {
48 | req := &runtimeapi.ListContainersRequest{
49 | Filter: &runtimeapi.ContainerFilter{
50 | State: &runtimeapi.ContainerStateValue{
51 | State: runtimeapi.ContainerState_CONTAINER_RUNNING,
52 | },
53 | },
54 | }
55 | resp, err := runtimeClient.ListContainers(ctx, req)
56 | if err != nil {
57 | return nil, fmt.Errorf("failed to list containers: %w", err)
58 | }
59 | return resp.Containers, nil
60 | }
61 |
62 | func getPods(
63 | ctx context.Context,
64 | runtimeClient runtimeapi.RuntimeServiceClient,
65 | ) ([]*runtimeapi.PodSandbox, error) {
66 | req := &runtimeapi.ListPodSandboxRequest{
67 | Filter: &runtimeapi.PodSandboxFilter{
68 | State: &runtimeapi.PodSandboxStateValue{
69 | State: runtimeapi.PodSandboxState_SANDBOX_READY,
70 | },
71 | },
72 | }
73 | resp, err := runtimeClient.ListPodSandbox(ctx, req)
74 | if err != nil {
75 | return nil, fmt.Errorf("failed to list pods: %w", err)
76 | }
77 | return resp.Items, nil
78 | }
79 |
--------------------------------------------------------------------------------
/internal/bpf/event_processor.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import (
4 | "context"
5 | "log/slog"
6 |
7 | "github.com/nullswan/bpfsnitch/internal/metrics"
8 | "github.com/nullswan/bpfsnitch/pkg/network"
9 | )
10 |
11 | func ProcessNetworkEvent(
12 | event *NetworkEvent,
13 | pod string,
14 | log *slog.Logger,
15 | ) {
16 | // Adjust endianness if necessary
17 | event.Saddr = network.Ntohl(event.Saddr)
18 | event.Daddr = network.Ntohl(event.Daddr)
19 | event.Sport = network.Ntohs(event.Sport)
20 | event.Dport = network.Ntohs(event.Dport)
21 |
22 | // Convert IP addresses to net.IP
23 | saddr := network.IntToSubnet(event.Saddr, network.SubnetMask24)
24 | daddr := network.IntToSubnet(event.Daddr, network.SubnetMask24)
25 |
26 | if log.Enabled(context.TODO(), slog.LevelDebug) {
27 | log.With("pid", event.Pid).
28 | With("cgroup_id", event.CgroupID).
29 | With("pod", pod).
30 | With("saddr", saddr).
31 | With("daddr", daddr).
32 | With("sport", event.Sport).
33 | With("dport", event.Dport).
34 | With("size", event.Size).
35 | Debug("Received network event")
36 | }
37 |
38 | if event.Protocol == NetworkEventProtocolUDP &&
39 | event.Direction == NetworkEventDirectionOutbound &&
40 | event.Dport == 53 {
41 | metrics.DNSQueryCounter.WithLabelValues(pod).Inc()
42 | }
43 |
44 | daddrStr := daddr.String()
45 | if event.Direction == 0 {
46 | metrics.NetworkSentBytesCounter.WithLabelValues(pod, daddrStr).
47 | Add(float64(event.Size))
48 | metrics.NetworkSentPacketsCounter.WithLabelValues(pod, daddrStr).
49 | Inc()
50 | } else {
51 | metrics.NetworkReceivedBytesCounter.WithLabelValues(pod, daddrStr).Add(float64(event.Size))
52 | metrics.NetworkReceivedPacketsCounter.WithLabelValues(pod, daddrStr).Inc()
53 | }
54 | }
55 |
56 | func ProcessSyscallEvent(
57 | event *SyscallEvent,
58 | pod string,
59 | log *slog.Logger,
60 | ) {
61 | // Check if debug logging is enabled for performance reasons
62 | if log.Enabled(context.TODO(), slog.LevelDebug) {
63 | log.
64 | With("syscall", event.GetSyscallName()).
65 | With("pid", event.Pid).
66 | With("cgroup_id", event.CgroupID).
67 | With("pod", pod).
68 | Debug("Received syscall event")
69 | }
70 |
71 | metrics.SyscallCounter.WithLabelValues(event.GetSyscallName(), pod).
72 | Inc()
73 | }
74 |
--------------------------------------------------------------------------------
/pkg/lru/lru.go:
--------------------------------------------------------------------------------
1 | package lru
2 |
3 | import (
4 | "container/list"
5 | "sync"
6 | )
7 |
8 | // Cache is a thread-safe fixed size LRU cache.
9 | type Cache[K comparable, V any] struct {
10 | capacity int
11 | lock sync.Mutex
12 | cache map[K]*list.Element
13 | list *list.List
14 | }
15 |
16 | type pair[K comparable, V any] struct {
17 | key K
18 | value V
19 | }
20 |
21 | // New creates a new LRUCache with the given capacity.
22 | func New[K comparable, V any](capacity int) *Cache[K, V] {
23 | return &Cache[K, V]{
24 | capacity: capacity,
25 | cache: make(map[K]*list.Element),
26 | list: list.New(),
27 | }
28 | }
29 |
30 | // Get retrieves the value of the key from the cache and marks the key as recently used.
31 | func (c *Cache[K, V]) Get(key K) (value V, ok bool) {
32 | c.lock.Lock()
33 | defer c.lock.Unlock()
34 |
35 | if elem, found := c.cache[key]; found {
36 | c.list.MoveToFront(elem)
37 | return elem.Value.(*pair[K, V]).value, true
38 | }
39 | var zeroValue V
40 | return zeroValue, false
41 | }
42 |
43 | // Put adds a key-value pair to the cache and evicts items if the cache is full.
44 | func (c *Cache[K, V]) Put(key K, value V) {
45 | c.lock.Lock()
46 | defer c.lock.Unlock()
47 |
48 | if elem, found := c.cache[key]; found {
49 | c.list.MoveToFront(elem)
50 | elem.Value.(*pair[K, V]).value = value
51 | return
52 | }
53 |
54 | if c.list.Len() >= c.capacity {
55 | backElem := c.list.Back()
56 | if backElem != nil {
57 | c.list.Remove(backElem)
58 | delete(c.cache, backElem.Value.(*pair[K, V]).key)
59 | }
60 | }
61 |
62 | entry := &pair[K, V]{key: key, value: value}
63 | elem := c.list.PushFront(entry)
64 | c.cache[key] = elem
65 | }
66 |
67 | // Remove removes the key from the cache.
68 | func (c *Cache[K, V]) Remove(key K) {
69 | c.lock.Lock()
70 | defer c.lock.Unlock()
71 |
72 | if elem, found := c.cache[key]; found {
73 | c.list.Remove(elem)
74 | delete(c.cache, key)
75 | }
76 | }
77 |
78 | // ForEach iterates over all elements in the cache and calls the given function for each element.
79 | func (c *Cache[K, V]) ForEach(fn func(key K, value V) bool) {
80 | c.lock.Lock()
81 | defer c.lock.Unlock()
82 |
83 | for elem := c.list.Front(); elem != nil; elem = elem.Next() {
84 | p := elem.Value.(*pair[K, V])
85 | if !fn(p.key, p.value) {
86 | break
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/internal/workload/resolve.go:
--------------------------------------------------------------------------------
1 | package workload
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "io"
7 | "log/slog"
8 | "os"
9 | "regexp"
10 | "strings"
11 |
12 | "github.com/nullswan/bpfsnitch/pkg/lru"
13 | )
14 |
15 | var (
16 | ErrCgroupIDBanned = errors.New("cgroup id is banned")
17 | ErrCgroupIDNotContainer = errors.New("cgroup id is not container")
18 | )
19 |
20 | func ResolvePod(
21 | pid uint64,
22 | cgroupID uint64,
23 | pidToShaLRU *lru.Cache[uint64, string],
24 | bannedCgroupIDs *lru.Cache[uint64, struct{}],
25 | shaResolver *ShaResolver,
26 | procPath string,
27 | log *slog.Logger,
28 | ) (string, error) {
29 | if _, ok := bannedCgroupIDs.Get(cgroupID); ok {
30 | return "", ErrCgroupIDBanned
31 | }
32 |
33 | sha, ok := pidToShaLRU.Get(pid)
34 | if !ok {
35 | sha, err := readShaFromCgroup(
36 | pid,
37 | cgroupID,
38 | bannedCgroupIDs,
39 | procPath,
40 | log,
41 | )
42 | if err != nil {
43 | return "", fmt.Errorf("failed to read sha from cgroup: %w", err)
44 | }
45 | pidToShaLRU.Put(pid, sha)
46 | }
47 |
48 | pod, err := shaResolver.Resolve(sha)
49 | if err != nil {
50 | return "", fmt.Errorf("failed to resolve sha: %w", err)
51 | }
52 |
53 | return pod, nil
54 | }
55 |
56 | var reKubeContainerd = regexp.MustCompile(`([a-f0-9]{64})\.scope`)
57 |
58 | func readShaFromCgroup(
59 | pid uint64,
60 | cgroupID uint64,
61 | bannedCgroupIDs *lru.Cache[uint64, struct{}],
62 | procPath string,
63 | log *slog.Logger,
64 | ) (string, error) {
65 | fd, err := os.Open(fmt.Sprintf("/%s/%d/cgroup", procPath, pid))
66 | if err != nil {
67 | return "", fmt.Errorf("failed to open cgroup file: %w", err)
68 | }
69 | defer fd.Close()
70 |
71 | content, err := io.ReadAll(fd)
72 | if err != nil {
73 | return "", fmt.Errorf("failed to read cgroup file: %w", err)
74 | }
75 |
76 | // format local containerd
77 | contentStr := string(content)
78 | if strings.Contains(contentStr, "k8s.io") {
79 | sha := strings.TrimSpace(
80 | contentStr[strings.LastIndex(contentStr, "/")+1:],
81 | )
82 | return sha, nil
83 | }
84 |
85 | // format SCW, AWS
86 | // 0::/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod7bd1a2a3_0861_4fe1_be78_9c76385b3dc0.slice/cri-containerd-1579a01cfce4b1e74529c17bed485d86b871b58f13348c773076b101df4ff62d.scope
87 | if strings.Contains(contentStr, "cri-containerd") {
88 | match := reKubeContainerd.FindStringSubmatch(contentStr)
89 | if len(match) == 2 { // nolint: mnd
90 | return match[1], nil
91 | }
92 | }
93 |
94 | log.With("cgroup_id", cgroupID).Debug("Banning cgroup id")
95 | bannedCgroupIDs.Put(cgroupID, struct{}{})
96 | return "", ErrCgroupIDNotContainer
97 | }
98 |
--------------------------------------------------------------------------------
/bpf/kprobe/trace_udp.c:
--------------------------------------------------------------------------------
1 | #include "bpf/core.h"
2 |
3 | struct udp_recvmsg_args {
4 | struct sock *sk;
5 | struct msghdr *msg;
6 | size_t size;
7 | int flags;
8 | int *addr_len;
9 | };
10 |
11 | SEC("kprobe/udp_recvmsg")
12 | int trace_udp_recvmsg(struct udp_recvmsg_args *ctx) {
13 | u64 cgroup_id = bpf_get_current_cgroup_id();
14 | u32 pid = bpf_get_current_pid_tgid() >> 32;
15 |
16 | struct sock *sk = ctx->sk;
17 | size_t size = ctx->size;
18 |
19 | __u64 err;
20 | __be32 saddr;
21 | __be32 daddr;
22 | __be16 dport;
23 | __u16 sport;
24 |
25 | err = bpf_probe_read(&saddr, sizeof(saddr), &sk->__sk_common.skc_rcv_saddr);
26 | if (err != 0)
27 | return 0;
28 | err = bpf_probe_read(&daddr, sizeof(daddr), &sk->__sk_common.skc_daddr);
29 | if (err != 0)
30 | return 0;
31 | err = bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
32 | if (err != 0)
33 | return 0;
34 | err = bpf_probe_read(&sport, sizeof(sport), &sk->__sk_common.skc_num);
35 | if (err != 0)
36 | return 0;
37 |
38 | if (is_local_ip(saddr) || is_local_ip(daddr)) {
39 | return 0;
40 | }
41 |
42 | struct network_event e = {};
43 | e.pid = pid;
44 | e.cgroup_id = cgroup_id;
45 | e.size = size;
46 | e.saddr = saddr;
47 | e.daddr = daddr;
48 | e.sport = sport;
49 | e.dport = dport;
50 | e.direction = DIRECTION_INBOUND;
51 | e.protocol = PROTOCOL_UDP;
52 |
53 | bpf_ringbuf_output(&network_events_rb, &e, sizeof(e), BPF_RB_FORCE_WAKEUP);
54 | return 0;
55 | }
56 |
57 | struct udp_sendmsg_args {
58 | struct sock *sk;
59 | struct msghdr *msg;
60 | size_t len;
61 | };
62 |
63 | SEC("kprobe/udp_sendmsg")
64 | int trace_udp_sendmsg(struct udp_sendmsg_args *ctx) {
65 | u64 cgroup_id = bpf_get_current_cgroup_id();
66 | u32 pid = bpf_get_current_pid_tgid() >> 32;
67 |
68 | struct sock *sk = ctx->sk;
69 | size_t size = ctx->len;
70 |
71 | __u64 err;
72 | __be32 saddr;
73 | __be32 daddr;
74 | __be16 sport;
75 | __be16 dport;
76 |
77 | err = bpf_probe_read(&saddr, sizeof(saddr), &sk->__sk_common.skc_rcv_saddr);
78 | if (err != 0)
79 | return 0;
80 | err = bpf_probe_read(&daddr, sizeof(daddr), &sk->__sk_common.skc_daddr);
81 | if (err != 0)
82 | return 0;
83 | err = bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
84 | if (err != 0)
85 | return 0;
86 | err = bpf_probe_read(&sport, sizeof(sport), &sk->__sk_common.skc_num);
87 | if (err != 0)
88 | return 0;
89 |
90 | if (is_local_ip(saddr) || is_local_ip(daddr)) {
91 | return 0;
92 | }
93 |
94 | struct network_event e = {};
95 | e.pid = pid;
96 | e.cgroup_id = cgroup_id;
97 | e.size = size;
98 | e.saddr = saddr;
99 | e.daddr = daddr;
100 | e.sport = sport;
101 | e.dport = dport;
102 | e.direction = DIRECTION_OUTBOUND;
103 | e.protocol = PROTOCOL_UDP;
104 |
105 | bpf_ringbuf_output(&network_events_rb, &e, sizeof(e), BPF_RB_FORCE_WAKEUP);
106 | return 0;
107 | }
--------------------------------------------------------------------------------
/bpf/kprobe/trace_tcp.c:
--------------------------------------------------------------------------------
1 | #include "bpf/core.h"
2 |
3 | struct tcp_recvmsg_args {
4 | struct sock *sk;
5 | struct msghdr *msg;
6 | size_t len;
7 | int nonblock;
8 | int flags;
9 | int *addr_len;
10 | };
11 |
12 | SEC("kprobe/tcp_recvmsg")
13 | int trace_tcp_recvmsg(struct tcp_recvmsg_args *ctx) {
14 | u64 cgroup_id = bpf_get_current_cgroup_id();
15 | u32 pid = bpf_get_current_pid_tgid() >> 32;
16 |
17 | struct sock *sk = ctx->sk;
18 | size_t size = ctx->len;
19 |
20 | __u64 err;
21 | __be32 saddr;
22 | __be32 daddr;
23 | __be16 sport;
24 | __be16 dport;
25 |
26 | err = bpf_probe_read(&saddr, sizeof(saddr), &sk->__sk_common.skc_rcv_saddr);
27 | if (err != 0)
28 | return 0;
29 | err = bpf_probe_read(&daddr, sizeof(daddr), &sk->__sk_common.skc_daddr);
30 | if (err != 0)
31 | return 0;
32 | err = bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
33 | if (err != 0)
34 | return 0;
35 | err = bpf_probe_read(&sport, sizeof(sport), &sk->__sk_common.skc_num);
36 | if (err != 0)
37 | return 0;
38 |
39 | if (is_local_ip(saddr) || is_local_ip(daddr)) {
40 | return 0;
41 | }
42 |
43 | struct network_event e = {};
44 | e.pid = pid;
45 | e.cgroup_id = cgroup_id;
46 | e.size = size;
47 | e.saddr = saddr;
48 | e.daddr = daddr;
49 | e.sport = sport;
50 | e.dport = dport;
51 | e.direction = DIRECTION_INBOUND;
52 | e.protocol = PROTOCOL_TCP;
53 |
54 | bpf_ringbuf_output(&network_events_rb, &e, sizeof(e), BPF_RB_FORCE_WAKEUP);
55 | return 0;
56 | }
57 |
58 | struct tcp_sendmsg_args {
59 | struct sock *sk;
60 | struct msghdr *msg;
61 | size_t size;
62 | };
63 |
64 | SEC("kprobe/tcp_sendmsg")
65 | int trace_tcp_sendmsg(struct tcp_sendmsg_args *ctx) {
66 | u64 cgroup_id = bpf_get_current_cgroup_id();
67 | u32 pid = bpf_get_current_pid_tgid() >> 32;
68 | struct sock *sk = ctx->sk;
69 | size_t size = ctx->size;
70 |
71 | __u64 err;
72 | __be32 saddr;
73 | __be32 daddr;
74 | __be16 sport;
75 | __be16 dport;
76 |
77 | err = bpf_probe_read(&saddr, sizeof(saddr), &sk->__sk_common.skc_rcv_saddr);
78 | if (err != 0)
79 | return 0;
80 | err = bpf_probe_read(&daddr, sizeof(daddr), &sk->__sk_common.skc_daddr);
81 | if (err != 0)
82 | return 0;
83 | err = bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
84 | if (err != 0)
85 | return 0;
86 | err = bpf_probe_read(&sport, sizeof(sport), &sk->__sk_common.skc_num);
87 | if (err != 0)
88 | return 0;
89 |
90 | if (is_local_ip(saddr) || is_local_ip(daddr)) {
91 | return 0;
92 | }
93 |
94 | struct network_event e = {};
95 | e.pid = pid;
96 | e.cgroup_id = cgroup_id;
97 | e.size = size;
98 | e.saddr = saddr;
99 | e.daddr = daddr;
100 | e.sport = sport;
101 | e.dport = dport;
102 | e.direction = DIRECTION_OUTBOUND;
103 | e.protocol = PROTOCOL_TCP;
104 |
105 | bpf_ringbuf_output(&network_events_rb, &e, sizeof(e), BPF_RB_FORCE_WAKEUP);
106 | return 0;
107 | }
108 |
--------------------------------------------------------------------------------
/internal/bpf/attacher.go:
--------------------------------------------------------------------------------
1 | package bpf
2 |
3 | import (
4 | "fmt"
5 | "log/slog"
6 |
7 | "github.com/cilium/ebpf"
8 | "github.com/cilium/ebpf/link"
9 | "github.com/cilium/ebpf/ringbuf"
10 | "github.com/cilium/ebpf/rlimit"
11 | )
12 |
13 | // Define a Kernel BPF context.
14 | type KBContext struct {
15 | SyscallRingBuffer *ringbuf.Reader
16 | NetworkRingBuffer *ringbuf.Reader
17 |
18 | Tps []link.Link
19 | Kps []link.Link
20 | }
21 |
22 | func Attach(
23 | log *slog.Logger,
24 | bpfProgramElf string,
25 | ) (*KBContext, error) {
26 | if err := rlimit.RemoveMemlock(); err != nil {
27 | return nil, fmt.Errorf("failed to remove memlock limit: %w", err)
28 | }
29 |
30 | spec, err := ebpf.LoadCollectionSpec(bpfProgramElf)
31 | if err != nil {
32 | return nil, fmt.Errorf("failed to create eBPF program: %w", err)
33 | }
34 |
35 | coll, err := ebpf.NewCollection(spec)
36 | if err != nil {
37 | return nil, fmt.Errorf("failed to create eBPF collection: %w", err)
38 | }
39 | defer coll.Close()
40 |
41 | log.Info("Loaded eBPF program", "programs", coll.Programs)
42 | log.Info("Loaded eBPF maps", "maps", coll.Maps)
43 |
44 | err = registerWhitelistedSyscalls(log, coll.Maps)
45 | if err != nil {
46 | return nil, fmt.Errorf(
47 | "failed to register whitelisted syscalls: %w",
48 | err,
49 | )
50 | }
51 |
52 | syscallRingBuffer, err := ringbuf.NewReader(
53 | coll.Maps["syscall_events_rb"],
54 | )
55 | if err != nil {
56 | return nil, fmt.Errorf("failed to create ring buffer: %w", err)
57 | }
58 |
59 | networkRingBuffer, err := ringbuf.NewReader(
60 | coll.Maps["network_events_rb"],
61 | )
62 | if err != nil {
63 | err2 := syscallRingBuffer.Close()
64 |
65 | if err2 != nil {
66 | log.With("error", err2).
67 | Error("Failed to close ring buffer")
68 | }
69 |
70 | return nil, fmt.Errorf("failed to create ring buffer: %w", err)
71 | }
72 |
73 | tps, err := attachTracepoints(log, coll)
74 | if err != nil {
75 | err2 := syscallRingBuffer.Close()
76 | if err2 != nil {
77 | log.With("error", err2).
78 | Error("Failed to close perf reader")
79 | }
80 |
81 | err2 = networkRingBuffer.Close()
82 | if err2 != nil {
83 | log.With("error", err2).
84 | Error("Failed to close perf reader")
85 | }
86 |
87 | return nil, fmt.Errorf("failed to attach tps: %w", err)
88 | }
89 |
90 | kps, err := attachKProbes(log, coll)
91 | if err != nil {
92 | err2 := syscallRingBuffer.Close()
93 | if err2 != nil {
94 | log.With("error", err2).
95 | Error("Failed to close perf reader")
96 | }
97 |
98 | err2 = networkRingBuffer.Close()
99 | if err2 != nil {
100 | log.With("error", err2).
101 | Error("Failed to close perf reader")
102 | }
103 |
104 | for _, tp := range tps {
105 | tp.Close()
106 | }
107 |
108 | return nil, fmt.Errorf("failed to attach kps: %w", err)
109 | }
110 |
111 | return &KBContext{
112 | SyscallRingBuffer: syscallRingBuffer,
113 | NetworkRingBuffer: networkRingBuffer,
114 | Tps: tps,
115 | Kps: kps,
116 | }, nil
117 | }
118 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
15 | do not have permission to do that, you may request the second reviewer to merge it for you.
16 |
17 | ## Code of Conduct
18 |
19 | ### Our Pledge
20 |
21 | In the interest of fostering an open and welcoming environment, we as
22 | contributors and maintainers pledge to making participation in our project and
23 | our community a harassment-free experience for everyone, regardless of age, body
24 | size, disability, ethnicity, gender identity and expression, level of experience,
25 | nationality, personal appearance, race, religion, or sexual identity and
26 | orientation.
27 |
28 | ### Our Standards
29 |
30 | Examples of behavior that contributes to creating a positive environment
31 | include:
32 |
33 | * Using welcoming and inclusive language
34 | * Being respectful of differing viewpoints and experiences
35 | * Gracefully accepting constructive criticism
36 | * Focusing on what is best for the community
37 | * Showing empathy towards other community members
38 |
39 | Examples of unacceptable behavior by participants include:
40 |
41 | * The use of sexualized language or imagery and unwelcome sexual attention or
42 | advances
43 | * Trolling, insulting/derogatory comments, and personal or political attacks
44 | * Public or private harassment
45 | * Publishing others' private information, such as a physical or electronic
46 | address, without explicit permission
47 | * Other conduct which could reasonably be considered inappropriate in a
48 | professional setting
49 |
50 | ### Our Responsibilities
51 |
52 | Project maintainers are responsible for clarifying the standards of acceptable
53 | behavior and are expected to take appropriate and fair corrective action in
54 | response to any instances of unacceptable behavior.
55 |
56 | Project maintainers have the right and responsibility to remove, edit, or
57 | reject comments, commits, code, wiki edits, issues, and other contributions
58 | that are not aligned to this Code of Conduct, or to ban temporarily or
59 | permanently any contributor for other behaviors that they deem inappropriate,
60 | threatening, offensive, or harmful.
61 |
62 | ### Scope
63 |
64 | This Code of Conduct applies both within project spaces and in public spaces
65 | when an individual is representing the project or its community. Examples of
66 | representing a project or community include using an official project e-mail
67 | address, posting via an official social media account, or acting as an appointed
68 | representative at an online or offline event. Representation of a project may be
69 | further defined and clarified by project maintainers.
70 |
71 | ### Enforcement
72 |
73 | All complaints will be reviewed and investigated and will result in a response that
74 | is deemed necessary and appropriate to the circumstances. The project team is
75 | obligated to maintain confidentiality with regard to the reporter of an incident.
76 | Further details of specific enforcement policies may be posted separately.
77 |
78 | Project maintainers who do not follow or enforce the Code of Conduct in good
79 | faith may face temporary or permanent repercussions as determined by other
80 | members of the project's leadership.
81 |
82 | ### Attribution
83 |
84 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
85 | available at [http://contributor-covenant.org/version/1/4][version]
86 |
87 | [homepage]: http://contributor-covenant.org
88 | [version]: http://contributor-covenant.org/version/1/4/
89 |
--------------------------------------------------------------------------------
/internal/app/app.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "flag"
7 | "fmt"
8 | "log/slog"
9 |
10 | "github.com/nullswan/bpfsnitch/internal/bpf"
11 | bpfarch "github.com/nullswan/bpfsnitch/internal/bpf/arch"
12 | "github.com/nullswan/bpfsnitch/internal/kernel"
13 | "github.com/nullswan/bpfsnitch/internal/metrics"
14 | "github.com/nullswan/bpfsnitch/internal/profile"
15 | "github.com/nullswan/bpfsnitch/internal/sig"
16 | "github.com/nullswan/bpfsnitch/internal/workload"
17 | "github.com/nullswan/bpfsnitch/pkg/lru"
18 | )
19 |
20 | const (
21 | bpfProgramElf = bpfarch.BpfProgramElf
22 | cacheBannedSz = 1000
23 | cachePidToShaSz = 1000
24 | defaultPrometheusPort = 9090
25 | minKernelVersion = "5.8"
26 | defaultMountedProcPath = "/host_proc"
27 | )
28 |
29 | func Run(
30 | log *slog.Logger,
31 | ) error {
32 | kernelVersion, err := kernel.GetKernelVersion()
33 | if err != nil {
34 | return fmt.Errorf("failed to get kernel version: %w", err)
35 | }
36 |
37 | if kernel.CompareVersions(kernelVersion, minKernelVersion) < 0 {
38 | return fmt.Errorf(
39 | "kernel version %s is not supported, minimum is %s",
40 | kernelVersion,
41 | minKernelVersion,
42 | )
43 | }
44 |
45 | if !workload.IsSocketPresent() {
46 | return errors.New("runtime socket not found")
47 | }
48 |
49 | var enablePprof bool
50 | flag.BoolVar(&enablePprof, "pprof", false, "Enable pprof")
51 |
52 | var enableProfiling bool
53 | flag.BoolVar(&enableProfiling, "profiling", false, "Enable profiling")
54 |
55 | var prometheusPort uint64
56 | flag.Uint64Var(
57 | &prometheusPort,
58 | "prometheus-port",
59 | defaultPrometheusPort,
60 | "Prometheus port",
61 | )
62 |
63 | flag.Parse()
64 |
65 | if enableProfiling {
66 | log.Info("Profiling enabled")
67 | err := profile.SetupProfiling(log)
68 | if err != nil {
69 | return fmt.Errorf("failed to setup profiling: %w", err)
70 | }
71 | }
72 |
73 | bpfCtx, err := bpf.Attach(log, bpfProgramElf)
74 | if err != nil {
75 | return fmt.Errorf("failed while attaching bpf: %w", err)
76 | }
77 |
78 | ctx, cancel := context.WithCancel(context.Background())
79 | defer cancel()
80 |
81 | // Set up signal handling to cancel context on termination.
82 | sig.SetupHandler(cancel, bpfCtx, log)
83 |
84 | metrics.RegisterMetrics()
85 | if enablePprof {
86 | log.Info("pprof enabled")
87 | profile.SetupPprof()
88 | }
89 |
90 | go metrics.StartServer(log, cancel, prometheusPort)
91 |
92 | deletedPodChan := make(chan string)
93 | shaResolver, err := workload.NewShaResolver(log, deletedPodChan)
94 | if err != nil {
95 | return fmt.Errorf("failed to create sha resolver: %w", err)
96 | }
97 | syscallEventChan := make(chan *bpf.SyscallEvent)
98 | networkEventChan := make(chan *bpf.NetworkEvent)
99 | go bpf.ConsumeEvents(ctx, log, bpfCtx.SyscallRingBuffer, syscallEventChan)
100 | go bpf.ConsumeEvents(ctx, log, bpfCtx.NetworkRingBuffer, networkEventChan)
101 |
102 | go deletePods(ctx, log, deletedPodChan)
103 |
104 | bannedCgroupIDs := lru.New[uint64, struct{}](cacheBannedSz)
105 | pidToShaLRU := lru.New[uint64, string](cachePidToShaSz)
106 |
107 | log.
108 | With("proc_path", defaultMountedProcPath).
109 | Info("Starting event processor")
110 |
111 | for {
112 | select {
113 | case <-ctx.Done():
114 | log.Info("Context done, exiting")
115 | return nil
116 | case event := <-networkEventChan:
117 | pod, err := workload.ResolvePod(
118 | event.Pid,
119 | event.CgroupID,
120 | pidToShaLRU,
121 | bannedCgroupIDs,
122 | shaResolver,
123 | defaultMountedProcPath,
124 | log,
125 | )
126 | if err != nil {
127 | if !errors.Is(err, workload.ErrCgroupIDBanned) {
128 | log.With("error", err).Debug("failed to resolve pod")
129 | }
130 | continue
131 | }
132 |
133 | bpf.ProcessNetworkEvent(event, pod, log)
134 | case event := <-syscallEventChan:
135 | pod, err := workload.ResolvePod(
136 | event.Pid,
137 | event.CgroupID,
138 | pidToShaLRU,
139 | bannedCgroupIDs,
140 | shaResolver,
141 | defaultMountedProcPath,
142 | log,
143 | )
144 | if err != nil {
145 | if !errors.Is(err, workload.ErrCgroupIDBanned) {
146 | log.With("error", err).
147 | Debug("failed to resolve pod")
148 | }
149 | continue
150 | }
151 |
152 | bpf.ProcessSyscallEvent(event, pod, log)
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/deployments/daemonset.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: DaemonSet
3 | metadata:
4 | name: bpfsnitch-agent
5 | namespace: kube-system
6 | labels:
7 | k8s-app: bpfsnitch-agent
8 | kubernetes.io/cluster-service: "true"
9 | spec:
10 | selector:
11 | matchLabels:
12 | k8s-app: bpfsnitch-agent
13 | kubernetes.io/cluster-service: "true"
14 | template:
15 | metadata:
16 | labels:
17 | k8s-app: bpfsnitch-agent
18 | kubernetes.io/cluster-service: "true"
19 | spec:
20 | affinity:
21 | nodeAffinity:
22 | requiredDuringSchedulingIgnoredDuringExecution:
23 | nodeSelectorTerms:
24 | - matchExpressions:
25 | - key: kubernetes.io/os
26 | operator: In
27 | values:
28 | - linux
29 | - key: kubernetes.io/arch
30 | operator: In
31 | values:
32 | - amd64
33 | - matchExpressions:
34 | - key: kubernetes.io/os
35 | operator: In
36 | values:
37 | - linux
38 | - key: kubernetes.io/arch
39 | operator: In
40 | values:
41 | - arm64
42 | - matchExpressions:
43 | - key: kubernetes.io/os
44 | operator: In
45 | values:
46 | - linux
47 | - key: kubernetes.io/arch
48 | operator: In
49 | values:
50 | - arm
51 | initContainers:
52 | - name: mount-bpf-fs
53 | image: alpine:3.20
54 | command:
55 | - /bin/sh
56 | - "-c"
57 | - "--"
58 | args:
59 | - >-
60 | mount | grep "/sys/fs/bpf type bpf" || mount -t bpf bpf /sys/fs/bpf
61 | volumeMounts:
62 | - name: bpf-maps
63 | mountPath: /sys/fs/bpf
64 | mountPropagation: Bidirectional
65 | terminationMessagePath: /dev/termination-log
66 | terminationMessagePolicy: FallbackToLogsOnError
67 | imagePullPolicy: IfNotPresent
68 | securityContext:
69 | privileged: true
70 | containers:
71 | - name: bpfsnitch-agent
72 | image: nullswan/bpfsnitch:latest
73 | imagePullPolicy: IfNotPresent
74 | args:
75 | - "./bpfsnitch"
76 | ports:
77 | - containerPort: 9090
78 | protocol: TCP
79 | securityContext:
80 | privileged: true
81 | capabilities:
82 | # TODO: sort out the capabilities
83 | add:
84 | - CHOWN
85 | - KILL
86 | - NET_ADMIN
87 | - NET_RAW
88 | - IPC_LOCK
89 | - SYS_MODULE
90 | - SYS_ADMIN
91 | - SYS_RESOURCE
92 | - DAC_OVERRIDE
93 | - FOWNER
94 | - SETGID
95 | - SETUID
96 | drop:
97 | - ALL
98 | volumeMounts:
99 | - name: bpf-maps
100 | mountPath: /sys/fs/bpf
101 | mountPropagation: HostToContainer
102 | - name: kernel-trace
103 | mountPath: /sys/kernel/tracing
104 | mountPropagation: HostToContainer
105 | - name: kernel-debug
106 | mountPath: /sys/kernel/debug
107 | mountPropagation: HostToContainer
108 | - name: host-proc
109 | mountPath: /host_proc
110 | mountPropagation: HostToContainer
111 | readOnly: true
112 | - name: containerd-sock
113 | mountPath: /run/containerd/containerd.sock
114 | mountPropagation: HostToContainer
115 | readOnly: true
116 | resources:
117 | limits:
118 | memory: "250Mi"
119 | cpu: "100m"
120 | requests:
121 | memory: "250Mi"
122 | cpu: "100m"
123 | volumes:
124 | - name: bpf-maps
125 | hostPath:
126 | path: /sys/fs/bpf
127 | type: DirectoryOrCreate
128 | - name: kernel-trace
129 | hostPath:
130 | path: /sys/kernel/tracing
131 | type: Directory
132 | - name: kernel-debug
133 | hostPath:
134 | path: /sys/kernel/debug
135 | type: Directory
136 | - name: host-proc
137 | hostPath:
138 | path: /proc
139 | type: Directory
140 | - name: containerd-sock
141 | hostPath:
142 | path: /run/containerd/containerd.sock
143 | type: Socket
144 |
--------------------------------------------------------------------------------
/internal/workload/sha_resolver.go:
--------------------------------------------------------------------------------
1 | package workload
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log/slog"
7 | "sync"
8 | "time"
9 |
10 | "github.com/nullswan/bpfsnitch/pkg/lru"
11 | "google.golang.org/grpc"
12 | runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
13 | )
14 |
15 | const (
16 | internalLRUCacheSize = 1000
17 | shaResolverTimeout = 5 * time.Second
18 | )
19 |
20 | // ContainerInfo stores information about a container's associated pod.
21 | type ContainerInfo struct {
22 | PodID string
23 | PodName string
24 | }
25 |
26 | type ContainerSha string
27 |
28 | type ShaResolver struct {
29 | containerToPodInfo *lru.Cache[ContainerSha, *ContainerInfo]
30 |
31 | logger *slog.Logger
32 | client runtimeapi.RuntimeServiceClient
33 | conn *grpc.ClientConn
34 |
35 | // Channel for expired pods
36 | ExpiredPodChan chan string
37 |
38 | // Map of known pod IDs to pod metadata
39 | knownPods map[string]*runtimeapi.PodSandbox
40 | knownPodsMutex sync.Mutex
41 | }
42 |
43 | // NewShaResolver creates a new ShaResolver instance.
44 | func NewShaResolver(
45 | logger *slog.Logger,
46 | expiredPodChan chan string,
47 | ) (*ShaResolver, error) {
48 | containerToPodInfo := lru.New[ContainerSha, *ContainerInfo](
49 | internalLRUCacheSize,
50 | )
51 |
52 | client, conn, err := getRuntimeServiceClient()
53 | if err != nil {
54 | return nil, fmt.Errorf("failed to get runtime service client: %w", err)
55 | }
56 |
57 | return &ShaResolver{
58 | containerToPodInfo: containerToPodInfo,
59 | client: client,
60 | conn: conn,
61 | logger: logger,
62 | ExpiredPodChan: expiredPodChan,
63 | knownPods: make(map[string]*runtimeapi.PodSandbox),
64 | knownPodsMutex: sync.Mutex{},
65 | }, nil
66 | }
67 |
68 | // Resolve returns the pod name associated with a given container SHA.
69 | func (r *ShaResolver) Resolve(inputSha string) (string, error) {
70 | sha := ContainerSha(inputSha)
71 |
72 | v, ok := r.containerToPodInfo.Get(sha)
73 | if ok {
74 | return v.PodName, nil
75 | }
76 |
77 | err := r.UpdateCache()
78 | if err != nil {
79 | return "", fmt.Errorf("failed to update cache: %w", err)
80 | }
81 |
82 | v, ok = r.containerToPodInfo.Get(sha)
83 | if !ok {
84 | return "", fmt.Errorf("sha %s not found in cache", sha)
85 | }
86 |
87 | return v.PodName, nil
88 | }
89 |
90 | // UpdateCache updates the cache with the latest pod and container information.
91 | func (r *ShaResolver) UpdateCache() error {
92 | ctx, cancel := context.WithTimeout(context.Background(), shaResolverTimeout)
93 | defer cancel()
94 |
95 | pods, err := getPods(ctx, r.client)
96 | if err != nil {
97 | return fmt.Errorf("failed to list pods: %w", err)
98 | }
99 |
100 | currentPods := make(map[string]*runtimeapi.PodSandbox)
101 | for _, pod := range pods {
102 | currentPods[pod.Id] = pod
103 | }
104 |
105 | r.detectExpiredPods(currentPods)
106 |
107 | r.knownPodsMutex.Lock()
108 | r.knownPods = currentPods
109 | r.knownPodsMutex.Unlock()
110 |
111 | containers, err := getContainers(ctx, r.client)
112 | if err != nil {
113 | return fmt.Errorf("failed to list containers: %w", err)
114 | }
115 |
116 | for _, container := range containers {
117 | containerID := container.GetId()
118 | podID := container.GetPodSandboxId()
119 |
120 | pod, ok := currentPods[podID]
121 | if !ok {
122 | r.logger.Warn(
123 | "container has no associated pod",
124 | "container_id", containerID,
125 | "pod_id", podID,
126 | )
127 | continue
128 | }
129 |
130 | r.containerToPodInfo.Put(
131 | ContainerSha(containerID),
132 | &ContainerInfo{
133 | PodID: podID,
134 | PodName: pod.GetMetadata().GetName(),
135 | },
136 | )
137 | }
138 | return nil
139 | }
140 |
141 | // detectExpiredPods detects pods that are no longer running and sends them to the expired pod channel.
142 | func (r *ShaResolver) detectExpiredPods(
143 | currentPods map[string]*runtimeapi.PodSandbox,
144 | ) {
145 | r.knownPodsMutex.Lock()
146 | defer r.knownPodsMutex.Unlock()
147 |
148 | for podID, pod := range r.knownPods {
149 | if _, exists := currentPods[podID]; !exists {
150 | r.logger.Info(
151 | "Pod expired",
152 | "pod_id",
153 | podID,
154 | "pod_name",
155 | pod.GetMetadata().GetName(),
156 | )
157 |
158 | select {
159 | case r.ExpiredPodChan <- podID:
160 | default:
161 | r.logger.Warn("Expired pod channel is full", "pod_id", podID)
162 | }
163 |
164 | r.removePodFromCache(podID)
165 | }
166 | }
167 | }
168 |
169 | // removePodFromCache removes all containers associated with a given pod ID from the cache.
170 | func (r *ShaResolver) removePodFromCache(podID string) {
171 | keysToRemove := []ContainerSha{}
172 |
173 | r.containerToPodInfo.ForEach(
174 | func(containerID ContainerSha, info *ContainerInfo) bool {
175 | if info.PodID == podID {
176 | keysToRemove = append(keysToRemove, containerID)
177 | }
178 | return true
179 | },
180 | )
181 |
182 | for _, key := range keysToRemove {
183 | r.containerToPodInfo.Remove(key)
184 | }
185 | }
186 |
187 | // Close closes the ShaResolver instance.
188 | func (r *ShaResolver) Close() {
189 | r.conn.Close()
190 | }
191 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8 |
9 | ## Our Standards
10 |
11 | Examples of behavior that contributes to a positive environment for our community include:
12 |
13 | * Demonstrating empathy and kindness toward other people
14 | * Being respectful of differing opinions, viewpoints, and experiences
15 | * Giving and gracefully accepting constructive feedback
16 | * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17 | * Focusing on what is best not just for us as individuals, but for the overall community
18 |
19 | Examples of unacceptable behavior include:
20 |
21 | * The use of sexualized language or imagery, and sexual attention or advances of any kind
22 | * Trolling, insulting or derogatory comments, and personal or political attacks
23 | * Public or private harassment
24 | * Publishing others’ private information, such as a physical or email address, without their explicit permission
25 | * Other conduct which could reasonably be considered inappropriate in a professional setting
26 |
27 | ## Enforcement Responsibilities
28 |
29 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
32 |
33 | ## Scope
34 |
35 | This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
36 |
37 | ## Enforcement
38 |
39 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at pro@nullswan.io. All complaints will be reviewed and investigated promptly and fairly.
40 |
41 | All community leaders are obligated to respect the privacy and security of the reporter of any incident.
42 |
43 | ## Enforcement Guidelines
44 |
45 | Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
46 |
47 | ### 1. Correction
48 |
49 | **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
50 |
51 | **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
52 |
53 | ### 2. Warning
54 |
55 | **Community Impact**: A violation through a single incident or series of actions.
56 |
57 | **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
58 |
59 | ### 3. Temporary Ban
60 |
61 | **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
62 |
63 | **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
64 |
65 | ### 4. Permanent Ban
66 |
67 | **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
68 |
69 | **Consequence**: A permanent ban from any sort of public interaction within the community.
70 |
71 | ## Attribution
72 |
73 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
74 |
75 | Community Impact Guidelines were inspired by [Mozilla’s code of conduct enforcement ladder](https://github.com/mozilla/diversity).
76 |
77 | [homepage]: https://www.contributor-covenant.org
78 |
79 | For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
--------------------------------------------------------------------------------
/pkg/network/converter_test.go:
--------------------------------------------------------------------------------
1 | package network
2 |
3 | import (
4 | "net"
5 | "reflect"
6 | "testing"
7 | )
8 |
9 | func TestIntToIP(t *testing.T) {
10 | t.Parallel()
11 | tests := []struct {
12 | name string
13 | input uint32
14 | expected net.IP
15 | }{
16 | {
17 | name: "Localhost",
18 | input: 0x7f000001,
19 | expected: net.IPv4(127, 0, 0, 1),
20 | },
21 | {
22 | name: "Broadcast",
23 | input: 0xffffffff,
24 | expected: net.IPv4(255, 255, 255, 255),
25 | },
26 | {
27 | name: "Zero",
28 | input: 0x00000000,
29 | expected: net.IPv4(0, 0, 0, 0),
30 | },
31 | {
32 | name: "PrivateNetwork192",
33 | input: 0xc0a80001,
34 | expected: net.IPv4(192, 168, 0, 1),
35 | },
36 | {
37 | name: "PrivateNetwork10",
38 | input: 0x0a000001,
39 | expected: net.IPv4(10, 0, 0, 1),
40 | },
41 | {
42 | name: "PrivateNetwork172",
43 | input: 0xac100001,
44 | expected: net.IPv4(172, 16, 0, 1),
45 | },
46 | {
47 | name: "Multicast",
48 | input: 0xe00000fb,
49 | expected: net.IPv4(224, 0, 0, 251),
50 | },
51 | {
52 | name: "GoogleDNS",
53 | input: 0x08080808,
54 | expected: net.IPv4(8, 8, 8, 8),
55 | },
56 | {
57 | name: "CloudflareDNS",
58 | input: 0x01010101,
59 | expected: net.IPv4(1, 1, 1, 1),
60 | },
61 | {
62 | name: "RandomIP1",
63 | input: 0x12345678,
64 | expected: net.IPv4(18, 52, 86, 120),
65 | },
66 | {
67 | name: "RandomIP2",
68 | input: 0x87654321,
69 | expected: net.IPv4(135, 101, 67, 33),
70 | },
71 | {
72 | name: "RandomIP3",
73 | input: 0xaabbccdd,
74 | expected: net.IPv4(170, 187, 204, 221),
75 | },
76 | {
77 | name: "MaxValue",
78 | input: 0xffffffff,
79 | expected: net.IPv4(255, 255, 255, 255),
80 | },
81 | {
82 | name: "MinValue",
83 | input: 0x00000000,
84 | expected: net.IPv4(0, 0, 0, 0),
85 | },
86 | }
87 |
88 | for _, test := range tests {
89 | test := test // capture range variable
90 | t.Run(test.name, func(t *testing.T) {
91 | t.Parallel()
92 | result := IntToIP(test.input)
93 | if !result.Equal(test.expected) {
94 | t.Errorf(
95 | "IntToIP(%#x) = %s; want %s",
96 | test.input,
97 | result,
98 | test.expected,
99 | )
100 | }
101 | })
102 | }
103 | }
104 |
105 | func TestNtohs(t *testing.T) {
106 | t.Parallel()
107 | tests := []struct {
108 | name string
109 | input uint16
110 | expected uint16
111 | }{
112 | {
113 | name: "Zero",
114 | input: 0x0000,
115 | expected: 0x0000,
116 | },
117 | {
118 | name: "MaxValue",
119 | input: 0xffff,
120 | expected: 0xffff,
121 | },
122 | {
123 | name: "Port80",
124 | input: 0x5000,
125 | expected: 0x0050,
126 | },
127 | {
128 | name: "Port443",
129 | input: 0xbb01,
130 | expected: 0x01bb,
131 | },
132 | {
133 | name: "Port22",
134 | input: 0x1600,
135 | expected: 0x0016,
136 | },
137 | {
138 | name: "RandomValue1",
139 | input: 0x3412,
140 | expected: 0x1234,
141 | },
142 | {
143 | name: "RandomValue2",
144 | input: 0x7856,
145 | expected: 0x5678,
146 | },
147 | {
148 | name: "RandomValue3",
149 | input: 0xa1b2,
150 | expected: 0xb2a1,
151 | },
152 | {
153 | name: "HighByteZero",
154 | input: 0x00ff,
155 | expected: 0xff00,
156 | },
157 | {
158 | name: "LowByteZero",
159 | input: 0xff00,
160 | expected: 0x00ff,
161 | },
162 | {
163 | name: "AlternatingBits",
164 | input: 0xaa55,
165 | expected: 0x55aa,
166 | },
167 | {
168 | name: "Palindrome",
169 | input: 0x1a1a,
170 | expected: 0x1a1a,
171 | },
172 | }
173 |
174 | for _, test := range tests {
175 | test := test // capture range variable
176 | t.Run(test.name, func(t *testing.T) {
177 | t.Parallel()
178 | result := Ntohs(test.input)
179 | if result != test.expected {
180 | t.Errorf(
181 | "Ntohs(%#x) = %#x; want %#x",
182 | test.input,
183 | result,
184 | test.expected,
185 | )
186 | }
187 | })
188 | }
189 | }
190 |
191 | func TestNtohl(t *testing.T) {
192 | t.Parallel()
193 | tests := []struct {
194 | name string
195 | input uint32
196 | expected uint32
197 | }{
198 | {
199 | name: "Zero",
200 | input: 0x00000000,
201 | expected: 0x00000000,
202 | },
203 | {
204 | name: "MaxValue",
205 | input: 0xffffffff,
206 | expected: 0xffffffff,
207 | },
208 | {
209 | name: "Localhost",
210 | input: 0x0100007f,
211 | expected: 0x7f000001,
212 | },
213 | {
214 | name: "GoogleDNS",
215 | input: 0x08080808,
216 | expected: 0x08080808,
217 | },
218 | {
219 | name: "PrivateNetwork192",
220 | input: 0xC0A80001,
221 | expected: 0x0100A8C0,
222 | },
223 | {
224 | name: "RandomValue1",
225 | input: 0x78563412,
226 | expected: 0x12345678,
227 | },
228 | {
229 | name: "RandomValue2",
230 | input: 0x44332211,
231 | expected: 0x11223344,
232 | },
233 | {
234 | name: "HighBytesZero",
235 | input: 0x0000ffff,
236 | expected: 0xffff0000,
237 | },
238 | {
239 | name: "LowBytesZero",
240 | input: 0xffff0000,
241 | expected: 0x0000ffff,
242 | },
243 | {
244 | name: "AlternatingBits",
245 | input: 0xaa55aa55,
246 | expected: 0x55aa55aa,
247 | },
248 | {
249 | name: "Palindrome",
250 | input: 0x1a2b2b1a,
251 | expected: 0x1a2b2b1a,
252 | },
253 | {
254 | name: "Multicast",
255 | input: 0xfb0000e0,
256 | expected: 0xe00000fb,
257 | },
258 | {
259 | name: "EdgeCase1",
260 | input: 0x00000001,
261 | expected: 0x01000000,
262 | },
263 | {
264 | name: "EdgeCase2",
265 | input: 0x80000000,
266 | expected: 0x00000080,
267 | },
268 | }
269 |
270 | for _, test := range tests {
271 | test := test // capture range variable
272 | t.Run(test.name, func(t *testing.T) {
273 | t.Parallel()
274 | result := Ntohl(test.input)
275 | if result != test.expected {
276 | t.Errorf(
277 | "Ntohl(%#x) = %#x; want %#x",
278 | test.input,
279 | result,
280 | test.expected,
281 | )
282 | }
283 | })
284 | }
285 | }
286 |
287 | func TestIntToSubnet(t *testing.T) {
288 | t.Parallel()
289 |
290 | tests := []struct {
291 | ip uint32
292 | mask uint32
293 | output *net.IPNet
294 | }{
295 | {
296 | ip: 0xC0A80101, // 192.168.1.1
297 | mask: 0xFFFFFF00, // 255.255.255.0
298 | output: &net.IPNet{
299 | IP: net.IPv4(192, 168, 1, 0),
300 | Mask: net.IPv4Mask(255, 255, 255, 0),
301 | },
302 | },
303 | {
304 | ip: 0x0A000001, // 10.0.0.1
305 | mask: 0xFF000000, // 255.0.0.0
306 | output: &net.IPNet{
307 | IP: net.IPv4(10, 0, 0, 0),
308 | Mask: net.IPv4Mask(255, 0, 0, 0),
309 | },
310 | },
311 | {
312 | ip: 0xC0A80101, // 192.168.1.1
313 | mask: 0xFFFF0000, // 255.255.0.0
314 | output: &net.IPNet{
315 | IP: net.IPv4(192, 168, 0, 0), // Host portion is zeroed out
316 | Mask: net.IPv4Mask(255, 255, 0, 0),
317 | },
318 | },
319 | {
320 | ip: 0xC0A80101, // 192.168.1.1
321 | mask: 0xFFFFFFFF, // 255.255.255.255
322 | output: &net.IPNet{
323 | IP: net.IPv4(192, 168, 1, 1), // No part is zeroed out
324 | Mask: net.IPv4Mask(255, 255, 255, 255),
325 | },
326 | },
327 | {
328 | ip: 0x0A0A0A0A, // 10.10.10.10
329 | mask: 0xFFFFF000, // 255.255.240.0
330 | output: &net.IPNet{
331 | IP: net.IPv4(10, 10, 0, 0), // Host portion is zeroed out
332 | Mask: net.IPv4Mask(255, 255, 240, 0),
333 | },
334 | },
335 | {
336 | ip: 0xAC100202, // 172.16.2.2
337 | mask: 0xFFFFFFF0, // 255.255.255.240
338 | output: &net.IPNet{
339 | IP: net.IPv4(
340 | 172,
341 | 16,
342 | 2,
343 | 0,
344 | ), // Host portion is mostly zeroed out
345 | Mask: net.IPv4Mask(255, 255, 255, 240),
346 | },
347 | },
348 | }
349 |
350 | for _, tt := range tests {
351 | result := IntToSubnet(tt.ip, tt.mask)
352 | if !reflect.DeepEqual(result, tt.output) {
353 | t.Errorf(
354 | "IntToSubnet(%v, %v) = %v; want %v",
355 | tt.ip,
356 | tt.mask,
357 | result,
358 | tt.output,
359 | )
360 | }
361 | }
362 | }
363 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
3 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
4 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
5 | github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
6 | github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
7 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
8 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 | github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
10 | github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
11 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
12 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
13 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
14 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
15 | github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d3KGj8=
16 | github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk=
17 | github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
18 | github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
19 | github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
20 | github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
21 | github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
22 | github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
23 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
24 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
25 | github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
26 | github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
27 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
28 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
29 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
30 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
31 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
32 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
33 | github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
34 | github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
35 | github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
36 | github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
37 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
38 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
39 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
40 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
41 | github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
42 | github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
43 | github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
44 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
45 | github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0=
46 | github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
47 | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
48 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
49 | github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
50 | github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
51 | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
52 | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
53 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
54 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
55 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
56 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
57 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
58 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
59 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
60 | golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
61 | golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
62 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
63 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
64 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
65 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
66 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
67 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
68 | golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
69 | golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
70 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
71 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
72 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
73 | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
74 | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
75 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
76 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
77 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
78 | golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
79 | golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
80 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
81 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
82 | golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
83 | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
85 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
86 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
87 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
88 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
89 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
90 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
91 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
92 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
93 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
94 | google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
95 | google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
96 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
97 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
98 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
99 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
100 | k8s.io/cri-api v0.31.1 h1:x0aI8yTI7Ho4c8tpuig8NwI/MRe+VhjiYyyebC2xphQ=
101 | k8s.io/cri-api v0.31.1/go.mod h1:Po3TMAYH/+KrZabi7QiwQI4a692oZcUOUThd/rqwxrI=
102 |
--------------------------------------------------------------------------------
/pkg/lru/lru_test.go:
--------------------------------------------------------------------------------
1 | package lru
2 |
3 | import (
4 | "sync"
5 | "testing"
6 | )
7 |
8 | func TestLRUCache(t *testing.T) {
9 | t.Parallel()
10 |
11 | cache := New[int, int](2) // Create LRUCache with capacity of 2
12 |
13 | cache.Put(1, 1)
14 | cache.Put(2, 2)
15 |
16 | if value, found := cache.Get(1); !found || value != 1 {
17 | t.Errorf(
18 | "Expected key 1 to have value 1, but got value %v found %v",
19 | value,
20 | found,
21 | )
22 | }
23 |
24 | cache.Put(3, 3)
25 |
26 | if _, found := cache.Get(2); found {
27 | t.Errorf("Expected key 2 to be evicted, but it was found")
28 | }
29 |
30 | cache.Put(4, 4)
31 |
32 | if _, found := cache.Get(1); found {
33 | t.Errorf("Expected key 1 to be evicted, but it was found")
34 | }
35 |
36 | if value, found := cache.Get(3); !found || value != 3 {
37 | t.Errorf(
38 | "Expected key 3 to have value 3, but got value %v found %v",
39 | value,
40 | found,
41 | )
42 | }
43 |
44 | if value, found := cache.Get(4); !found || value != 4 {
45 | t.Errorf(
46 | "Expected key 4 to have value 4, but got value %v found %v",
47 | value,
48 | found,
49 | )
50 | }
51 | }
52 |
53 | func TestLRUCacheOverwrite(t *testing.T) {
54 | t.Parallel()
55 |
56 | cache := New[int, int](2)
57 | cache.Put(1, 1)
58 | cache.Put(1, 10)
59 | if value, found := cache.Get(1); !found || value != 10 {
60 | t.Errorf(
61 | "Expected key 1 to have value 10, but got value %v found %v",
62 | value,
63 | found,
64 | )
65 | }
66 | }
67 |
68 | func TestLRUCacheEvictionOrder(t *testing.T) {
69 | t.Parallel()
70 |
71 | cache := New[int, int](3)
72 | cache.Put(1, 1)
73 | cache.Put(2, 2)
74 | cache.Put(3, 3)
75 | cache.Get(1) // Make key 1 the most recently used
76 | cache.Put(4, 4)
77 | if _, found := cache.Get(2); found {
78 | t.Errorf("Expected key 2 to be evicted, but it was found")
79 | }
80 | }
81 |
82 | func TestLRUCacheBoundaryUsage(t *testing.T) {
83 | t.Parallel()
84 |
85 | cache := New[int, int](1)
86 | cache.Put(1, 1)
87 | if value, found := cache.Get(1); !found || value != 1 {
88 | t.Errorf(
89 | "Expected key 1 to have value 1, but got value %v found %v",
90 | value,
91 | found,
92 | )
93 | }
94 | cache.Put(2, 2)
95 | if _, found := cache.Get(1); found {
96 | t.Errorf("Expected key 1 to be evicted, but it was found")
97 | }
98 | if value, found := cache.Get(2); !found || value != 2 {
99 | t.Errorf(
100 | "Expected key 2 to have value 2, but got value %v found %v",
101 | value,
102 | found,
103 | )
104 | }
105 | }
106 |
107 | func TestLRUCacheZeroCapacity(t *testing.T) {
108 | t.Parallel()
109 |
110 | cache := New[int, int](0)
111 | cache.Put(1, 1)
112 | if value, found := cache.Get(1); !found || value != 1 {
113 | t.Errorf(
114 | "Expected key 1 to be added with value 1, but got value %v found %v",
115 | value,
116 | found,
117 | )
118 | }
119 | cache.Put(2, 2)
120 | if value, found := cache.Get(2); !found || value != 2 {
121 | t.Errorf(
122 | "Expected key 2 to be added with value 2, but got value %v found %v",
123 | value,
124 | found,
125 | )
126 | }
127 | if _, found := cache.Get(1); found {
128 | t.Errorf(
129 | "Expected key 1 to be evicted after adding key 2, but it was found",
130 | )
131 | }
132 | }
133 |
134 | func TestLRUCacheConcurrency(t *testing.T) {
135 | t.Parallel()
136 |
137 | cache := New[int, int](100) // Create LRUCache with capacity of 100
138 | wg := sync.WaitGroup{}
139 |
140 | // Function to perform a sequence of puts and gets
141 | concurrentAccess := func(start, end int) {
142 | defer wg.Done()
143 | for i := start; i < end; i++ {
144 | cache.Put(i, i)
145 | if value, found := cache.Get(i); !found || value != i {
146 | t.Errorf(
147 | "Expected key %v to have value %v, but got value %v found %v",
148 | i,
149 | i,
150 | value,
151 | found,
152 | )
153 | }
154 | }
155 | }
156 |
157 | // Perform concurrent access to the cache
158 | threads := 10
159 | for i := 0; i < threads; i++ {
160 | wg.Add(1)
161 | go concurrentAccess(i*10, (i+1)*10)
162 | }
163 |
164 | wg.Wait()
165 |
166 | // Validate the cache contents
167 | for i := 0; i < 50; i++ {
168 | if value, found := cache.Get(i); !found || value != i {
169 | t.Errorf(
170 | "Expected key %v to have value %v, but got value %v found %v",
171 | i,
172 | i,
173 | value,
174 | found,
175 | )
176 | }
177 | }
178 | }
179 |
180 | func TestLRUCacheEvictionPattern(t *testing.T) {
181 | t.Parallel()
182 |
183 | cache := New[int, int](3)
184 | cache.Put(1, 1)
185 | cache.Put(2, 2)
186 | cache.Put(3, 3)
187 | cache.Get(2)
188 | cache.Get(3)
189 | cache.Put(4, 4)
190 | if _, found := cache.Get(1); found {
191 | t.Errorf("Expected key 1 to be evicted, but it was found")
192 | }
193 | if value, found := cache.Get(2); !found || value != 2 {
194 | t.Errorf(
195 | "Expected key 2 to have value 2, but got value %v found %v",
196 | value,
197 | found,
198 | )
199 | }
200 | if value, found := cache.Get(3); !found || value != 3 {
201 | t.Errorf(
202 | "Expected key 3 to have value 3, but got value %v found %v",
203 | value,
204 | found,
205 | )
206 | }
207 | if value, found := cache.Get(4); !found || value != 4 {
208 | t.Errorf(
209 | "Expected key 4 to have value 4, but got value %v found %v",
210 | value,
211 | found,
212 | )
213 | }
214 | }
215 |
216 | func TestLRUCacheMultipleEvictions(t *testing.T) {
217 | t.Parallel()
218 |
219 | cache := New[int, int](2)
220 | cache.Put(1, 1)
221 | cache.Put(2, 2)
222 | cache.Put(3, 3) // Causes eviction of key 1
223 | cache.Put(4, 4) // Causes eviction of key 2
224 | if _, found := cache.Get(1); found {
225 | t.Errorf("Expected key 1 to be evicted, but it was found")
226 | }
227 | if _, found := cache.Get(2); found {
228 | t.Errorf("Expected key 2 to be evicted, but it was found")
229 | }
230 | if value, found := cache.Get(3); !found || value != 3 {
231 | t.Errorf(
232 | "Expected key 3 to have value 3, but got value %v found %v",
233 | value,
234 | found,
235 | )
236 | }
237 | if value, found := cache.Get(4); !found || value != 4 {
238 | t.Errorf(
239 | "Expected key 4 to have value 4, but got value %v found %v",
240 | value,
241 | found,
242 | )
243 | }
244 | }
245 |
246 | func TestLRUCacheRemove(t *testing.T) {
247 | t.Parallel()
248 |
249 | cache := New[int, int](2)
250 |
251 | cache.Put(1, 100)
252 | cache.Put(2, 200)
253 |
254 | cache.Remove(1)
255 |
256 | if _, found := cache.Get(1); found {
257 | t.Errorf("Expected key 1 to be removed, but it was found")
258 | }
259 |
260 | if value, found := cache.Get(2); !found || value != 200 {
261 | t.Errorf(
262 | "Expected key 2 to have value 200, but got value %v found %v",
263 | value,
264 | found,
265 | )
266 | }
267 |
268 | cache.Put(3, 300)
269 |
270 | if value, found := cache.Get(3); !found || value != 300 {
271 | t.Errorf(
272 | "Expected key 3 to have value 300, but got value %v found %v",
273 | value,
274 | found,
275 | )
276 | }
277 | }
278 |
279 | func TestLRUCacheForEach(t *testing.T) {
280 | t.Parallel()
281 |
282 | cache := New[int, int](3)
283 | cache.Put(1, 100)
284 | cache.Put(2, 200)
285 | cache.Put(3, 300)
286 |
287 | // Expected order: 3 (MRU), 2, 1 (LRU)
288 | expectedKeys := []int{3, 2, 1}
289 | index := 0
290 |
291 | cache.ForEach(func(key int, _ int) bool {
292 | if index >= len(expectedKeys) {
293 | t.Errorf("Iterated over more elements than expected")
294 | return false
295 | }
296 | expectedKey := expectedKeys[index]
297 | if key != expectedKey {
298 | t.Errorf(
299 | "Expected key %v at index %v, but got key %v",
300 | expectedKey,
301 | index,
302 | key,
303 | )
304 | }
305 | index++
306 | return true
307 | })
308 |
309 | if index != len(expectedKeys) {
310 | t.Errorf(
311 | "Expected to iterate over %v elements, but iterated over %v",
312 | len(expectedKeys),
313 | index,
314 | )
315 | }
316 | }
317 |
318 | func TestLRUCacheForEachEarlyExit(t *testing.T) {
319 | t.Parallel()
320 |
321 | cache := New[int, int](1)
322 | cache.Put(1, 100)
323 | cache.Put(2, 200)
324 | cache.Put(3, 300)
325 |
326 | // Expected to stop after first element
327 | index := 0
328 |
329 | cache.ForEach(func(_ int, _ int) bool {
330 | index++
331 | return false
332 | })
333 |
334 | if index != 1 {
335 | t.Errorf(
336 | "Expected to iterate over 1 element, but iterated over %v",
337 | index,
338 | )
339 | }
340 | }
341 |
342 | func TestLRUCacheForEachEmptyCache(t *testing.T) {
343 | t.Parallel()
344 |
345 | cache := New[int, int](1)
346 |
347 | called := false
348 |
349 | cache.ForEach(func(_ int, _ int) bool {
350 | called = true
351 | return true
352 | })
353 |
354 | if called {
355 | t.Errorf("Expected ForEach not to call the function on an empty cache")
356 | }
357 | }
358 |
359 | func TestLRUCacheForEachAfterOperations(t *testing.T) {
360 | t.Parallel()
361 |
362 | cache := New[int, int](3)
363 | cache.Put(1, 100) // [1]
364 | cache.Put(2, 200) // [2, 1]
365 | cache.Get(1) // Make key 1 MRU [1, 2]
366 | cache.Put(3, 300) // [3, 1, 2]
367 | cache.Get(2) // Now key 2 is MRU [2, 3, 1]
368 | cache.Put(4, 400) // Evicts key 3 (LRU) [4, 2, 3]
369 |
370 | // Expected order: 2 (MRU), 1, 4
371 | expectedKeys := []int{4, 2, 3}
372 | index := 0
373 |
374 | cache.ForEach(func(key int, _ int) bool {
375 | if index >= len(expectedKeys) {
376 | t.Errorf("Iterated over more elements than expected")
377 | return false
378 | }
379 | expectedKey := expectedKeys[index]
380 | if key != expectedKey {
381 | t.Errorf(
382 | "Expected key %v at index %v, but got key %v",
383 | expectedKey,
384 | index,
385 | key,
386 | )
387 | }
388 | index++
389 | return true
390 | })
391 |
392 | if index != len(expectedKeys) {
393 | t.Errorf(
394 | "Expected to iterate over %v elements, but iterated over %v",
395 | len(expectedKeys),
396 | index,
397 | )
398 | }
399 | }
400 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bpfsnitch
2 |
3 | [](LICENSE) [](https://goreportcard.com/report/github.com/nullswan/bpfsnitch)
4 |
5 | bpfsnitch is an open-source, real-time monitoring tool for Linux systems and Kubernetes clusters. Inspired by GlassWire, bpfsnitch leverages eBPF (extended Berkeley Packet Filter) technology to provide observability at the lowest level possible by tracking system calls and network activities. It is capable of monitoring every syscall and network event in real-time, offering valuable insights into what's happening inside your systems and containers.
6 |
7 | ---
8 |
9 | ## Table of Contents
10 |
11 | - [bpfsnitch](#bpfsnitch)
12 | - [Table of Contents](#table-of-contents)
13 | - [Features](#features)
14 | - [Prerequisites](#prerequisites)
15 | - [Installation](#installation)
16 | - [On Kubernetes Clusters](#on-kubernetes-clusters)
17 | - [Metrics](#metrics)
18 | - [Key Metrics](#key-metrics)
19 | - [Example Metrics Output](#example-metrics-output)
20 | - [Performance](#performance)
21 | - [Configuration (soon)](#configuration-soon)
22 | - [Customizing Syscall Monitoring](#customizing-syscall-monitoring)
23 | - [Predefined Syscalls](#predefined-syscalls)
24 | - [Educational Value](#educational-value)
25 | - [License](#license)
26 | - [Future Plans](#future-plans)
27 | - [Contact](#contact)
28 | - [Acknowledgments](#acknowledgments)
29 | - [Join the Community](#join-the-community)
30 |
31 | ---
32 |
33 | ## Features
34 |
35 | - **Real-Time Monitoring**: Track every syscall and network event as they happen.
36 | - **eBPF Powered**: Utilizes eBPF for efficient, low-overhead monitoring at the kernel level.
37 | - **Kubernetes Support**: Deployable as a DaemonSet to monitor your entire Kubernetes cluster.
38 | - **Customizable Syscall Monitoring**: Predefined list of critical syscalls with plans to provide a configurable syscall whitelist.
39 | - **Prometheus Integration**: Exposes metrics via a Prometheus scrape endpoint for easy integration with your monitoring stack.
40 | - **Pod Awareness**: Labels metrics with pod names for granular visibility.
41 | - **Open Source**: Released under the GPL license, encouraging community collaboration.
42 |
43 | ---
44 |
45 | ## Prerequisites
46 |
47 | - **Linux Kernel with eBPF Support**: bpfsnitch requires a Linux kernel version that supports eBPF (version 5.8 or higher recommended).
48 | - **eBPF Libraries**: Ensure that `libbpf` and related dependencies are installed.
49 | - **Prometheus**: For metrics scraping and monitoring.
50 | - **Container Runtime**: Supports Docker and Containerd Kubernetes environments.
51 |
52 | ---
53 |
54 | ## Installation
55 |
56 | ### On Kubernetes Clusters
57 |
58 | Deploy bpfsnitch as a DaemonSet to monitor all nodes in your cluster.
59 |
60 | 1. Apply the DaemonSet Manifest
61 |
62 | ```bash
63 | curl -s https://raw.githubusercontent.com/nullswan/bpfsnitch/main/deployments/daemonset.yaml | kubectl apply -f -
64 | ```
65 |
66 | ## Metrics
67 |
68 | bpfsnitch exposes a variety of Prometheus metrics, providing insights into syscalls and network activities.
69 |
70 | ### Key Metrics
71 |
72 | - Syscall Counters: Counts of specific syscalls made by processes or pods.
73 | - Network Bytes Counters: Total bytes sent and received, labeled by pod and remote subnets.
74 | - Network Packets Counters: Total packets sent and received.
75 | - DNS Query Counters: Number of DNS queries made by pods.
76 |
77 | ### Example Metrics Output
78 |
79 | ```perl
80 | # HELP bpfsnitch_dns_query_counter Number of DNS queries
81 | # TYPE bpfsnitch_dns_query_counter counter
82 | bpfsnitch_dns_query_counter{container="kube-proxy-cwn8r"} 23
83 |
84 | # HELP bpfsnitch_network_received_bytes_counter Number of bytes received
85 | # TYPE bpfsnitch_network_received_bytes_counter counter
86 | bpfsnitch_network_received_bytes_counter{pod="nginx-7b9f54988c-2tpbd",remote_subnet="0.0.0.0/24"} 1334512
87 |
88 | # HELP bpfsnitch_network_received_packets_counter Number of packets received
89 | # TYPE bpfsnitch_network_received_packets_counter counter
90 | bpfsnitch_network_received_packets_counter{pod="nginx-7b9f54988c-2tpbd",remote_subnet="0.0.0.0/24"} 623
91 |
92 | # HELP bpfsnitch_network_sent_bytes_counter Number of bytes sent
93 | # TYPE bpfsnitch_network_sent_bytes_counter counter
94 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.3.0/24"} 1293500
95 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.97.0/24"} 80
96 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.111.0/24"} 310
97 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.108.0/24"} 65
98 |
99 | # HELP bpfsnitch_network_sent_packets_counter Number of packets sent
100 | # TYPE bpfsnitch_network_sent_packets_counter counter
101 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.3.0/24"} 1529
102 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.97.0/24"} 1
103 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.111.0/24"} 3
104 | bpfsnitch_network_sent_packets_counter{pod="kube-proxy-cwn8r",remote_subnet="1.2.108.0/24"} 1
105 |
106 | # HELP bpfsnitch_syscall_counter Number of syscalls
107 | # TYPE bpfsnitch_syscall_counter counter
108 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="arch_prctl"} 520
109 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="bind"} 2713
110 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="clone"} 818
111 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="connect"} 264
112 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="getrandom"} 578
113 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="getsockname"} 2845
114 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="read"} 16424
115 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="recvmsg"} 56939
116 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="sendmsg"} 443
117 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="sendto"} 32007
118 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="setsockopt"} 819
119 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="socket"} 2845
120 | bpfsnitch_syscall_counter{pod="kube-proxy-cwn8r",syscall="wait4"} 818
121 | ```
122 |
123 | ## Performance
124 |
125 | Starting from v0.1.0, bpfsnitch is built to be lightweight and efficient using eBPF technology. It monitors syscalls and network events at the kernel level, providing real-time insights with minimal system impact.
126 |
127 | In production, bpfsnitch typically uses an average of 5ms of CPU per 60-second scrape and maintains a memory footprint of up to `250MB`. It is statically bound to a maximum of `100ms` CPU usage, ensuring consistent performance regardless of system configuration or workload. See the [DaemonSet resources](https://github.com/search?q=repo%3Anullswan/bpfsnitch%20resources&type=code)
128 |
129 | To monitor bpfsnitch's performance in real-time, start it with the -pprof flag to expose a pprof server. Access live profiling data at the /debug/pprof route to analyze CPU and memory usage and optimize performance as needed.
130 |
131 | We are committed to providing detailed performance benchmarks and optimization tips in future releases to help you maximize bpfsnitch's benefits.
132 |
133 | ## Configuration (soon)
134 |
135 | ### Customizing Syscall Monitoring
136 |
137 | bpfsnitch comes with a predefined list of syscalls to monitor, focusing on critical operations that could affect system security or stability. We plan to provide a configurable syscall whitelist in future releases, allowing you to tailor monitoring to your specific needs.
138 |
139 | #### Predefined Syscalls
140 |
141 | ```go
142 | var WhitelistedSyscalls = []int{
143 | SyscallToId["clone"],
144 | SyscallToId["execve"],
145 | SyscallToId["mknodat"],
146 | SyscallToId["chroot"],
147 | SyscallToId["mount"],
148 | SyscallToId["umount2"],
149 | SyscallToId["pivot_root"],
150 | SyscallToId["setuid"],
151 | SyscallToId["setgid"],
152 | ...
153 | ```
154 |
155 | ## Educational Value
156 |
157 | bpfsnitch is not only a powerful monitoring tool but also an excellent educational resource. It provides insights into:
158 | - eBPF Programming: Learn how eBPF programs are written and attached to kernel functions.
159 | - System Call Mechanics: Understand how syscalls work and how they impact system behavior.
160 | - Kernel-Level Monitoring: Gain knowledge about low-level monitoring techniques in Linux.
161 | - Observability Practices: Explore how to collect and expose metrics for modern monitoring systems like Prometheus.
162 |
163 | ## License
164 |
165 | bpfsnitch is released under the GNU General Public License (GPL).
166 |
167 | ## Future Plans
168 |
169 | - Configurable Syscall Whitelist: Allow users to define which syscalls to monitor.
170 | - User Interface: Develop a web-based UI for easier visualization and management.
171 | - Performance Optimizations: Enhance the efficiency of data collection and processing.
172 | - Additional Metrics: Include more granular metrics, such as latency measurements and error counts.
173 | - Extended Container Support: Improve compatibility with various container runtimes and orchestration platforms.
174 |
175 | ## Contact
176 |
177 | - Contributor: [@nullswan](https://github.com/nullswan)
178 | - Reviewers: [@gmarcha](https://github.com/gmarcha), [@naofel1](https://github.com/naofel1)
179 | - GitHub Issues: [https://github.com/nullswan/bpfsnitch/issues](https://github.com/nullswan/bpfsnitch/issues)
180 |
181 | ## Acknowledgments
182 |
183 | - eBPF Community: For providing extensive resources and support for eBPF development.
184 | - Prometheus: For their powerful monitoring and alerting toolkit.
185 | - Open Source Community: Thanks to all who have contributed to the open-source ecosystem, making projects like bpfsnitch possible.
186 |
187 | ## Join the Community
188 |
189 | If you find bpfsnitch valuable, please give us a ⭐ star on GitHub and share it with others who might be interested. Your support helps us improve and grow the project!
190 |
191 | Feel free to reach out if you have any questions or need assistance getting started with bpfsnitch. We look forward to your feedback!
192 |
--------------------------------------------------------------------------------
/internal/bpf/arch/arm64.go:
--------------------------------------------------------------------------------
1 | // AUTOGENERATED FILE
2 |
3 | //go:build arm64
4 | // +build arm64
5 |
6 | package bpfarch
7 |
8 | const BpfProgramElf = bpfProgramName + "_arm64.o"
9 |
10 | var SyscallToId = map[string]int{
11 | "io_setup": 0,
12 | "io_destroy": 1,
13 | "io_submit": 2,
14 | "io_cancel": 3,
15 | "io_getevents": 4,
16 | "setxattr": 5,
17 | "lsetxattr": 6,
18 | "fsetxattr": 7,
19 | "getxattr": 8,
20 | "lgetxattr": 9,
21 | "fgetxattr": 10,
22 | "listxattr": 11,
23 | "llistxattr": 12,
24 | "flistxattr": 13,
25 | "removexattr": 14,
26 | "lremovexattr": 15,
27 | "fremovexattr": 16,
28 | "getcwd": 17,
29 | "lookup_dcookie": 18,
30 | "eventfd2": 19,
31 | "epoll_create1": 20,
32 | "epoll_ctl": 21,
33 | "epoll_pwait": 22,
34 | "dup": 23,
35 | "dup3": 24,
36 | "fcntl": 25,
37 | "inotify_init1": 26,
38 | "inotify_add_watch": 27,
39 | "inotify_rm_watch": 28,
40 | "ioctl": 29,
41 | "ioprio_set": 30,
42 | "ioprio_get": 31,
43 | "flock": 32,
44 | "mknodat": 33,
45 | "mkdirat": 34,
46 | "unlinkat": 35,
47 | "symlinkat": 36,
48 | "linkat": 37,
49 | "renameat": 38,
50 | "umount2": 39,
51 | "mount": 40,
52 | "pivot_root": 41,
53 | "nfsservctl": 42,
54 | "statfs": 43,
55 | "fstatfs": 44,
56 | "truncate": 45,
57 | "ftruncate": 46,
58 | "fallocate": 47,
59 | "faccessat": 48,
60 | "chdir": 49,
61 | "fchdir": 50,
62 | "chroot": 51,
63 | "fchmod": 52,
64 | "fchmodat": 53,
65 | "fchownat": 54,
66 | "fchown": 55,
67 | "openat": 56,
68 | "close": 57,
69 | "vhangup": 58,
70 | "pipe2": 59,
71 | "quotactl": 60,
72 | "getdents64": 61,
73 | "lseek": 62,
74 | "read": 63,
75 | "write": 64,
76 | "readv": 65,
77 | "writev": 66,
78 | "pread64": 67,
79 | "pwrite64": 68,
80 | "preadv": 69,
81 | "pwritev": 70,
82 | "sendfile": 71,
83 | "pselect6": 72,
84 | "ppoll": 73,
85 | "signalfd4": 74,
86 | "vmsplice": 75,
87 | "splice": 76,
88 | "tee": 77,
89 | "readlinkat": 78,
90 | "newfstatat": 79,
91 | "fstat": 80,
92 | "sync": 81,
93 | "fsync": 82,
94 | "fdatasync": 83,
95 | "sync_file_range": 84,
96 | "timerfd_create": 85,
97 | "timerfd_settime": 86,
98 | "timerfd_gettime": 87,
99 | "utimensat": 88,
100 | "acct": 89,
101 | "capget": 90,
102 | "capset": 91,
103 | "personality": 92,
104 | "exit": 93,
105 | "exit_group": 94,
106 | "waitid": 95,
107 | "set_tid_address": 96,
108 | "unshare": 97,
109 | "futex": 98,
110 | "set_robust_list": 99,
111 | "get_robust_list": 100,
112 | "nanosleep": 101,
113 | "getitimer": 102,
114 | "setitimer": 103,
115 | "kexec_load": 104,
116 | "init_module": 105,
117 | "delete_module": 106,
118 | "timer_create": 107,
119 | "timer_gettime": 108,
120 | "timer_getoverrun": 109,
121 | "timer_settime": 110,
122 | "timer_delete": 111,
123 | "clock_settime": 112,
124 | "clock_gettime": 113,
125 | "clock_getres": 114,
126 | "clock_nanosleep": 115,
127 | "syslog": 116,
128 | "ptrace": 117,
129 | "sched_setparam": 118,
130 | "sched_setscheduler": 119,
131 | "sched_getscheduler": 120,
132 | "sched_getparam": 121,
133 | "sched_setaffinity": 122,
134 | "sched_getaffinity": 123,
135 | "sched_yield": 124,
136 | "sched_get_priority_max": 125,
137 | "sched_get_priority_min": 126,
138 | "sched_rr_get_interval": 127,
139 | "restart_syscall": 128,
140 | "kill": 129,
141 | "tkill": 130,
142 | "tgkill": 131,
143 | "sigaltstack": 132,
144 | "rt_sigsuspend": 133,
145 | "rt_sigaction": 134,
146 | "rt_sigprocmask": 135,
147 | "rt_sigpending": 136,
148 | "rt_sigtimedwait": 137,
149 | "rt_sigqueueinfo": 138,
150 | "rt_sigreturn": 139,
151 | "setpriority": 140,
152 | "getpriority": 141,
153 | "reboot": 142,
154 | "setregid": 143,
155 | "setgid": 144,
156 | "setreuid": 145,
157 | "setuid": 146,
158 | "setresuid": 147,
159 | "getresuid": 148,
160 | "setresgid": 149,
161 | "getresgid": 150,
162 | "setfsuid": 151,
163 | "setfsgid": 152,
164 | "times": 153,
165 | "setpgid": 154,
166 | "getpgid": 155,
167 | "getsid": 156,
168 | "setsid": 157,
169 | "getgroups": 158,
170 | "setgroups": 159,
171 | "uname": 160,
172 | "sethostname": 161,
173 | "setdomainname": 162,
174 | "getrlimit": 163,
175 | "setrlimit": 164,
176 | "getrusage": 165,
177 | "umask": 166,
178 | "prctl": 167,
179 | "getcpu": 168,
180 | "gettimeofday": 169,
181 | "settimeofday": 170,
182 | "adjtimex": 171,
183 | "getpid": 172,
184 | "getppid": 173,
185 | "getuid": 174,
186 | "geteuid": 175,
187 | "getgid": 176,
188 | "getegid": 177,
189 | "gettid": 178,
190 | "sysinfo": 179,
191 | "mq_open": 180,
192 | "mq_unlink": 181,
193 | "mq_timedsend": 182,
194 | "mq_timedreceive": 183,
195 | "mq_notify": 184,
196 | "mq_getsetattr": 185,
197 | "msgget": 186,
198 | "msgctl": 187,
199 | "msgrcv": 188,
200 | "msgsnd": 189,
201 | "semget": 190,
202 | "semctl": 191,
203 | "semtimedop": 192,
204 | "semop": 193,
205 | "shmget": 194,
206 | "shmctl": 195,
207 | "shmat": 196,
208 | "shmdt": 197,
209 | "socket": 198,
210 | "socketpair": 199,
211 | "bind": 200,
212 | "listen": 201,
213 | "accept": 202,
214 | "connect": 203,
215 | "getsockname": 204,
216 | "getpeername": 205,
217 | "sendto": 206,
218 | "recvfrom": 207,
219 | "setsockopt": 208,
220 | "getsockopt": 209,
221 | "shutdown": 210,
222 | "sendmsg": 211,
223 | "recvmsg": 212,
224 | "readahead": 213,
225 | "brk": 214,
226 | "munmap": 215,
227 | "mremap": 216,
228 | "add_key": 217,
229 | "request_key": 218,
230 | "keyctl": 219,
231 | "clone": 220,
232 | "execve": 221,
233 | "mmap": 222,
234 | "fadvise64": 223,
235 | "swapon": 224,
236 | "swapoff": 225,
237 | "mprotect": 226,
238 | "msync": 227,
239 | "mlock": 228,
240 | "munlock": 229,
241 | "mlockall": 230,
242 | "munlockall": 231,
243 | "mincore": 232,
244 | "madvise": 233,
245 | "remap_file_pages": 234,
246 | "mbind": 235,
247 | "get_mempolicy": 236,
248 | "set_mempolicy": 237,
249 | "migrate_pages": 238,
250 | "move_pages": 239,
251 | "rt_tgsigqueueinfo": 240,
252 | "perf_event_open": 241,
253 | "accept4": 242,
254 | "recvmmsg": 243,
255 | "wait4": 260,
256 | "prlimit64": 261,
257 | "fanotify_init": 262,
258 | "fanotify_mark": 263,
259 | "name_to_handle_at": 264,
260 | "open_by_handle_at": 265,
261 | "clock_adjtime": 266,
262 | "syncfs": 267,
263 | "setns": 268,
264 | "sendmmsg": 269,
265 | "process_vm_readv": 270,
266 | "process_vm_writev": 271,
267 | "kcmp": 272,
268 | "finit_module": 273,
269 | "sched_setattr": 274,
270 | "sched_getattr": 275,
271 | "renameat2": 276,
272 | "seccomp": 277,
273 | "getrandom": 278,
274 | "memfd_create": 279,
275 | "bpf": 280,
276 | "execveat": 281,
277 | "userfaultfd": 282,
278 | "membarrier": 283,
279 | "mlock2": 284,
280 | "copy_file_range": 285,
281 | "preadv2": 286,
282 | "pwritev2": 287,
283 | "pkey_mprotect": 288,
284 | "pkey_alloc": 289,
285 | "pkey_free": 290,
286 | "statx": 291,
287 | }
288 |
289 | var IdToSyscall = map[int]string{
290 | 0: "io_setup",
291 | 1: "io_destroy",
292 | 2: "io_submit",
293 | 3: "io_cancel",
294 | 4: "io_getevents",
295 | 5: "setxattr",
296 | 6: "lsetxattr",
297 | 7: "fsetxattr",
298 | 8: "getxattr",
299 | 9: "lgetxattr",
300 | 10: "fgetxattr",
301 | 11: "listxattr",
302 | 12: "llistxattr",
303 | 13: "flistxattr",
304 | 14: "removexattr",
305 | 15: "lremovexattr",
306 | 16: "fremovexattr",
307 | 17: "getcwd",
308 | 18: "lookup_dcookie",
309 | 19: "eventfd2",
310 | 20: "epoll_create1",
311 | 21: "epoll_ctl",
312 | 22: "epoll_pwait",
313 | 23: "dup",
314 | 24: "dup3",
315 | 25: "fcntl",
316 | 26: "inotify_init1",
317 | 27: "inotify_add_watch",
318 | 28: "inotify_rm_watch",
319 | 29: "ioctl",
320 | 30: "ioprio_set",
321 | 31: "ioprio_get",
322 | 32: "flock",
323 | 33: "mknodat",
324 | 34: "mkdirat",
325 | 35: "unlinkat",
326 | 36: "symlinkat",
327 | 37: "linkat",
328 | 38: "renameat",
329 | 39: "umount2",
330 | 40: "mount",
331 | 41: "pivot_root",
332 | 42: "nfsservctl",
333 | 43: "statfs",
334 | 44: "fstatfs",
335 | 45: "truncate",
336 | 46: "ftruncate",
337 | 47: "fallocate",
338 | 48: "faccessat",
339 | 49: "chdir",
340 | 50: "fchdir",
341 | 51: "chroot",
342 | 52: "fchmod",
343 | 53: "fchmodat",
344 | 54: "fchownat",
345 | 55: "fchown",
346 | 56: "openat",
347 | 57: "close",
348 | 58: "vhangup",
349 | 59: "pipe2",
350 | 60: "quotactl",
351 | 61: "getdents64",
352 | 62: "lseek",
353 | 63: "read",
354 | 64: "write",
355 | 65: "readv",
356 | 66: "writev",
357 | 67: "pread64",
358 | 68: "pwrite64",
359 | 69: "preadv",
360 | 70: "pwritev",
361 | 71: "sendfile",
362 | 72: "pselect6",
363 | 73: "ppoll",
364 | 74: "signalfd4",
365 | 75: "vmsplice",
366 | 76: "splice",
367 | 77: "tee",
368 | 78: "readlinkat",
369 | 79: "newfstatat",
370 | 80: "fstat",
371 | 81: "sync",
372 | 82: "fsync",
373 | 83: "fdatasync",
374 | 84: "sync_file_range",
375 | 85: "timerfd_create",
376 | 86: "timerfd_settime",
377 | 87: "timerfd_gettime",
378 | 88: "utimensat",
379 | 89: "acct",
380 | 90: "capget",
381 | 91: "capset",
382 | 92: "personality",
383 | 93: "exit",
384 | 94: "exit_group",
385 | 95: "waitid",
386 | 96: "set_tid_address",
387 | 97: "unshare",
388 | 98: "futex",
389 | 99: "set_robust_list",
390 | 100: "get_robust_list",
391 | 101: "nanosleep",
392 | 102: "getitimer",
393 | 103: "setitimer",
394 | 104: "kexec_load",
395 | 105: "init_module",
396 | 106: "delete_module",
397 | 107: "timer_create",
398 | 108: "timer_gettime",
399 | 109: "timer_getoverrun",
400 | 110: "timer_settime",
401 | 111: "timer_delete",
402 | 112: "clock_settime",
403 | 113: "clock_gettime",
404 | 114: "clock_getres",
405 | 115: "clock_nanosleep",
406 | 116: "syslog",
407 | 117: "ptrace",
408 | 118: "sched_setparam",
409 | 119: "sched_setscheduler",
410 | 120: "sched_getscheduler",
411 | 121: "sched_getparam",
412 | 122: "sched_setaffinity",
413 | 123: "sched_getaffinity",
414 | 124: "sched_yield",
415 | 125: "sched_get_priority_max",
416 | 126: "sched_get_priority_min",
417 | 127: "sched_rr_get_interval",
418 | 128: "restart_syscall",
419 | 129: "kill",
420 | 130: "tkill",
421 | 131: "tgkill",
422 | 132: "sigaltstack",
423 | 133: "rt_sigsuspend",
424 | 134: "rt_sigaction",
425 | 135: "rt_sigprocmask",
426 | 136: "rt_sigpending",
427 | 137: "rt_sigtimedwait",
428 | 138: "rt_sigqueueinfo",
429 | 139: "rt_sigreturn",
430 | 140: "setpriority",
431 | 141: "getpriority",
432 | 142: "reboot",
433 | 143: "setregid",
434 | 144: "setgid",
435 | 145: "setreuid",
436 | 146: "setuid",
437 | 147: "setresuid",
438 | 148: "getresuid",
439 | 149: "setresgid",
440 | 150: "getresgid",
441 | 151: "setfsuid",
442 | 152: "setfsgid",
443 | 153: "times",
444 | 154: "setpgid",
445 | 155: "getpgid",
446 | 156: "getsid",
447 | 157: "setsid",
448 | 158: "getgroups",
449 | 159: "setgroups",
450 | 160: "uname",
451 | 161: "sethostname",
452 | 162: "setdomainname",
453 | 163: "getrlimit",
454 | 164: "setrlimit",
455 | 165: "getrusage",
456 | 166: "umask",
457 | 167: "prctl",
458 | 168: "getcpu",
459 | 169: "gettimeofday",
460 | 170: "settimeofday",
461 | 171: "adjtimex",
462 | 172: "getpid",
463 | 173: "getppid",
464 | 174: "getuid",
465 | 175: "geteuid",
466 | 176: "getgid",
467 | 177: "getegid",
468 | 178: "gettid",
469 | 179: "sysinfo",
470 | 180: "mq_open",
471 | 181: "mq_unlink",
472 | 182: "mq_timedsend",
473 | 183: "mq_timedreceive",
474 | 184: "mq_notify",
475 | 185: "mq_getsetattr",
476 | 186: "msgget",
477 | 187: "msgctl",
478 | 188: "msgrcv",
479 | 189: "msgsnd",
480 | 190: "semget",
481 | 191: "semctl",
482 | 192: "semtimedop",
483 | 193: "semop",
484 | 194: "shmget",
485 | 195: "shmctl",
486 | 196: "shmat",
487 | 197: "shmdt",
488 | 198: "socket",
489 | 199: "socketpair",
490 | 200: "bind",
491 | 201: "listen",
492 | 202: "accept",
493 | 203: "connect",
494 | 204: "getsockname",
495 | 205: "getpeername",
496 | 206: "sendto",
497 | 207: "recvfrom",
498 | 208: "setsockopt",
499 | 209: "getsockopt",
500 | 210: "shutdown",
501 | 211: "sendmsg",
502 | 212: "recvmsg",
503 | 213: "readahead",
504 | 214: "brk",
505 | 215: "munmap",
506 | 216: "mremap",
507 | 217: "add_key",
508 | 218: "request_key",
509 | 219: "keyctl",
510 | 220: "clone",
511 | 221: "execve",
512 | 222: "mmap",
513 | 223: "fadvise64",
514 | 224: "swapon",
515 | 225: "swapoff",
516 | 226: "mprotect",
517 | 227: "msync",
518 | 228: "mlock",
519 | 229: "munlock",
520 | 230: "mlockall",
521 | 231: "munlockall",
522 | 232: "mincore",
523 | 233: "madvise",
524 | 234: "remap_file_pages",
525 | 235: "mbind",
526 | 236: "get_mempolicy",
527 | 237: "set_mempolicy",
528 | 238: "migrate_pages",
529 | 239: "move_pages",
530 | 240: "rt_tgsigqueueinfo",
531 | 241: "perf_event_open",
532 | 242: "accept4",
533 | 243: "recvmmsg",
534 | 260: "wait4",
535 | 261: "prlimit64",
536 | 262: "fanotify_init",
537 | 263: "fanotify_mark",
538 | 264: "name_to_handle_at",
539 | 265: "open_by_handle_at",
540 | 266: "clock_adjtime",
541 | 267: "syncfs",
542 | 268: "setns",
543 | 269: "sendmmsg",
544 | 270: "process_vm_readv",
545 | 271: "process_vm_writev",
546 | 272: "kcmp",
547 | 273: "finit_module",
548 | 274: "sched_setattr",
549 | 275: "sched_getattr",
550 | 276: "renameat2",
551 | 277: "seccomp",
552 | 278: "getrandom",
553 | 279: "memfd_create",
554 | 280: "bpf",
555 | 281: "execveat",
556 | 282: "userfaultfd",
557 | 283: "membarrier",
558 | 284: "mlock2",
559 | 285: "copy_file_range",
560 | 286: "preadv2",
561 | 287: "pwritev2",
562 | 288: "pkey_mprotect",
563 | 289: "pkey_alloc",
564 | 290: "pkey_free",
565 | 291: "statx",
566 | }
567 |
568 | var WhitelistedSyscalls = []int{
569 | SyscallToId["clone"],
570 | SyscallToId["execve"],
571 | SyscallToId["mknodat"],
572 | SyscallToId["chroot"],
573 | SyscallToId["mount"],
574 | SyscallToId["umount2"],
575 | SyscallToId["pivot_root"],
576 | SyscallToId["setuid"],
577 | SyscallToId["setgid"],
578 | SyscallToId["setreuid"],
579 | SyscallToId["setregid"],
580 | SyscallToId["setresuid"],
581 | SyscallToId["setresgid"],
582 | SyscallToId["capget"],
583 | SyscallToId["capset"],
584 | SyscallToId["prctl"],
585 | SyscallToId["seccomp"],
586 | SyscallToId["setns"],
587 | SyscallToId["unshare"],
588 | SyscallToId["kill"],
589 | SyscallToId["tkill"],
590 | SyscallToId["tgkill"],
591 | SyscallToId["socket"],
592 | SyscallToId["bind"],
593 | SyscallToId["connect"],
594 | SyscallToId["listen"],
595 | SyscallToId["accept"],
596 | SyscallToId["accept4"],
597 | SyscallToId["shutdown"],
598 | SyscallToId["sendmsg"],
599 | SyscallToId["recvmsg"],
600 | SyscallToId["sendto"],
601 | SyscallToId["recvfrom"],
602 | SyscallToId["getsockopt"],
603 | SyscallToId["setsockopt"],
604 | SyscallToId["sendmmsg"],
605 | SyscallToId["sethostname"],
606 | SyscallToId["setdomainname"],
607 | SyscallToId["wait4"],
608 | SyscallToId["finit_module"],
609 | SyscallToId["kexec_load"],
610 | SyscallToId["capget"],
611 | SyscallToId["capset"],
612 | SyscallToId["syslog"],
613 | SyscallToId["ptrace"],
614 | SyscallToId["prctl"],
615 | }
616 |
--------------------------------------------------------------------------------
/internal/bpf/arch/amd64.go:
--------------------------------------------------------------------------------
1 | // AUTOGENERATED FILE
2 |
3 | //go:build amd64
4 | // +build amd64
5 |
6 | package bpfarch
7 |
8 | const BpfProgramElf = bpfProgramName + "_amd64.o"
9 |
10 | var SyscallToId = map[string]int{
11 | "read": 0,
12 | "write": 1,
13 | "open": 2,
14 | "close": 3,
15 | "stat": 4,
16 | "fstat": 5,
17 | "lstat": 6,
18 | "poll": 7,
19 | "lseek": 8,
20 | "mmap": 9,
21 | "mprotect": 10,
22 | "munmap": 11,
23 | "brk": 12,
24 | "rt_sigaction": 13,
25 | "rt_sigprocmask": 14,
26 | "rt_sigreturn": 15,
27 | "ioctl": 16,
28 | "pread64": 17,
29 | "pwrite64": 18,
30 | "readv": 19,
31 | "writev": 20,
32 | "access": 21,
33 | "pipe": 22,
34 | "select": 23,
35 | "sched_yield": 24,
36 | "mremap": 25,
37 | "msync": 26,
38 | "mincore": 27,
39 | "madvise": 28,
40 | "shmget": 29,
41 | "shmat": 30,
42 | "shmctl": 31,
43 | "dup": 32,
44 | "dup2": 33,
45 | "pause": 34,
46 | "nanosleep": 35,
47 | "getitimer": 36,
48 | "alarm": 37,
49 | "setitimer": 38,
50 | "getpid": 39,
51 | "sendfile": 40,
52 | "socket": 41,
53 | "connect": 42,
54 | "accept": 43,
55 | "sendto": 44,
56 | "recvfrom": 45,
57 | "sendmsg": 46,
58 | "recvmsg": 47,
59 | "shutdown": 48,
60 | "bind": 49,
61 | "listen": 50,
62 | "getsockname": 51,
63 | "getpeername": 52,
64 | "socketpair": 53,
65 | "setsockopt": 54,
66 | "getsockopt": 55,
67 | "clone": 56,
68 | "fork": 57,
69 | "vfork": 58,
70 | "execve": 59,
71 | "exit": 60,
72 | "wait4": 61,
73 | "kill": 62,
74 | "uname": 63,
75 | "semget": 64,
76 | "semop": 65,
77 | "semctl": 66,
78 | "shmdt": 67,
79 | "msgget": 68,
80 | "msgsnd": 69,
81 | "msgrcv": 70,
82 | "msgctl": 71,
83 | "fcntl": 72,
84 | "flock": 73,
85 | "fsync": 74,
86 | "fdatasync": 75,
87 | "truncate": 76,
88 | "ftruncate": 77,
89 | "getdents": 78,
90 | "getcwd": 79,
91 | "chdir": 80,
92 | "fchdir": 81,
93 | "rename": 82,
94 | "mkdir": 83,
95 | "rmdir": 84,
96 | "creat": 85,
97 | "link": 86,
98 | "unlink": 87,
99 | "symlink": 88,
100 | "readlink": 89,
101 | "chmod": 90,
102 | "fchmod": 91,
103 | "chown": 92,
104 | "fchown": 93,
105 | "lchown": 94,
106 | "umask": 95,
107 | "gettimeofday": 96,
108 | "getrlimit": 97,
109 | "getrusage": 98,
110 | "sysinfo": 99,
111 | "times": 100,
112 | "ptrace": 101,
113 | "getuid": 102,
114 | "syslog": 103,
115 | "getgid": 104,
116 | "setuid": 105,
117 | "setgid": 106,
118 | "geteuid": 107,
119 | "getegid": 108,
120 | "setpgid": 109,
121 | "getppid": 110,
122 | "getpgrp": 111,
123 | "setsid": 112,
124 | "setreuid": 113,
125 | "setregid": 114,
126 | "getgroups": 115,
127 | "setgroups": 116,
128 | "setresuid": 117,
129 | "getresuid": 118,
130 | "setresgid": 119,
131 | "getresgid": 120,
132 | "getpgid": 121,
133 | "setfsuid": 122,
134 | "setfsgid": 123,
135 | "getsid": 124,
136 | "capget": 125,
137 | "capset": 126,
138 | "rt_sigpending": 127,
139 | "rt_sigtimedwait": 128,
140 | "rt_sigqueueinfo": 129,
141 | "rt_sigsuspend": 130,
142 | "sigaltstack": 131,
143 | "utime": 132,
144 | "mknod": 133,
145 | "uselib": 134,
146 | "personality": 135,
147 | "ustat": 136,
148 | "statfs": 137,
149 | "fstatfs": 138,
150 | "sysfs": 139,
151 | "getpriority": 140,
152 | "setpriority": 141,
153 | "sched_setparam": 142,
154 | "sched_getparam": 143,
155 | "sched_setscheduler": 144,
156 | "sched_getscheduler": 145,
157 | "sched_get_priority_max": 146,
158 | "sched_get_priority_min": 147,
159 | "sched_rr_get_interval": 148,
160 | "mlock": 149,
161 | "munlock": 150,
162 | "mlockall": 151,
163 | "munlockall": 152,
164 | "vhangup": 153,
165 | "modify_ldt": 154,
166 | "pivot_root": 155,
167 | "_sysctl": 156,
168 | "prctl": 157,
169 | "arch_prctl": 158,
170 | "adjtimex": 159,
171 | "setrlimit": 160,
172 | "chroot": 161,
173 | "sync": 162,
174 | "acct": 163,
175 | "settimeofday": 164,
176 | "mount": 165,
177 | "umount2": 166,
178 | "swapon": 167,
179 | "swapoff": 168,
180 | "reboot": 169,
181 | "sethostname": 170,
182 | "setdomainname": 171,
183 | "iopl": 172,
184 | "ioperm": 173,
185 | "create_module": 174,
186 | "init_module": 175,
187 | "delete_module": 176,
188 | "get_kernel_syms": 177,
189 | "query_module": 178,
190 | "quotactl": 179,
191 | "nfsservctl": 180,
192 | "getpmsg": 181,
193 | "putpmsg": 182,
194 | "afs_syscall": 183,
195 | "tuxcall": 184,
196 | "security": 185,
197 | "gettid": 186,
198 | "readahead": 187,
199 | "setxattr": 188,
200 | "lsetxattr": 189,
201 | "fsetxattr": 190,
202 | "getxattr": 191,
203 | "lgetxattr": 192,
204 | "fgetxattr": 193,
205 | "listxattr": 194,
206 | "llistxattr": 195,
207 | "flistxattr": 196,
208 | "removexattr": 197,
209 | "lremovexattr": 198,
210 | "fremovexattr": 199,
211 | "tkill": 200,
212 | "time": 201,
213 | "futex": 202,
214 | "sched_setaffinity": 203,
215 | "sched_getaffinity": 204,
216 | "set_thread_area": 205,
217 | "io_setup": 206,
218 | "io_destroy": 207,
219 | "io_getevents": 208,
220 | "io_submit": 209,
221 | "io_cancel": 210,
222 | "get_thread_area": 211,
223 | "lookup_dcookie": 212,
224 | "epoll_create": 213,
225 | "epoll_ctl_old": 214,
226 | "epoll_wait_old": 215,
227 | "remap_file_pages": 216,
228 | "getdents64": 217,
229 | "set_tid_address": 218,
230 | "restart_syscall": 219,
231 | "semtimedop": 220,
232 | "fadvise64": 221,
233 | "timer_create": 222,
234 | "timer_settime": 223,
235 | "timer_gettime": 224,
236 | "timer_getoverrun": 225,
237 | "timer_delete": 226,
238 | "clock_settime": 227,
239 | "clock_gettime": 228,
240 | "clock_getres": 229,
241 | "clock_nanosleep": 230,
242 | "exit_group": 231,
243 | "epoll_wait": 232,
244 | "epoll_ctl": 233,
245 | "tgkill": 234,
246 | "utimes": 235,
247 | "vserver": 236,
248 | "mbind": 237,
249 | "set_mempolicy": 238,
250 | "get_mempolicy": 239,
251 | "mq_open": 240,
252 | "mq_unlink": 241,
253 | "mq_timedsend": 242,
254 | "mq_timedreceive": 243,
255 | "mq_notify": 244,
256 | "mq_getsetattr": 245,
257 | "kexec_load": 246,
258 | "waitid": 247,
259 | "add_key": 248,
260 | "request_key": 249,
261 | "keyctl": 250,
262 | "ioprio_set": 251,
263 | "ioprio_get": 252,
264 | "inotify_init": 253,
265 | "inotify_add_watch": 254,
266 | "inotify_rm_watch": 255,
267 | "migrate_pages": 256,
268 | "openat": 257,
269 | "mkdirat": 258,
270 | "mknodat": 259,
271 | "fchownat": 260,
272 | "futimesat": 261,
273 | "newfstatat": 262,
274 | "unlinkat": 263,
275 | "renameat": 264,
276 | "linkat": 265,
277 | "symlinkat": 266,
278 | "readlinkat": 267,
279 | "fchmodat": 268,
280 | "faccessat": 269,
281 | "pselect6": 270,
282 | "ppoll": 271,
283 | "unshare": 272,
284 | "set_robust_list": 273,
285 | "get_robust_list": 274,
286 | "splice": 275,
287 | "tee": 276,
288 | "sync_file_range": 277,
289 | "vmsplice": 278,
290 | "move_pages": 279,
291 | "utimensat": 280,
292 | "epoll_pwait": 281,
293 | "signalfd": 282,
294 | "timerfd_create": 283,
295 | "eventfd": 284,
296 | "fallocate": 285,
297 | "timerfd_settime": 286,
298 | "timerfd_gettime": 287,
299 | "accept4": 288,
300 | "signalfd4": 289,
301 | "eventfd2": 290,
302 | "epoll_create1": 291,
303 | "dup3": 292,
304 | "pipe2": 293,
305 | "inotify_init1": 294,
306 | "preadv": 295,
307 | "pwritev": 296,
308 | "rt_tgsigqueueinfo": 297,
309 | "perf_event_open": 298,
310 | "recvmmsg": 299,
311 | "fanotify_init": 300,
312 | "fanotify_mark": 301,
313 | "prlimit64": 302,
314 | "name_to_handle_at": 303,
315 | "open_by_handle_at": 304,
316 | "clock_adjtime": 305,
317 | "syncfs": 306,
318 | "sendmmsg": 307,
319 | "setns": 308,
320 | "getcpu": 309,
321 | "process_vm_readv": 310,
322 | "process_vm_writev": 311,
323 | "kcmp": 312,
324 | "finit_module": 313,
325 | "sched_setattr": 314,
326 | "sched_getattr": 315,
327 | "renameat2": 316,
328 | "seccomp": 317,
329 | "getrandom": 318,
330 | "memfd_create": 319,
331 | "kexec_file_load": 320,
332 | "bpf": 321,
333 | "execveat": 322,
334 | "userfaultfd": 323,
335 | "membarrier": 324,
336 | "mlock2": 325,
337 | "copy_file_range": 326,
338 | "preadv2": 327,
339 | "pwritev2": 328,
340 | "pkey_mprotect": 329,
341 | "pkey_alloc": 330,
342 | "pkey_free": 331,
343 | "statx": 332,
344 | }
345 |
346 | var IdToSyscall = map[int]string{
347 | 0: "read",
348 | 1: "write",
349 | 2: "open",
350 | 3: "close",
351 | 4: "stat",
352 | 5: "fstat",
353 | 6: "lstat",
354 | 7: "poll",
355 | 8: "lseek",
356 | 9: "mmap",
357 | 10: "mprotect",
358 | 11: "munmap",
359 | 12: "brk",
360 | 13: "rt_sigaction",
361 | 14: "rt_sigprocmask",
362 | 15: "rt_sigreturn",
363 | 16: "ioctl",
364 | 17: "pread64",
365 | 18: "pwrite64",
366 | 19: "readv",
367 | 20: "writev",
368 | 21: "access",
369 | 22: "pipe",
370 | 23: "select",
371 | 24: "sched_yield",
372 | 25: "mremap",
373 | 26: "msync",
374 | 27: "mincore",
375 | 28: "madvise",
376 | 29: "shmget",
377 | 30: "shmat",
378 | 31: "shmctl",
379 | 32: "dup",
380 | 33: "dup2",
381 | 34: "pause",
382 | 35: "nanosleep",
383 | 36: "getitimer",
384 | 37: "alarm",
385 | 38: "setitimer",
386 | 39: "getpid",
387 | 40: "sendfile",
388 | 41: "socket",
389 | 42: "connect",
390 | 43: "accept",
391 | 44: "sendto",
392 | 45: "recvfrom",
393 | 46: "sendmsg",
394 | 47: "recvmsg",
395 | 48: "shutdown",
396 | 49: "bind",
397 | 50: "listen",
398 | 51: "getsockname",
399 | 52: "getpeername",
400 | 53: "socketpair",
401 | 54: "setsockopt",
402 | 55: "getsockopt",
403 | 56: "clone",
404 | 57: "fork",
405 | 58: "vfork",
406 | 59: "execve",
407 | 60: "exit",
408 | 61: "wait4",
409 | 62: "kill",
410 | 63: "uname",
411 | 64: "semget",
412 | 65: "semop",
413 | 66: "semctl",
414 | 67: "shmdt",
415 | 68: "msgget",
416 | 69: "msgsnd",
417 | 70: "msgrcv",
418 | 71: "msgctl",
419 | 72: "fcntl",
420 | 73: "flock",
421 | 74: "fsync",
422 | 75: "fdatasync",
423 | 76: "truncate",
424 | 77: "ftruncate",
425 | 78: "getdents",
426 | 79: "getcwd",
427 | 80: "chdir",
428 | 81: "fchdir",
429 | 82: "rename",
430 | 83: "mkdir",
431 | 84: "rmdir",
432 | 85: "creat",
433 | 86: "link",
434 | 87: "unlink",
435 | 88: "symlink",
436 | 89: "readlink",
437 | 90: "chmod",
438 | 91: "fchmod",
439 | 92: "chown",
440 | 93: "fchown",
441 | 94: "lchown",
442 | 95: "umask",
443 | 96: "gettimeofday",
444 | 97: "getrlimit",
445 | 98: "getrusage",
446 | 99: "sysinfo",
447 | 100: "times",
448 | 101: "ptrace",
449 | 102: "getuid",
450 | 103: "syslog",
451 | 104: "getgid",
452 | 105: "setuid",
453 | 106: "setgid",
454 | 107: "geteuid",
455 | 108: "getegid",
456 | 109: "setpgid",
457 | 110: "getppid",
458 | 111: "getpgrp",
459 | 112: "setsid",
460 | 113: "setreuid",
461 | 114: "setregid",
462 | 115: "getgroups",
463 | 116: "setgroups",
464 | 117: "setresuid",
465 | 118: "getresuid",
466 | 119: "setresgid",
467 | 120: "getresgid",
468 | 121: "getpgid",
469 | 122: "setfsuid",
470 | 123: "setfsgid",
471 | 124: "getsid",
472 | 125: "capget",
473 | 126: "capset",
474 | 127: "rt_sigpending",
475 | 128: "rt_sigtimedwait",
476 | 129: "rt_sigqueueinfo",
477 | 130: "rt_sigsuspend",
478 | 131: "sigaltstack",
479 | 132: "utime",
480 | 133: "mknod",
481 | 134: "uselib",
482 | 135: "personality",
483 | 136: "ustat",
484 | 137: "statfs",
485 | 138: "fstatfs",
486 | 139: "sysfs",
487 | 140: "getpriority",
488 | 141: "setpriority",
489 | 142: "sched_setparam",
490 | 143: "sched_getparam",
491 | 144: "sched_setscheduler",
492 | 145: "sched_getscheduler",
493 | 146: "sched_get_priority_max",
494 | 147: "sched_get_priority_min",
495 | 148: "sched_rr_get_interval",
496 | 149: "mlock",
497 | 150: "munlock",
498 | 151: "mlockall",
499 | 152: "munlockall",
500 | 153: "vhangup",
501 | 154: "modify_ldt",
502 | 155: "pivot_root",
503 | 156: "_sysctl",
504 | 157: "prctl",
505 | 158: "arch_prctl",
506 | 159: "adjtimex",
507 | 160: "setrlimit",
508 | 161: "chroot",
509 | 162: "sync",
510 | 163: "acct",
511 | 164: "settimeofday",
512 | 165: "mount",
513 | 166: "umount2",
514 | 167: "swapon",
515 | 168: "swapoff",
516 | 169: "reboot",
517 | 170: "sethostname",
518 | 171: "setdomainname",
519 | 172: "iopl",
520 | 173: "ioperm",
521 | 174: "create_module",
522 | 175: "init_module",
523 | 176: "delete_module",
524 | 177: "get_kernel_syms",
525 | 178: "query_module",
526 | 179: "quotactl",
527 | 180: "nfsservctl",
528 | 181: "getpmsg",
529 | 182: "putpmsg",
530 | 183: "afs_syscall",
531 | 184: "tuxcall",
532 | 185: "security",
533 | 186: "gettid",
534 | 187: "readahead",
535 | 188: "setxattr",
536 | 189: "lsetxattr",
537 | 190: "fsetxattr",
538 | 191: "getxattr",
539 | 192: "lgetxattr",
540 | 193: "fgetxattr",
541 | 194: "listxattr",
542 | 195: "llistxattr",
543 | 196: "flistxattr",
544 | 197: "removexattr",
545 | 198: "lremovexattr",
546 | 199: "fremovexattr",
547 | 200: "tkill",
548 | 201: "time",
549 | 202: "futex",
550 | 203: "sched_setaffinity",
551 | 204: "sched_getaffinity",
552 | 205: "set_thread_area",
553 | 206: "io_setup",
554 | 207: "io_destroy",
555 | 208: "io_getevents",
556 | 209: "io_submit",
557 | 210: "io_cancel",
558 | 211: "get_thread_area",
559 | 212: "lookup_dcookie",
560 | 213: "epoll_create",
561 | 214: "epoll_ctl_old",
562 | 215: "epoll_wait_old",
563 | 216: "remap_file_pages",
564 | 217: "getdents64",
565 | 218: "set_tid_address",
566 | 219: "restart_syscall",
567 | 220: "semtimedop",
568 | 221: "fadvise64",
569 | 222: "timer_create",
570 | 223: "timer_settime",
571 | 224: "timer_gettime",
572 | 225: "timer_getoverrun",
573 | 226: "timer_delete",
574 | 227: "clock_settime",
575 | 228: "clock_gettime",
576 | 229: "clock_getres",
577 | 230: "clock_nanosleep",
578 | 231: "exit_group",
579 | 232: "epoll_wait",
580 | 233: "epoll_ctl",
581 | 234: "tgkill",
582 | 235: "utimes",
583 | 236: "vserver",
584 | 237: "mbind",
585 | 238: "set_mempolicy",
586 | 239: "get_mempolicy",
587 | 240: "mq_open",
588 | 241: "mq_unlink",
589 | 242: "mq_timedsend",
590 | 243: "mq_timedreceive",
591 | 244: "mq_notify",
592 | 245: "mq_getsetattr",
593 | 246: "kexec_load",
594 | 247: "waitid",
595 | 248: "add_key",
596 | 249: "request_key",
597 | 250: "keyctl",
598 | 251: "ioprio_set",
599 | 252: "ioprio_get",
600 | 253: "inotify_init",
601 | 254: "inotify_add_watch",
602 | 255: "inotify_rm_watch",
603 | 256: "migrate_pages",
604 | 257: "openat",
605 | 258: "mkdirat",
606 | 259: "mknodat",
607 | 260: "fchownat",
608 | 261: "futimesat",
609 | 262: "newfstatat",
610 | 263: "unlinkat",
611 | 264: "renameat",
612 | 265: "linkat",
613 | 266: "symlinkat",
614 | 267: "readlinkat",
615 | 268: "fchmodat",
616 | 269: "faccessat",
617 | 270: "pselect6",
618 | 271: "ppoll",
619 | 272: "unshare",
620 | 273: "set_robust_list",
621 | 274: "get_robust_list",
622 | 275: "splice",
623 | 276: "tee",
624 | 277: "sync_file_range",
625 | 278: "vmsplice",
626 | 279: "move_pages",
627 | 280: "utimensat",
628 | 281: "epoll_pwait",
629 | 282: "signalfd",
630 | 283: "timerfd_create",
631 | 284: "eventfd",
632 | 285: "fallocate",
633 | 286: "timerfd_settime",
634 | 287: "timerfd_gettime",
635 | 288: "accept4",
636 | 289: "signalfd4",
637 | 290: "eventfd2",
638 | 291: "epoll_create1",
639 | 292: "dup3",
640 | 293: "pipe2",
641 | 294: "inotify_init1",
642 | 295: "preadv",
643 | 296: "pwritev",
644 | 297: "rt_tgsigqueueinfo",
645 | 298: "perf_event_open",
646 | 299: "recvmmsg",
647 | 300: "fanotify_init",
648 | 301: "fanotify_mark",
649 | 302: "prlimit64",
650 | 303: "name_to_handle_at",
651 | 304: "open_by_handle_at",
652 | 305: "clock_adjtime",
653 | 306: "syncfs",
654 | 307: "sendmmsg",
655 | 308: "setns",
656 | 309: "getcpu",
657 | 310: "process_vm_readv",
658 | 311: "process_vm_writev",
659 | 312: "kcmp",
660 | 313: "finit_module",
661 | 314: "sched_setattr",
662 | 315: "sched_getattr",
663 | 316: "renameat2",
664 | 317: "seccomp",
665 | 318: "getrandom",
666 | 319: "memfd_create",
667 | 320: "kexec_file_load",
668 | 321: "bpf",
669 | 322: "execveat",
670 | 323: "userfaultfd",
671 | 324: "membarrier",
672 | 325: "mlock2",
673 | 326: "copy_file_range",
674 | 327: "preadv2",
675 | 328: "pwritev2",
676 | 329: "pkey_mprotect",
677 | 330: "pkey_alloc",
678 | 331: "pkey_free",
679 | 332: "statx",
680 | }
681 |
682 | var WhitelistedSyscalls = []int{
683 | SyscallToId["clone"],
684 | SyscallToId["fork"],
685 | SyscallToId["vfork"],
686 | SyscallToId["execve"],
687 | SyscallToId["exit"],
688 | SyscallToId["wait4"],
689 | SyscallToId["kill"],
690 | SyscallToId["ptrace"],
691 | SyscallToId["setuid"],
692 | SyscallToId["setgid"],
693 | SyscallToId["seteuid"],
694 | SyscallToId["setegid"],
695 | SyscallToId["setpgid"],
696 | SyscallToId["setresuid"],
697 | SyscallToId["getresuid"],
698 | SyscallToId["setresgid"],
699 | SyscallToId["getresgid"],
700 | SyscallToId["prctl"],
701 | SyscallToId["arch_prctl"],
702 | SyscallToId["capget"],
703 | SyscallToId["capset"],
704 | SyscallToId["seccomp"],
705 | SyscallToId["setns"],
706 | SyscallToId["unshare"],
707 | SyscallToId["chroot"],
708 | SyscallToId["pivot_root"],
709 | SyscallToId["mknod"],
710 | SyscallToId["mount"],
711 | SyscallToId["umount2"],
712 | SyscallToId["socket"],
713 | SyscallToId["connect"],
714 | SyscallToId["accept"],
715 | SyscallToId["sendto"],
716 | SyscallToId["recvfrom"],
717 | SyscallToId["sendmsg"],
718 | SyscallToId["recvmsg"],
719 | SyscallToId["shutdown"],
720 | SyscallToId["bind"],
721 | SyscallToId["listen"],
722 | SyscallToId["getsockname"],
723 | SyscallToId["getpeername"],
724 | SyscallToId["socketpair"],
725 | SyscallToId["setsockopt"],
726 | SyscallToId["getsockopt"],
727 | SyscallToId["accept4"],
728 | SyscallToId["sendmmsg"],
729 | SyscallToId["getrandom"],
730 | SyscallToId["mknodat"],
731 | SyscallToId["fchownat"],
732 | }
733 |
--------------------------------------------------------------------------------
/internal/bpf/arch/386.go:
--------------------------------------------------------------------------------
1 | // AUTOGENERATED FILE
2 |
3 | //go:build 386
4 | // +build 386
5 |
6 | package bpfarch
7 |
8 | const BpfProgramElf = bpfProgramName + "_x86.o"
9 |
10 | var SyscallToId = map[string]int{
11 | "restart_syscall": 0,
12 | "exit": 1,
13 | "fork": 2,
14 | "read": 3,
15 | "write": 4,
16 | "open": 5,
17 | "close": 6,
18 | "waitpid": 7,
19 | "creat": 8,
20 | "link": 9,
21 | "unlink": 10,
22 | "execve": 11,
23 | "chdir": 12,
24 | "time": 13,
25 | "mknod": 14,
26 | "chmod": 15,
27 | "lchown": 16,
28 | "break": 17,
29 | "oldstat": 18,
30 | "lseek": 19,
31 | "getpid": 20,
32 | "mount": 21,
33 | "umount": 22,
34 | "setuid": 23,
35 | "getuid": 24,
36 | "stime": 25,
37 | "ptrace": 26,
38 | "alarm": 27,
39 | "oldfstat": 28,
40 | "pause": 29,
41 | "utime": 30,
42 | "stty": 31,
43 | "gtty": 32,
44 | "access": 33,
45 | "nice": 34,
46 | "ftime": 35,
47 | "sync": 36,
48 | "kill": 37,
49 | "rename": 38,
50 | "mkdir": 39,
51 | "rmdir": 40,
52 | "dup": 41,
53 | "pipe": 42,
54 | "times": 43,
55 | "prof": 44,
56 | "brk": 45,
57 | "setgid": 46,
58 | "getgid": 47,
59 | "signal": 48,
60 | "geteuid": 49,
61 | "getegid": 50,
62 | "acct": 51,
63 | "umount2": 52,
64 | "lock": 53,
65 | "ioctl": 54,
66 | "fcntl": 55,
67 | "mpx": 56,
68 | "setpgid": 57,
69 | "ulimit": 58,
70 | "oldolduname": 59,
71 | "umask": 60,
72 | "chroot": 61,
73 | "ustat": 62,
74 | "dup2": 63,
75 | "getppid": 64,
76 | "getpgrp": 65,
77 | "setsid": 66,
78 | "sigaction": 67,
79 | "sgetmask": 68,
80 | "ssetmask": 69,
81 | "setreuid": 70,
82 | "setregid": 71,
83 | "sigsuspend": 72,
84 | "sigpending": 73,
85 | "sethostname": 74,
86 | "setrlimit": 75,
87 | "getrlimit": 76,
88 | "getrusage": 77,
89 | "gettimeofday": 78,
90 | "settimeofday": 79,
91 | "getgroups": 80,
92 | "setgroups": 81,
93 | "select": 82,
94 | "symlink": 83,
95 | "oldlstat": 84,
96 | "readlink": 85,
97 | "uselib": 86,
98 | "swapon": 87,
99 | "reboot": 88,
100 | "readdir": 89,
101 | "mmap": 90,
102 | "munmap": 91,
103 | "truncate": 92,
104 | "ftruncate": 93,
105 | "fchmod": 94,
106 | "fchown": 95,
107 | "getpriority": 96,
108 | "setpriority": 97,
109 | "profil": 98,
110 | "statfs": 99,
111 | "fstatfs": 100,
112 | "ioperm": 101,
113 | "socketcall": 102,
114 | "syslog": 103,
115 | "setitimer": 104,
116 | "getitimer": 105,
117 | "stat": 106,
118 | "lstat": 107,
119 | "fstat": 108,
120 | "olduname": 109,
121 | "iopl": 110,
122 | "vhangup": 111,
123 | "idle": 112,
124 | "vm86old": 113,
125 | "wait4": 114,
126 | "swapoff": 115,
127 | "sysinfo": 116,
128 | "ipc": 117,
129 | "fsync": 118,
130 | "sigreturn": 119,
131 | "clone": 120,
132 | "setdomainname": 121,
133 | "uname": 122,
134 | "modify_ldt": 123,
135 | "adjtimex": 124,
136 | "mprotect": 125,
137 | "sigprocmask": 126,
138 | "create_module": 127,
139 | "init_module": 128,
140 | "delete_module": 129,
141 | "get_kernel_syms": 130,
142 | "quotactl": 131,
143 | "getpgid": 132,
144 | "fchdir": 133,
145 | "bdflush": 134,
146 | "sysfs": 135,
147 | "personality": 136,
148 | "afs_syscall": 137,
149 | "setfsuid": 138,
150 | "setfsgid": 139,
151 | "_llseek": 140,
152 | "getdents": 141,
153 | "_newselect": 142,
154 | "flock": 143,
155 | "msync": 144,
156 | "readv": 145,
157 | "writev": 146,
158 | "getsid": 147,
159 | "fdatasync": 148,
160 | "_sysctl": 149,
161 | "mlock": 150,
162 | "munlock": 151,
163 | "mlockall": 152,
164 | "munlockall": 153,
165 | "sched_setparam": 154,
166 | "sched_getparam": 155,
167 | "sched_setscheduler": 156,
168 | "sched_getscheduler": 157,
169 | "sched_yield": 158,
170 | "sched_get_priority_max": 159,
171 | "sched_get_priority_min": 160,
172 | "sched_rr_get_interval": 161,
173 | "nanosleep": 162,
174 | "mremap": 163,
175 | "setresuid": 164,
176 | "getresuid": 165,
177 | "vm86": 166,
178 | "query_module": 167,
179 | "poll": 168,
180 | "nfsservctl": 169,
181 | "setresgid": 170,
182 | "getresgid": 171,
183 | "prctl": 172,
184 | "rt_sigreturn": 173,
185 | "rt_sigaction": 174,
186 | "rt_sigprocmask": 175,
187 | "rt_sigpending": 176,
188 | "rt_sigtimedwait": 177,
189 | "rt_sigqueueinfo": 178,
190 | "rt_sigsuspend": 179,
191 | "pread64": 180,
192 | "pwrite64": 181,
193 | "chown": 182,
194 | "getcwd": 183,
195 | "capget": 184,
196 | "capset": 185,
197 | "sigaltstack": 186,
198 | "sendfile": 187,
199 | "getpmsg": 188,
200 | "putpmsg": 189,
201 | "vfork": 190,
202 | "ugetrlimit": 191,
203 | "mmap2": 192,
204 | "truncate64": 193,
205 | "ftruncate64": 194,
206 | "stat64": 195,
207 | "lstat64": 196,
208 | "fstat64": 197,
209 | "lchown32": 198,
210 | "getuid32": 199,
211 | "getgid32": 200,
212 | "geteuid32": 201,
213 | "getegid32": 202,
214 | "setreuid32": 203,
215 | "setregid32": 204,
216 | "getgroups32": 205,
217 | "setgroups32": 206,
218 | "fchown32": 207,
219 | "setresuid32": 208,
220 | "getresuid32": 209,
221 | "setresgid32": 210,
222 | "getresgid32": 211,
223 | "chown32": 212,
224 | "setuid32": 213,
225 | "setgid32": 214,
226 | "setfsuid32": 215,
227 | "setfsgid32": 216,
228 | "pivot_root": 217,
229 | "mincore": 218,
230 | "madvise": 219,
231 | "getdents64": 220,
232 | "fcntl64": 221,
233 | "gettid": 224,
234 | "readahead": 225,
235 | "setxattr": 226,
236 | "lsetxattr": 227,
237 | "fsetxattr": 228,
238 | "getxattr": 229,
239 | "lgetxattr": 230,
240 | "fgetxattr": 231,
241 | "listxattr": 232,
242 | "llistxattr": 233,
243 | "flistxattr": 234,
244 | "removexattr": 235,
245 | "lremovexattr": 236,
246 | "fremovexattr": 237,
247 | "tkill": 238,
248 | "sendfile64": 239,
249 | "futex": 240,
250 | "sched_setaffinity": 241,
251 | "sched_getaffinity": 242,
252 | "set_thread_area": 243,
253 | "get_thread_area": 244,
254 | "io_setup": 245,
255 | "io_destroy": 246,
256 | "io_getevents": 247,
257 | "io_submit": 248,
258 | "io_cancel": 249,
259 | "fadvise64": 250,
260 | "exit_group": 252,
261 | "lookup_dcookie": 253,
262 | "epoll_create": 254,
263 | "epoll_ctl": 255,
264 | "epoll_wait": 256,
265 | "remap_file_pages": 257,
266 | "set_tid_address": 258,
267 | "timer_create": 259,
268 | "timer_settime": 260,
269 | "timer_gettime": 261,
270 | "timer_getoverrun": 262,
271 | "timer_delete": 263,
272 | "clock_settime": 264,
273 | "clock_gettime": 265,
274 | "clock_getres": 266,
275 | "clock_nanosleep": 267,
276 | "statfs64": 268,
277 | "fstatfs64": 269,
278 | "tgkill": 270,
279 | "utimes": 271,
280 | "fadvise64_64": 272,
281 | "vserver": 273,
282 | "mbind": 274,
283 | "get_mempolicy": 275,
284 | "set_mempolicy": 276,
285 | "mq_open": 277,
286 | "mq_unlink": 278,
287 | "mq_timedsend": 279,
288 | "mq_timedreceive": 280,
289 | "mq_notify": 281,
290 | "mq_getsetattr": 282,
291 | "kexec_load": 283,
292 | "waitid": 284,
293 | "add_key": 286,
294 | "request_key": 287,
295 | "keyctl": 288,
296 | "ioprio_set": 289,
297 | "ioprio_get": 290,
298 | "inotify_init": 291,
299 | "inotify_add_watch": 292,
300 | "inotify_rm_watch": 293,
301 | "migrate_pages": 294,
302 | "openat": 295,
303 | "mkdirat": 296,
304 | "mknodat": 297,
305 | "fchownat": 298,
306 | "futimesat": 299,
307 | "fstatat64": 300,
308 | "unlinkat": 301,
309 | "renameat": 302,
310 | "linkat": 303,
311 | "symlinkat": 304,
312 | "readlinkat": 305,
313 | "fchmodat": 306,
314 | "faccessat": 307,
315 | "pselect6": 308,
316 | "ppoll": 309,
317 | "unshare": 310,
318 | "set_robust_list": 311,
319 | "get_robust_list": 312,
320 | "splice": 313,
321 | "sync_file_range": 314,
322 | "tee": 315,
323 | "vmsplice": 316,
324 | "move_pages": 317,
325 | "getcpu": 318,
326 | "epoll_pwait": 319,
327 | "utimensat": 320,
328 | "signalfd": 321,
329 | "timerfd_create": 322,
330 | "eventfd": 323,
331 | "fallocate": 324,
332 | "timerfd_settime": 325,
333 | "timerfd_gettime": 326,
334 | "signalfd4": 327,
335 | "eventfd2": 328,
336 | "epoll_create1": 329,
337 | "dup3": 330,
338 | "pipe2": 331,
339 | "inotify_init1": 332,
340 | "preadv": 333,
341 | "pwritev": 334,
342 | "rt_tgsigqueueinfo": 335,
343 | "perf_event_open": 336,
344 | "recvmmsg": 337,
345 | "fanotify_init": 338,
346 | "fanotify_mark": 339,
347 | "prlimit64": 340,
348 | "name_to_handle_at": 341,
349 | "open_by_handle_at": 342,
350 | "clock_adjtime": 343,
351 | "syncfs": 344,
352 | "sendmmsg": 345,
353 | "setns": 346,
354 | "process_vm_readv": 347,
355 | "process_vm_writev": 348,
356 | "kcmp": 349,
357 | "finit_module": 350,
358 | "sched_setattr": 351,
359 | "sched_getattr": 352,
360 | "renameat2": 353,
361 | "seccomp": 354,
362 | "getrandom": 355,
363 | "memfd_create": 356,
364 | "bpf": 357,
365 | "execveat": 358,
366 | "socket": 359,
367 | "socketpair": 360,
368 | "bind": 361,
369 | "connect": 362,
370 | "listen": 363,
371 | "accept4": 364,
372 | "getsockopt": 365,
373 | "setsockopt": 366,
374 | "getsockname": 367,
375 | "getpeername": 368,
376 | "sendto": 369,
377 | "sendmsg": 370,
378 | "recvfrom": 371,
379 | "recvmsg": 372,
380 | "shutdown": 373,
381 | "userfaultfd": 374,
382 | "membarrier": 375,
383 | "mlock2": 376,
384 | "copy_file_range": 377,
385 | "preadv2": 378,
386 | "pwritev2": 379,
387 | "pkey_mprotect": 380,
388 | "pkey_alloc": 381,
389 | "pkey_free": 382,
390 | "statx": 383,
391 | "arch_prctl": 384,
392 | }
393 |
394 | var IdToSyscall = map[int]string{
395 | 0: "restart_syscall",
396 | 1: "exit",
397 | 2: "fork",
398 | 3: "read",
399 | 4: "write",
400 | 5: "open",
401 | 6: "close",
402 | 7: "waitpid",
403 | 8: "creat",
404 | 9: "link",
405 | 10: "unlink",
406 | 11: "execve",
407 | 12: "chdir",
408 | 13: "time",
409 | 14: "mknod",
410 | 15: "chmod",
411 | 16: "lchown",
412 | 17: "break",
413 | 18: "oldstat",
414 | 19: "lseek",
415 | 20: "getpid",
416 | 21: "mount",
417 | 22: "umount",
418 | 23: "setuid",
419 | 24: "getuid",
420 | 25: "stime",
421 | 26: "ptrace",
422 | 27: "alarm",
423 | 28: "oldfstat",
424 | 29: "pause",
425 | 30: "utime",
426 | 31: "stty",
427 | 32: "gtty",
428 | 33: "access",
429 | 34: "nice",
430 | 35: "ftime",
431 | 36: "sync",
432 | 37: "kill",
433 | 38: "rename",
434 | 39: "mkdir",
435 | 40: "rmdir",
436 | 41: "dup",
437 | 42: "pipe",
438 | 43: "times",
439 | 44: "prof",
440 | 45: "brk",
441 | 46: "setgid",
442 | 47: "getgid",
443 | 48: "signal",
444 | 49: "geteuid",
445 | 50: "getegid",
446 | 51: "acct",
447 | 52: "umount2",
448 | 53: "lock",
449 | 54: "ioctl",
450 | 55: "fcntl",
451 | 56: "mpx",
452 | 57: "setpgid",
453 | 58: "ulimit",
454 | 59: "oldolduname",
455 | 60: "umask",
456 | 61: "chroot",
457 | 62: "ustat",
458 | 63: "dup2",
459 | 64: "getppid",
460 | 65: "getpgrp",
461 | 66: "setsid",
462 | 67: "sigaction",
463 | 68: "sgetmask",
464 | 69: "ssetmask",
465 | 70: "setreuid",
466 | 71: "setregid",
467 | 72: "sigsuspend",
468 | 73: "sigpending",
469 | 74: "sethostname",
470 | 75: "setrlimit",
471 | 76: "getrlimit",
472 | 77: "getrusage",
473 | 78: "gettimeofday",
474 | 79: "settimeofday",
475 | 80: "getgroups",
476 | 81: "setgroups",
477 | 82: "select",
478 | 83: "symlink",
479 | 84: "oldlstat",
480 | 85: "readlink",
481 | 86: "uselib",
482 | 87: "swapon",
483 | 88: "reboot",
484 | 89: "readdir",
485 | 90: "mmap",
486 | 91: "munmap",
487 | 92: "truncate",
488 | 93: "ftruncate",
489 | 94: "fchmod",
490 | 95: "fchown",
491 | 96: "getpriority",
492 | 97: "setpriority",
493 | 98: "profil",
494 | 99: "statfs",
495 | 100: "fstatfs",
496 | 101: "ioperm",
497 | 102: "socketcall",
498 | 103: "syslog",
499 | 104: "setitimer",
500 | 105: "getitimer",
501 | 106: "stat",
502 | 107: "lstat",
503 | 108: "fstat",
504 | 109: "olduname",
505 | 110: "iopl",
506 | 111: "vhangup",
507 | 112: "idle",
508 | 113: "vm86old",
509 | 114: "wait4",
510 | 115: "swapoff",
511 | 116: "sysinfo",
512 | 117: "ipc",
513 | 118: "fsync",
514 | 119: "sigreturn",
515 | 120: "clone",
516 | 121: "setdomainname",
517 | 122: "uname",
518 | 123: "modify_ldt",
519 | 124: "adjtimex",
520 | 125: "mprotect",
521 | 126: "sigprocmask",
522 | 127: "create_module",
523 | 128: "init_module",
524 | 129: "delete_module",
525 | 130: "get_kernel_syms",
526 | 131: "quotactl",
527 | 132: "getpgid",
528 | 133: "fchdir",
529 | 134: "bdflush",
530 | 135: "sysfs",
531 | 136: "personality",
532 | 137: "afs_syscall",
533 | 138: "setfsuid",
534 | 139: "setfsgid",
535 | 140: "_llseek",
536 | 141: "getdents",
537 | 142: "_newselect",
538 | 143: "flock",
539 | 144: "msync",
540 | 145: "readv",
541 | 146: "writev",
542 | 147: "getsid",
543 | 148: "fdatasync",
544 | 149: "_sysctl",
545 | 150: "mlock",
546 | 151: "munlock",
547 | 152: "mlockall",
548 | 153: "munlockall",
549 | 154: "sched_setparam",
550 | 155: "sched_getparam",
551 | 156: "sched_setscheduler",
552 | 157: "sched_getscheduler",
553 | 158: "sched_yield",
554 | 159: "sched_get_priority_max",
555 | 160: "sched_get_priority_min",
556 | 161: "sched_rr_get_interval",
557 | 162: "nanosleep",
558 | 163: "mremap",
559 | 164: "setresuid",
560 | 165: "getresuid",
561 | 166: "vm86",
562 | 167: "query_module",
563 | 168: "poll",
564 | 169: "nfsservctl",
565 | 170: "setresgid",
566 | 171: "getresgid",
567 | 172: "prctl",
568 | 173: "rt_sigreturn",
569 | 174: "rt_sigaction",
570 | 175: "rt_sigprocmask",
571 | 176: "rt_sigpending",
572 | 177: "rt_sigtimedwait",
573 | 178: "rt_sigqueueinfo",
574 | 179: "rt_sigsuspend",
575 | 180: "pread64",
576 | 181: "pwrite64",
577 | 182: "chown",
578 | 183: "getcwd",
579 | 184: "capget",
580 | 185: "capset",
581 | 186: "sigaltstack",
582 | 187: "sendfile",
583 | 188: "getpmsg",
584 | 189: "putpmsg",
585 | 190: "vfork",
586 | 191: "ugetrlimit",
587 | 192: "mmap2",
588 | 193: "truncate64",
589 | 194: "ftruncate64",
590 | 195: "stat64",
591 | 196: "lstat64",
592 | 197: "fstat64",
593 | 198: "lchown32",
594 | 199: "getuid32",
595 | 200: "getgid32",
596 | 201: "geteuid32",
597 | 202: "getegid32",
598 | 203: "setreuid32",
599 | 204: "setregid32",
600 | 205: "getgroups32",
601 | 206: "setgroups32",
602 | 207: "fchown32",
603 | 208: "setresuid32",
604 | 209: "getresuid32",
605 | 210: "setresgid32",
606 | 211: "getresgid32",
607 | 212: "chown32",
608 | 213: "setuid32",
609 | 214: "setgid32",
610 | 215: "setfsuid32",
611 | 216: "setfsgid32",
612 | 217: "pivot_root",
613 | 218: "mincore",
614 | 219: "madvise",
615 | 220: "getdents64",
616 | 221: "fcntl64",
617 | 224: "gettid",
618 | 225: "readahead",
619 | 226: "setxattr",
620 | 227: "lsetxattr",
621 | 228: "fsetxattr",
622 | 229: "getxattr",
623 | 230: "lgetxattr",
624 | 231: "fgetxattr",
625 | 232: "listxattr",
626 | 233: "llistxattr",
627 | 234: "flistxattr",
628 | 235: "removexattr",
629 | 236: "lremovexattr",
630 | 237: "fremovexattr",
631 | 238: "tkill",
632 | 239: "sendfile64",
633 | 240: "futex",
634 | 241: "sched_setaffinity",
635 | 242: "sched_getaffinity",
636 | 243: "set_thread_area",
637 | 244: "get_thread_area",
638 | 245: "io_setup",
639 | 246: "io_destroy",
640 | 247: "io_getevents",
641 | 248: "io_submit",
642 | 249: "io_cancel",
643 | 250: "fadvise64",
644 | 252: "exit_group",
645 | 253: "lookup_dcookie",
646 | 254: "epoll_create",
647 | 255: "epoll_ctl",
648 | 256: "epoll_wait",
649 | 257: "remap_file_pages",
650 | 258: "set_tid_address",
651 | 259: "timer_create",
652 | 260: "timer_settime",
653 | 261: "timer_gettime",
654 | 262: "timer_getoverrun",
655 | 263: "timer_delete",
656 | 264: "clock_settime",
657 | 265: "clock_gettime",
658 | 266: "clock_getres",
659 | 267: "clock_nanosleep",
660 | 268: "statfs64",
661 | 269: "fstatfs64",
662 | 270: "tgkill",
663 | 271: "utimes",
664 | 272: "fadvise64_64",
665 | 273: "vserver",
666 | 274: "mbind",
667 | 275: "get_mempolicy",
668 | 276: "set_mempolicy",
669 | 277: "mq_open",
670 | 278: "mq_unlink",
671 | 279: "mq_timedsend",
672 | 280: "mq_timedreceive",
673 | 281: "mq_notify",
674 | 282: "mq_getsetattr",
675 | 283: "kexec_load",
676 | 284: "waitid",
677 | 286: "add_key",
678 | 287: "request_key",
679 | 288: "keyctl",
680 | 289: "ioprio_set",
681 | 290: "ioprio_get",
682 | 291: "inotify_init",
683 | 292: "inotify_add_watch",
684 | 293: "inotify_rm_watch",
685 | 294: "migrate_pages",
686 | 295: "openat",
687 | 296: "mkdirat",
688 | 297: "mknodat",
689 | 298: "fchownat",
690 | 299: "futimesat",
691 | 300: "fstatat64",
692 | 301: "unlinkat",
693 | 302: "renameat",
694 | 303: "linkat",
695 | 304: "symlinkat",
696 | 305: "readlinkat",
697 | 306: "fchmodat",
698 | 307: "faccessat",
699 | 308: "pselect6",
700 | 309: "ppoll",
701 | 310: "unshare",
702 | 311: "set_robust_list",
703 | 312: "get_robust_list",
704 | 313: "splice",
705 | 314: "sync_file_range",
706 | 315: "tee",
707 | 316: "vmsplice",
708 | 317: "move_pages",
709 | 318: "getcpu",
710 | 319: "epoll_pwait",
711 | 320: "utimensat",
712 | 321: "signalfd",
713 | 322: "timerfd_create",
714 | 323: "eventfd",
715 | 324: "fallocate",
716 | 325: "timerfd_settime",
717 | 326: "timerfd_gettime",
718 | 327: "signalfd4",
719 | 328: "eventfd2",
720 | 329: "epoll_create1",
721 | 330: "dup3",
722 | 331: "pipe2",
723 | 332: "inotify_init1",
724 | 333: "preadv",
725 | 334: "pwritev",
726 | 335: "rt_tgsigqueueinfo",
727 | 336: "perf_event_open",
728 | 337: "recvmmsg",
729 | 338: "fanotify_init",
730 | 339: "fanotify_mark",
731 | 340: "prlimit64",
732 | 341: "name_to_handle_at",
733 | 342: "open_by_handle_at",
734 | 343: "clock_adjtime",
735 | 344: "syncfs",
736 | 345: "sendmmsg",
737 | 346: "setns",
738 | 347: "process_vm_readv",
739 | 348: "process_vm_writev",
740 | 349: "kcmp",
741 | 350: "finit_module",
742 | 351: "sched_setattr",
743 | 352: "sched_getattr",
744 | 353: "renameat2",
745 | 354: "seccomp",
746 | 355: "getrandom",
747 | 356: "memfd_create",
748 | 357: "bpf",
749 | 358: "execveat",
750 | 359: "socket",
751 | 360: "socketpair",
752 | 361: "bind",
753 | 362: "connect",
754 | 363: "listen",
755 | 364: "accept4",
756 | 365: "getsockopt",
757 | 366: "setsockopt",
758 | 367: "getsockname",
759 | 368: "getpeername",
760 | 369: "sendto",
761 | 370: "sendmsg",
762 | 371: "recvfrom",
763 | 372: "recvmsg",
764 | 373: "shutdown",
765 | 374: "userfaultfd",
766 | 375: "membarrier",
767 | 376: "mlock2",
768 | 377: "copy_file_range",
769 | 378: "preadv2",
770 | 379: "pwritev2",
771 | 380: "pkey_mprotect",
772 | 381: "pkey_alloc",
773 | 382: "pkey_free",
774 | 383: "statx",
775 | 384: "arch_prctl",
776 | }
777 |
778 | var WhitelistedSyscalls = []int{
779 | SyscallToId["execve"],
780 | SyscallToId["ptrace"],
781 | SyscallToId["fork"],
782 | SyscallToId["vfork"],
783 | SyscallToId["clone"],
784 | SyscallToId["mknod"],
785 | SyscallToId["chroot"],
786 | SyscallToId["mount"],
787 | SyscallToId["umount"],
788 | SyscallToId["umount2"],
789 | SyscallToId["setuid"],
790 | SyscallToId["setgid"],
791 | SyscallToId["setresuid"],
792 | SyscallToId["setresgid"],
793 | SyscallToId["getuid"],
794 | SyscallToId["getgid"],
795 | SyscallToId["geteuid"],
796 | SyscallToId["getegid"],
797 | SyscallToId["kill"],
798 | SyscallToId["tkill"],
799 | SyscallToId["prctl"],
800 | SyscallToId["seccomp"],
801 | SyscallToId["unshare"],
802 | SyscallToId["setns"],
803 | SyscallToId["capset"],
804 | SyscallToId["capget"],
805 | SyscallToId["socket"],
806 | SyscallToId["bind"],
807 | SyscallToId["connect"],
808 | SyscallToId["listen"],
809 | SyscallToId["accept"],
810 | SyscallToId["shutdown"],
811 | SyscallToId["setsockopt"],
812 | SyscallToId["getsockopt"],
813 | SyscallToId["recvmsg"],
814 | SyscallToId["sendmsg"],
815 | SyscallToId["recvfrom"],
816 | SyscallToId["sendto"],
817 | SyscallToId["getrandom"],
818 | SyscallToId["mknodat"],
819 | SyscallToId["fchownat"],
820 | }
821 |
--------------------------------------------------------------------------------
/internal/bpf/arch/arm.go:
--------------------------------------------------------------------------------
1 | // AUTOGENERATED FILE
2 |
3 | //go:build arm
4 | // +build arm
5 |
6 | package bpfarch
7 |
8 | const BpfProgramElf = bpfProgramName + "_arm.o"
9 |
10 | var SyscallToId = map[string]int{
11 | "restart_syscall": 0,
12 | "exit": 1,
13 | "fork": 2,
14 | "read": 3,
15 | "write": 4,
16 | "open": 5,
17 | "close": 6,
18 | "creat": 8,
19 | "link": 9,
20 | "unlink": 10,
21 | "execve": 11,
22 | "chdir": 12,
23 | "mknod": 14,
24 | "chmod": 15,
25 | "lchown": 16,
26 | "lseek": 19,
27 | "getpid": 20,
28 | "mount": 21,
29 | "setuid": 23,
30 | "getuid": 24,
31 | "ptrace": 26,
32 | "pause": 29,
33 | "access": 33,
34 | "nice": 34,
35 | "sync": 36,
36 | "kill": 37,
37 | "rename": 38,
38 | "mkdir": 39,
39 | "rmdir": 40,
40 | "dup": 41,
41 | "pipe": 42,
42 | "times": 43,
43 | "brk": 45,
44 | "setgid": 46,
45 | "getgid": 47,
46 | "geteuid": 49,
47 | "getegid": 50,
48 | "acct": 51,
49 | "umount2": 52,
50 | "ioctl": 54,
51 | "fcntl": 55,
52 | "setpgid": 57,
53 | "umask": 60,
54 | "chroot": 61,
55 | "ustat": 62,
56 | "dup2": 63,
57 | "getppid": 64,
58 | "getpgrp": 65,
59 | "setsid": 66,
60 | "sigaction": 67,
61 | "setreuid": 70,
62 | "setregid": 71,
63 | "sigsuspend": 72,
64 | "sigpending": 73,
65 | "sethostname": 74,
66 | "setrlimit": 75,
67 | "getrusage": 77,
68 | "gettimeofday": 78,
69 | "settimeofday": 79,
70 | "getgroups": 80,
71 | "setgroups": 81,
72 | "symlink": 83,
73 | "readlink": 85,
74 | "uselib": 86,
75 | "swapon": 87,
76 | "reboot": 88,
77 | "munmap": 91,
78 | "truncate": 92,
79 | "ftruncate": 93,
80 | "fchmod": 94,
81 | "fchown": 95,
82 | "getpriority": 96,
83 | "setpriority": 97,
84 | "statfs": 99,
85 | "fstatfs": 100,
86 | "syslog": 103,
87 | "setitimer": 104,
88 | "getitimer": 105,
89 | "stat": 106,
90 | "lstat": 107,
91 | "fstat": 108,
92 | "vhangup": 111,
93 | "wait4": 114,
94 | "swapoff": 115,
95 | "sysinfo": 116,
96 | "fsync": 118,
97 | "sigreturn": 119,
98 | "clone": 120,
99 | "setdomainname": 121,
100 | "uname": 122,
101 | "adjtimex": 124,
102 | "mprotect": 125,
103 | "sigprocmask": 126,
104 | "init_module": 128,
105 | "delete_module": 129,
106 | "quotactl": 131,
107 | "getpgid": 132,
108 | "fchdir": 133,
109 | "bdflush": 134,
110 | "sysfs": 135,
111 | "personality": 136,
112 | "setfsuid": 138,
113 | "setfsgid": 139,
114 | "_llseek": 140,
115 | "getdents": 141,
116 | "flock": 143,
117 | "msync": 144,
118 | "readv": 145,
119 | "writev": 146,
120 | "getsid": 147,
121 | "fdatasync": 148,
122 | "mlock": 150,
123 | "munlock": 151,
124 | "mlockall": 152,
125 | "munlockall": 153,
126 | "sched_setparam": 154,
127 | "sched_getparam": 155,
128 | "sched_setscheduler": 156,
129 | "sched_getscheduler": 157,
130 | "sched_yield": 158,
131 | "sched_get_priority_max": 159,
132 | "sched_get_priority_min": 160,
133 | "sched_rr_get_interval": 161,
134 | "nanosleep": 162,
135 | "mremap": 163,
136 | "setresuid": 164,
137 | "getresuid": 165,
138 | "poll": 168,
139 | "nfsservctl": 169,
140 | "setresgid": 170,
141 | "getresgid": 171,
142 | "prctl": 172,
143 | "rt_sigreturn": 173,
144 | "rt_sigaction": 174,
145 | "rt_sigprocmask": 175,
146 | "rt_sigpending": 176,
147 | "rt_sigtimedwait": 177,
148 | "rt_sigqueueinfo": 178,
149 | "rt_sigsuspend": 179,
150 | "pread64": 180,
151 | "pwrite64": 181,
152 | "chown": 182,
153 | "getcwd": 183,
154 | "capget": 184,
155 | "capset": 185,
156 | "sigaltstack": 186,
157 | "sendfile": 187,
158 | "vfork": 190,
159 | "ugetrlimit": 191,
160 | "mmap2": 192,
161 | "truncate64": 193,
162 | "ftruncate64": 194,
163 | "stat64": 195,
164 | "lstat64": 196,
165 | "fstat64": 197,
166 | "lchown32": 198,
167 | "getuid32": 199,
168 | "getgid32": 200,
169 | "geteuid32": 201,
170 | "getegid32": 202,
171 | "setreuid32": 203,
172 | "setregid32": 204,
173 | "getgroups32": 205,
174 | "setgroups32": 206,
175 | "fchown32": 207,
176 | "setresuid32": 208,
177 | "getresuid32": 209,
178 | "setresgid32": 210,
179 | "getresgid32": 211,
180 | "chown32": 212,
181 | "setuid32": 213,
182 | "setgid32": 214,
183 | "setfsuid32": 215,
184 | "setfsgid32": 216,
185 | "getdents64": 217,
186 | "pivot_root": 218,
187 | "mincore": 219,
188 | "madvise": 220,
189 | "fcntl64": 221,
190 | "gettid": 224,
191 | "readahead": 225,
192 | "setxattr": 226,
193 | "lsetxattr": 227,
194 | "fsetxattr": 228,
195 | "getxattr": 229,
196 | "lgetxattr": 230,
197 | "fgetxattr": 231,
198 | "listxattr": 232,
199 | "llistxattr": 233,
200 | "flistxattr": 234,
201 | "removexattr": 235,
202 | "lremovexattr": 236,
203 | "fremovexattr": 237,
204 | "tkill": 238,
205 | "sendfile64": 239,
206 | "futex": 240,
207 | "sched_setaffinity": 241,
208 | "sched_getaffinity": 242,
209 | "io_setup": 243,
210 | "io_destroy": 244,
211 | "io_getevents": 245,
212 | "io_submit": 246,
213 | "io_cancel": 247,
214 | "exit_group": 248,
215 | "lookup_dcookie": 249,
216 | "epoll_create": 250,
217 | "epoll_ctl": 251,
218 | "epoll_wait": 252,
219 | "remap_file_pages": 253,
220 | "set_tid_address": 256,
221 | "timer_create": 257,
222 | "timer_settime": 258,
223 | "timer_gettime": 259,
224 | "timer_getoverrun": 260,
225 | "timer_delete": 261,
226 | "clock_settime": 262,
227 | "clock_gettime": 263,
228 | "clock_getres": 264,
229 | "clock_nanosleep": 265,
230 | "statfs64": 266,
231 | "fstatfs64": 267,
232 | "tgkill": 268,
233 | "utimes": 269,
234 | "arm_fadvise64_64": 270,
235 | "pciconfig_iobase": 271,
236 | "pciconfig_read": 272,
237 | "pciconfig_write": 273,
238 | "mq_open": 274,
239 | "mq_unlink": 275,
240 | "mq_timedsend": 276,
241 | "mq_timedreceive": 277,
242 | "mq_notify": 278,
243 | "mq_getsetattr": 279,
244 | "waitid": 280,
245 | "socket": 281,
246 | "bind": 282,
247 | "connect": 283,
248 | "listen": 284,
249 | "accept": 285,
250 | "getsockname": 286,
251 | "getpeername": 287,
252 | "socketpair": 288,
253 | "send": 289,
254 | "sendto": 290,
255 | "recv": 291,
256 | "recvfrom": 292,
257 | "shutdown": 293,
258 | "setsockopt": 294,
259 | "getsockopt": 295,
260 | "sendmsg": 296,
261 | "recvmsg": 297,
262 | "semop": 298,
263 | "semget": 299,
264 | "semctl": 300,
265 | "msgsnd": 301,
266 | "msgrcv": 302,
267 | "msgget": 303,
268 | "msgctl": 304,
269 | "shmat": 305,
270 | "shmdt": 306,
271 | "shmget": 307,
272 | "shmctl": 308,
273 | "add_key": 309,
274 | "request_key": 310,
275 | "keyctl": 311,
276 | "semtimedop": 312,
277 | "vserver": 313,
278 | "ioprio_set": 314,
279 | "ioprio_get": 315,
280 | "inotify_init": 316,
281 | "inotify_add_watch": 317,
282 | "inotify_rm_watch": 318,
283 | "mbind": 319,
284 | "get_mempolicy": 320,
285 | "set_mempolicy": 321,
286 | "openat": 322,
287 | "mkdirat": 323,
288 | "mknodat": 324,
289 | "fchownat": 325,
290 | "futimesat": 326,
291 | "fstatat64": 327,
292 | "unlinkat": 328,
293 | "renameat": 329,
294 | "linkat": 330,
295 | "symlinkat": 331,
296 | "readlinkat": 332,
297 | "fchmodat": 333,
298 | "faccessat": 334,
299 | "pselect6": 335,
300 | "ppoll": 336,
301 | "unshare": 337,
302 | "set_robust_list": 338,
303 | "get_robust_list": 339,
304 | "splice": 340,
305 | "sync_file_range2": 341,
306 | "tee": 342,
307 | "vmsplice": 343,
308 | "move_pages": 344,
309 | "getcpu": 345,
310 | "epoll_pwait": 346,
311 | "kexec_load": 347,
312 | "utimensat": 348,
313 | "signalfd": 349,
314 | "timerfd_create": 350,
315 | "eventfd": 351,
316 | "fallocate": 352,
317 | "timerfd_settime": 353,
318 | "timerfd_gettime": 354,
319 | "signalfd4": 355,
320 | "eventfd2": 356,
321 | "epoll_create1": 357,
322 | "dup3": 358,
323 | "pipe2": 359,
324 | "inotify_init1": 360,
325 | "preadv": 361,
326 | "pwritev": 362,
327 | "rt_tgsigqueueinfo": 363,
328 | "perf_event_open": 364,
329 | "recvmmsg": 365,
330 | "accept4": 366,
331 | "fanotify_init": 367,
332 | "fanotify_mark": 368,
333 | "prlimit64": 369,
334 | "name_to_handle_at": 370,
335 | "open_by_handle_at": 371,
336 | "clock_adjtime": 372,
337 | "syncfs": 373,
338 | "sendmmsg": 374,
339 | "setns": 375,
340 | "process_vm_readv": 376,
341 | "process_vm_writev": 377,
342 | "kcmp": 378,
343 | "finit_module": 379,
344 | "sched_setattr": 380,
345 | "sched_getattr": 381,
346 | "renameat2": 382,
347 | "seccomp": 383,
348 | "getrandom": 384,
349 | "memfd_create": 385,
350 | "bpf": 386,
351 | "execveat": 387,
352 | "userfaultfd": 388,
353 | "membarrier": 389,
354 | "mlock2": 390,
355 | "copy_file_range": 391,
356 | "preadv2": 392,
357 | "pwritev2": 393,
358 | "pkey_mprotect": 394,
359 | "pkey_alloc": 395,
360 | "pkey_free": 396,
361 | "statx": 397,
362 | "ARM_breakpoint": 983041,
363 | "ARM_cacheflush": 983042,
364 | "ARM_usr26": 983043,
365 | "ARM_usr32": 983044,
366 | "ARM_set_tls": 983045,
367 | }
368 |
369 | var IdToSyscall = map[int]string{
370 | 0: "restart_syscall",
371 | 1: "exit",
372 | 2: "fork",
373 | 3: "read",
374 | 4: "write",
375 | 5: "open",
376 | 6: "close",
377 | 8: "creat",
378 | 9: "link",
379 | 10: "unlink",
380 | 11: "execve",
381 | 12: "chdir",
382 | 14: "mknod",
383 | 15: "chmod",
384 | 16: "lchown",
385 | 19: "lseek",
386 | 20: "getpid",
387 | 21: "mount",
388 | 23: "setuid",
389 | 24: "getuid",
390 | 26: "ptrace",
391 | 29: "pause",
392 | 33: "access",
393 | 34: "nice",
394 | 36: "sync",
395 | 37: "kill",
396 | 38: "rename",
397 | 39: "mkdir",
398 | 40: "rmdir",
399 | 41: "dup",
400 | 42: "pipe",
401 | 43: "times",
402 | 45: "brk",
403 | 46: "setgid",
404 | 47: "getgid",
405 | 49: "geteuid",
406 | 50: "getegid",
407 | 51: "acct",
408 | 52: "umount2",
409 | 54: "ioctl",
410 | 55: "fcntl",
411 | 57: "setpgid",
412 | 60: "umask",
413 | 61: "chroot",
414 | 62: "ustat",
415 | 63: "dup2",
416 | 64: "getppid",
417 | 65: "getpgrp",
418 | 66: "setsid",
419 | 67: "sigaction",
420 | 70: "setreuid",
421 | 71: "setregid",
422 | 72: "sigsuspend",
423 | 73: "sigpending",
424 | 74: "sethostname",
425 | 75: "setrlimit",
426 | 77: "getrusage",
427 | 78: "gettimeofday",
428 | 79: "settimeofday",
429 | 80: "getgroups",
430 | 81: "setgroups",
431 | 83: "symlink",
432 | 85: "readlink",
433 | 86: "uselib",
434 | 87: "swapon",
435 | 88: "reboot",
436 | 91: "munmap",
437 | 92: "truncate",
438 | 93: "ftruncate",
439 | 94: "fchmod",
440 | 95: "fchown",
441 | 96: "getpriority",
442 | 97: "setpriority",
443 | 99: "statfs",
444 | 100: "fstatfs",
445 | 103: "syslog",
446 | 104: "setitimer",
447 | 105: "getitimer",
448 | 106: "stat",
449 | 107: "lstat",
450 | 108: "fstat",
451 | 111: "vhangup",
452 | 114: "wait4",
453 | 115: "swapoff",
454 | 116: "sysinfo",
455 | 118: "fsync",
456 | 119: "sigreturn",
457 | 120: "clone",
458 | 121: "setdomainname",
459 | 122: "uname",
460 | 124: "adjtimex",
461 | 125: "mprotect",
462 | 126: "sigprocmask",
463 | 128: "init_module",
464 | 129: "delete_module",
465 | 131: "quotactl",
466 | 132: "getpgid",
467 | 133: "fchdir",
468 | 134: "bdflush",
469 | 135: "sysfs",
470 | 136: "personality",
471 | 138: "setfsuid",
472 | 139: "setfsgid",
473 | 140: "_llseek",
474 | 141: "getdents",
475 | 143: "flock",
476 | 144: "msync",
477 | 145: "readv",
478 | 146: "writev",
479 | 147: "getsid",
480 | 148: "fdatasync",
481 | 150: "mlock",
482 | 151: "munlock",
483 | 152: "mlockall",
484 | 153: "munlockall",
485 | 154: "sched_setparam",
486 | 155: "sched_getparam",
487 | 156: "sched_setscheduler",
488 | 157: "sched_getscheduler",
489 | 158: "sched_yield",
490 | 159: "sched_get_priority_max",
491 | 160: "sched_get_priority_min",
492 | 161: "sched_rr_get_interval",
493 | 162: "nanosleep",
494 | 163: "mremap",
495 | 164: "setresuid",
496 | 165: "getresuid",
497 | 168: "poll",
498 | 169: "nfsservctl",
499 | 170: "setresgid",
500 | 171: "getresgid",
501 | 172: "prctl",
502 | 173: "rt_sigreturn",
503 | 174: "rt_sigaction",
504 | 175: "rt_sigprocmask",
505 | 176: "rt_sigpending",
506 | 177: "rt_sigtimedwait",
507 | 178: "rt_sigqueueinfo",
508 | 179: "rt_sigsuspend",
509 | 180: "pread64",
510 | 181: "pwrite64",
511 | 182: "chown",
512 | 183: "getcwd",
513 | 184: "capget",
514 | 185: "capset",
515 | 186: "sigaltstack",
516 | 187: "sendfile",
517 | 190: "vfork",
518 | 191: "ugetrlimit",
519 | 192: "mmap2",
520 | 193: "truncate64",
521 | 194: "ftruncate64",
522 | 195: "stat64",
523 | 196: "lstat64",
524 | 197: "fstat64",
525 | 198: "lchown32",
526 | 199: "getuid32",
527 | 200: "getgid32",
528 | 201: "geteuid32",
529 | 202: "getegid32",
530 | 203: "setreuid32",
531 | 204: "setregid32",
532 | 205: "getgroups32",
533 | 206: "setgroups32",
534 | 207: "fchown32",
535 | 208: "setresuid32",
536 | 209: "getresuid32",
537 | 210: "setresgid32",
538 | 211: "getresgid32",
539 | 212: "chown32",
540 | 213: "setuid32",
541 | 214: "setgid32",
542 | 215: "setfsuid32",
543 | 216: "setfsgid32",
544 | 217: "getdents64",
545 | 218: "pivot_root",
546 | 219: "mincore",
547 | 220: "madvise",
548 | 221: "fcntl64",
549 | 224: "gettid",
550 | 225: "readahead",
551 | 226: "setxattr",
552 | 227: "lsetxattr",
553 | 228: "fsetxattr",
554 | 229: "getxattr",
555 | 230: "lgetxattr",
556 | 231: "fgetxattr",
557 | 232: "listxattr",
558 | 233: "llistxattr",
559 | 234: "flistxattr",
560 | 235: "removexattr",
561 | 236: "lremovexattr",
562 | 237: "fremovexattr",
563 | 238: "tkill",
564 | 239: "sendfile64",
565 | 240: "futex",
566 | 241: "sched_setaffinity",
567 | 242: "sched_getaffinity",
568 | 243: "io_setup",
569 | 244: "io_destroy",
570 | 245: "io_getevents",
571 | 246: "io_submit",
572 | 247: "io_cancel",
573 | 248: "exit_group",
574 | 249: "lookup_dcookie",
575 | 250: "epoll_create",
576 | 251: "epoll_ctl",
577 | 252: "epoll_wait",
578 | 253: "remap_file_pages",
579 | 256: "set_tid_address",
580 | 257: "timer_create",
581 | 258: "timer_settime",
582 | 259: "timer_gettime",
583 | 260: "timer_getoverrun",
584 | 261: "timer_delete",
585 | 262: "clock_settime",
586 | 263: "clock_gettime",
587 | 264: "clock_getres",
588 | 265: "clock_nanosleep",
589 | 266: "statfs64",
590 | 267: "fstatfs64",
591 | 268: "tgkill",
592 | 269: "utimes",
593 | 270: "arm_fadvise64_64",
594 | 271: "pciconfig_iobase",
595 | 272: "pciconfig_read",
596 | 273: "pciconfig_write",
597 | 274: "mq_open",
598 | 275: "mq_unlink",
599 | 276: "mq_timedsend",
600 | 277: "mq_timedreceive",
601 | 278: "mq_notify",
602 | 279: "mq_getsetattr",
603 | 280: "waitid",
604 | 281: "socket",
605 | 282: "bind",
606 | 283: "connect",
607 | 284: "listen",
608 | 285: "accept",
609 | 286: "getsockname",
610 | 287: "getpeername",
611 | 288: "socketpair",
612 | 289: "send",
613 | 290: "sendto",
614 | 291: "recv",
615 | 292: "recvfrom",
616 | 293: "shutdown",
617 | 294: "setsockopt",
618 | 295: "getsockopt",
619 | 296: "sendmsg",
620 | 297: "recvmsg",
621 | 298: "semop",
622 | 299: "semget",
623 | 300: "semctl",
624 | 301: "msgsnd",
625 | 302: "msgrcv",
626 | 303: "msgget",
627 | 304: "msgctl",
628 | 305: "shmat",
629 | 306: "shmdt",
630 | 307: "shmget",
631 | 308: "shmctl",
632 | 309: "add_key",
633 | 310: "request_key",
634 | 311: "keyctl",
635 | 312: "semtimedop",
636 | 313: "vserver",
637 | 314: "ioprio_set",
638 | 315: "ioprio_get",
639 | 316: "inotify_init",
640 | 317: "inotify_add_watch",
641 | 318: "inotify_rm_watch",
642 | 319: "mbind",
643 | 320: "get_mempolicy",
644 | 321: "set_mempolicy",
645 | 322: "openat",
646 | 323: "mkdirat",
647 | 324: "mknodat",
648 | 325: "fchownat",
649 | 326: "futimesat",
650 | 327: "fstatat64",
651 | 328: "unlinkat",
652 | 329: "renameat",
653 | 330: "linkat",
654 | 331: "symlinkat",
655 | 332: "readlinkat",
656 | 333: "fchmodat",
657 | 334: "faccessat",
658 | 335: "pselect6",
659 | 336: "ppoll",
660 | 337: "unshare",
661 | 338: "set_robust_list",
662 | 339: "get_robust_list",
663 | 340: "splice",
664 | 341: "sync_file_range2",
665 | 342: "tee",
666 | 343: "vmsplice",
667 | 344: "move_pages",
668 | 345: "getcpu",
669 | 346: "epoll_pwait",
670 | 347: "kexec_load",
671 | 348: "utimensat",
672 | 349: "signalfd",
673 | 350: "timerfd_create",
674 | 351: "eventfd",
675 | 352: "fallocate",
676 | 353: "timerfd_settime",
677 | 354: "timerfd_gettime",
678 | 355: "signalfd4",
679 | 356: "eventfd2",
680 | 357: "epoll_create1",
681 | 358: "dup3",
682 | 359: "pipe2",
683 | 360: "inotify_init1",
684 | 361: "preadv",
685 | 362: "pwritev",
686 | 363: "rt_tgsigqueueinfo",
687 | 364: "perf_event_open",
688 | 365: "recvmmsg",
689 | 366: "accept4",
690 | 367: "fanotify_init",
691 | 368: "fanotify_mark",
692 | 369: "prlimit64",
693 | 370: "name_to_handle_at",
694 | 371: "open_by_handle_at",
695 | 372: "clock_adjtime",
696 | 373: "syncfs",
697 | 374: "sendmmsg",
698 | 375: "setns",
699 | 376: "process_vm_readv",
700 | 377: "process_vm_writev",
701 | 378: "kcmp",
702 | 379: "finit_module",
703 | 380: "sched_setattr",
704 | 381: "sched_getattr",
705 | 382: "renameat2",
706 | 383: "seccomp",
707 | 384: "getrandom",
708 | 385: "memfd_create",
709 | 386: "bpf",
710 | 387: "execveat",
711 | 388: "userfaultfd",
712 | 389: "membarrier",
713 | 390: "mlock2",
714 | 391: "copy_file_range",
715 | 392: "preadv2",
716 | 393: "pwritev2",
717 | 394: "pkey_mprotect",
718 | 395: "pkey_alloc",
719 | 396: "pkey_free",
720 | 397: "statx",
721 | 983041: "ARM_breakpoint",
722 | 983042: "ARM_cacheflush",
723 | 983043: "ARM_usr26",
724 | 983044: "ARM_usr32",
725 | 983045: "ARM_set_tls",
726 | }
727 |
728 | var WhitelistedSyscalls = []int{
729 | SyscallToId["restart_syscall"],
730 | SyscallToId["exit"],
731 | SyscallToId["fork"],
732 | SyscallToId["creat"],
733 | SyscallToId["link"],
734 | SyscallToId["unlink"],
735 | SyscallToId["execve"],
736 | SyscallToId["mknod"],
737 | SyscallToId["ptrace"],
738 | SyscallToId["setuid"],
739 | SyscallToId["getuid"],
740 | SyscallToId["setgid"],
741 | SyscallToId["getgid"],
742 | SyscallToId["seteuid"],
743 | SyscallToId["getegid"],
744 | SyscallToId["setpgid"],
745 | SyscallToId["setreuid"],
746 | SyscallToId["setregid"],
747 | SyscallToId["setresuid"],
748 | SyscallToId["getresuid"],
749 | SyscallToId["setresgid"],
750 | SyscallToId["getresgid"],
751 | SyscallToId["prctl"],
752 | SyscallToId["capget"],
753 | SyscallToId["capset"],
754 | SyscallToId["seccomp"],
755 | SyscallToId["setns"],
756 | SyscallToId["unshare"],
757 | SyscallToId["chroot"],
758 | SyscallToId["mount"],
759 | SyscallToId["umount2"],
760 | SyscallToId["pivot_root"],
761 | SyscallToId["clone"],
762 | SyscallToId["wait4"],
763 | SyscallToId["kill"],
764 | SyscallToId["nice"],
765 | SyscallToId["kill"],
766 | SyscallToId["tkill"],
767 | SyscallToId["tgkill"],
768 | SyscallToId["socket"],
769 | SyscallToId["bind"],
770 | SyscallToId["connect"],
771 | SyscallToId["listen"],
772 | SyscallToId["accept"],
773 | SyscallToId["accept4"],
774 | SyscallToId["getsockname"],
775 | SyscallToId["getpeername"],
776 | SyscallToId["socketpair"],
777 | SyscallToId["sendto"],
778 | SyscallToId["recvfrom"],
779 | SyscallToId["sendmsg"],
780 | SyscallToId["recvmsg"],
781 | SyscallToId["getsockopt"],
782 | SyscallToId["setsockopt"],
783 | SyscallToId["shutdown"],
784 | SyscallToId["sendmmsg"],
785 | SyscallToId["sethostname"],
786 | SyscallToId["setdomainname"],
787 | }
788 |
--------------------------------------------------------------------------------