Skip to content

Instantly share code, notes, and snippets.

@andrewkroh
Created April 9, 2018 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewkroh/1d0af375eb5d697cdba3c9b03d91b258 to your computer and use it in GitHub Desktop.
Save andrewkroh/1d0af375eb5d697cdba3c9b03d91b258 to your computer and use it in GitHub Desktop.
Seccomp BPF Filter Analysis in Go

Generating Seccomp BPF Filters with libbseccomp in Go

// +build linux

package main

import (
	"log"
	"os"

	libseccomp "github.com/seccomp/libseccomp-golang"
)

func main() {
	filter, err := libseccomp.NewFilter(libseccomp.ActErrno)
	if err != nil {
		log.Fatalf("error creating filter: %s", err)
	}

	if err := filter.AddRule(libseccomp.ScmpSyscall(59), libseccomp.ActAllow); err != nil {
		log.Fatal("failed adding rule", err)
	}


	log.Println("Dumping rule")
	filter.ExportPFC(os.Stdout)

	out, err := os.Create("bpf.bin")
	if err != nil {
		log.Fatal("failed to create bpf.bin", err)
	}
	defer out.Close()

	filter.ExportBPF(out)
}
#
# pseudo filter code start
#
# filter for arch x86_64 (3221225534)
if ($arch == 3221225534)
  # filter for syscall "execve" (59) [priority: 65535]
  if ($syscall == 59)
    action ALLOW;
  # default action
  action ERRNO(0);
# invalid architecture action
action KILL;
#
# pseudo filter code end
#
$ hexdump -C bpf.bin 
00000000  20 00 00 00 04 00 00 00  15 00 00 05 3e 00 00 c0  | ...........>...|
00000010  20 00 00 00 00 00 00 00  35 00 03 00 00 00 00 40  | .......5......@|
00000020  15 00 01 00 3b 00 00 00  06 00 00 00 00 00 05 00  |....;...........|
00000030  06 00 00 00 00 00 ff 7f  06 00 00 00 00 00 00 00  |................|

Disassembling Seccomp BPF Filters in Go

package main

import (
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"io/ioutil"
	"log"

	"golang.org/x/net/bpf"
)

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		log.Fatalln("You must specify the filename of a BPF filter")
	}

	// Read the file.
	data, err := ioutil.ReadFile(args[0])
	if err != nil {
		log.Fatalln("failed to read file", err)
	}

	// Read the instructions.
	raw := make([]bpf.RawInstruction, len(data)/8)
	if err = binary.Read(bytes.NewReader(data), binary.LittleEndian, raw); err != nil {
		log.Fatalln("failed to read bytes", err)
	}

	// Disassemble the instructions.
	instructions, all := bpf.Disassemble(raw)
	if !all {
		log.Println("failed to decode all instructions")
	}

	// Log them.
	for i, instruction := range instructions {
		fmt.Printf("%d: %+v\n", i, instruction)
	}
}
go run dissassembler.go bpf.bin
0: ld [4]
1: jneq #3221225534,5
2: ld [0]
3: jge #1073741824,3
4: jeq #59,1
5: ret #327680
6: ret #2147418112
7: ret #0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment