<|start_filename|>modify-arguments-on-the-fly/tracee/Makefile<|end_filename|>
APP=tracee

build:
	go build -gcflags='-l' -o $(APP)

run:
	./$(APP) 'hello world!'

clean:
	rm -f $(APP)


<|start_filename|>modify-arguments-on-the-fly/tracee/main.go<|end_filename|>
package main

import (
	"fmt"
	"os"
	"time"
)

//go:noinline
func greet(s string) {
	fmt.Println(s)
}

func main() {
	for {
		greet(os.Args[1])
		time.Sleep(time.Second)
	}
}


<|start_filename|>xdp-helloworld/drop.c<|end_filename|>
#include <linux/bpf.h>
#include "bpf_helpers.h"

#define SEC(NAME) __attribute__((section(NAME), used))

SEC("xdp")
int xdp_drop(struct xdp_md *ctx) {
   bpf_printk("xdp_drop get called\n");
   return XDP_DROP;
}

char __license[] SEC("license") = "GPL";


<|start_filename|>trace-tcpreset-and-tcpretransmit/tracer/Makefile<|end_filename|>
APP=tracer

build:
	go build -o $(APP)

run:
	sudo ./$(APP)

view:
	sudo python3 view.py

clean:
	rm -f $(APP)


<|start_filename|>xdp-security-group/server/Makefile<|end_filename|>
APP=testserver

build:
	go build -o $(APP)

run:
	./$(APP)

clean:
	rm -f $(APP)


<|start_filename|>tc-traffic-stat/pcap/Makefile<|end_filename|>
APP=pcap-stat

build:
	g++ -Wall -std=c++17 -o $(APP) main.cpp -lpcap -lpthread

run:
	sudo ./$(APP)

clean:
	rm -f $(APP)


<|start_filename|>trace-tcpreset-and-tcpretransmit/tracer/doc.go<|end_filename|>
package main

// http://www.brendangregg.com/blog/2018-03-22/tcp-tracepoints.html
// http://www.brendangregg.com/blog/2018-05-31/linux-tcpdrop.html


<|start_filename|>tc-traffic-stat/bpf/trafficstat.bpf.c<|end_filename|>
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

int ifindex = 0;
__u64 traffic = 0;

SEC("tp_btf/netif_receive_skb")
int BPF_PROG(netif_receive_skb, struct sk_buff *skb)
{
    if (skb->dev->ifindex == ifindex) {
        traffic += skb->data_len;
    }
    return 0;
}

char LICENSE[] SEC("license") = "GPL";


<|start_filename|>tc-traffic-stat/pcap/main.cpp<|end_filename|>
#include <pcap.h>
#include <linux/ip.h>

#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <future>
#include <thread>

#define ETHERNET_HEADER_LEN 14
#define MIN_IP_HEADER_LEN 20
#define IP_HL(ip) (((ip)->ihl) & 0x0f)

const char* dev = "br-7e20abc6df31";
const char* filter_expr = "src net 172.20.0.0/16";

int64_t traffic = 0;

// Reference:
//      https://www.tcpdump.org/manpages/
//      https://tools.ietf.org/html/rfc791
void traffic_stat() {
    // find the IPv4 network number and netmask for a device
    bpf_u_int32 net = 0;
    bpf_u_int32 mask = 0;
    char errbuf[PCAP_ERRBUF_SIZE] = {0};
    int ret = pcap_lookupnet(dev, &net, &mask, errbuf);
    if (ret == PCAP_ERROR) {
        fprintf(stderr, "pcap_lookupnet failed: %s\n", errbuf);
        exit(EXIT_FAILURE);
    }

    // open a device for capturing
    int promisc = 1;
    int timeout = 1000;   // in milliseconds
    const int SNAP_LEN = 64;
    auto handle = pcap_open_live(dev, SNAP_LEN, promisc, timeout, errbuf);
    if (!handle) {
        fprintf(stderr, "pcap_open_live failed: %s\n", errbuf);
        exit(EXIT_FAILURE);
    }

    // compile a filter expression
    struct bpf_program fp;
    int optimize = 1;
    ret = pcap_compile(handle, &fp, filter_expr, optimize, net);
    if (ret == PCAP_ERROR) {
        fprintf(stderr, "pcap_compile failed: %s\n", pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }

    // set the filter
    ret = pcap_setfilter(handle, &fp);
    if (ret == PCAP_ERROR) {
        fprintf(stderr, "pcap_setfilter failed: %s\n", pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }

    // process packets from a live capture
    int packet_count = -1;  // -1 means infinity
    pcap_loop(handle, packet_count, [](u_char* args, const struct pcap_pkthdr* header, const u_char* bytes) {

        auto ip_header = reinterpret_cast<iphdr*>(const_cast<u_char*>(bytes) + ETHERNET_HEADER_LEN);
        const int ip_header_len = IP_HL(ip_header) * 4;
        if (ip_header_len < MIN_IP_HEADER_LEN) {
            return;
        }

        auto len = ntohs(ip_header->tot_len);
        if (len <= 0) {
            return;
        }

        auto traffic = reinterpret_cast<int64_t*>(args);
        *traffic += len;

    }, reinterpret_cast<u_char*>(&traffic));

    // free a BPF program
    pcap_freecode(&fp);
    // close the capture device
    pcap_close(handle);
}

int main() {
    auto task = std::async(std::launch::async, traffic_stat);
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
        printf("traffic in bytes: %ld\n", traffic);
    }
    task.wait();
    return 0;
}


<|start_filename|>trace-tcpreset-and-tcpretransmit/tracer/main.go<|end_filename|>
package main

import (
	"fmt"

	"github.com/iovisor/gobpf/bcc"
)

const bpfProgram = `
#include <uapi/linux/ptrace.h>
#include <net/sock.h>

int log_tcp_retransmit(struct pt_regs *ctx, struct sock *sk) {
    u16 port = sk->__sk_common.skc_dport;
    u32 daddr = sk->__sk_common.skc_daddr;
    u8 state = sk->__sk_common.skc_state;
    bpf_trace_printk("tcp_retransmit port=%d dst=%d state=%d\n", port, daddr, state);
    return 0;
}

int log_tcp_reset(struct pt_regs *ctx, struct sock *sk) {
    u16 port = sk->__sk_common.skc_dport;
    u32 daddr = sk->__sk_common.skc_daddr;
    u8 state = sk->__sk_common.skc_state;
    bpf_trace_printk("tcp_reset port=%d dst=%d state=%d\n", port, daddr, state);
    return 0;
}

int log_tcp_drop(struct pt_regs *ctx, struct sock *sk) {
    u16 port = sk->__sk_common.skc_dport;
    u32 daddr = sk->__sk_common.skc_daddr;
    u8 state = sk->__sk_common.skc_state;
    bpf_trace_printk("tcp_drop port=%d dst=%d state=%d\n", port, daddr, state);
    return 0;
}
`

const (
	funcNameTCPRetransmit  = "log_tcp_retransmit"
	funcNameTCPReset       = "log_tcp_reset"
	funcNameTCPDrop        = "log_tcp_drop"
	eventNameTCPRetransmit = "tcp_retransmit_skb"
	eventNameTCPReset      = "tcp_reset"
	eventNameTCPDrop       = "tcp_drop"
	maxActive              = 0
)

func main() {
	bpfModule := bcc.NewModule(bpfProgram, []string{})
	defer bpfModule.Close()

	// TCP Retransmission
	uprobeFD, err := bpfModule.LoadKprobe(funcNameTCPRetransmit)
	if err != nil {
		panic(err)
	}
	err = bpfModule.AttachKprobe(eventNameTCPRetransmit, uprobeFD, maxActive)
	if err != nil {
		panic(err)
	}

	// TCP Reset
	uprobeFD, err = bpfModule.LoadKprobe(funcNameTCPReset)
	if err != nil {
		panic(err)
	}
	err = bpfModule.AttachKprobe(eventNameTCPReset, uprobeFD, maxActive)
	if err != nil {
		panic(err)
	}

	// TCP Drop
	uprobeFD, err = bpfModule.LoadKprobe(funcNameTCPDrop)
	if err != nil {
		panic(err)
	}
	err = bpfModule.AttachKprobe(eventNameTCPDrop, uprobeFD, maxActive)
	if err != nil {
		panic(err)
	}

	fmt.Println("attached!")
	select {}
}


<|start_filename|>modify-arguments-on-the-fly/tracer/Makefile<|end_filename|>
APP=tracer
ROOT=$(realpath ..)

build:
	go build -o $(APP)

run:
	sudo ./$(APP) $(ROOT)/tracee/tracee 'main.greet'

clean:
	rm -f $(APP)


<|start_filename|>uretprobe-with-golang-the-wrong-way/tracee/main.go<|end_filename|>
package main

import (
	"fmt"
	"os"
	"time"
)

//go:noinline
func foobar() (int, string, int) {
	var x [10]int
	foo(x)
	return 0xbeef, os.Args[1], 0xfaac
}

//go:noinline
func foo(x [10]int) {
	var y [100]int
	bar(y)
}

//go:noinline
func bar(y [100]int) {
	var z [1000]int
	buz(z)
}

//go:noinline
func buz(z [1000]int) {

}

func main() {
	for {
		a, b, c := foobar()
		fmt.Printf("%x %s %x\n", a, b, c)
		time.Sleep(time.Second)
	}
}


<|start_filename|>xdp-security-group/server/main.go<|end_filename|>
package main

import (
	"io"
	"log"
	"net"
)

func serve(c net.Conn) {
	defer c.Close()

	log.Printf("client connected: %s\n", c.RemoteAddr().String())
	io.Copy(c, c)
	log.Printf("client closed: %s\n", c.RemoteAddr().String())
}

func main() {
	lis, err := net.Listen("tcp", ":12160")
	if err != nil {
		panic(err)
	}

	for {
		conn, err := lis.Accept()
		if err != nil {
			panic(err)
		}
		go serve(conn)
	}
}


<|start_filename|>xdp-security-group/Makefile<|end_filename|>
ROOT_DIR=$(realpath ..)
LIBBPF_HEADERS_DIR=$(ROOT_DIR)/tc-traffic-stat/bpf/libbpf/src

DEV_NAME=eth0
OBJ=sg.bpf.o

build:
	clang -I$(LIBBPF_HEADERS_DIR) -Wall -g -O2 -target bpf -c sg.bpf.c -o $(OBJ)

load:
	sudo ip link set dev $(DEV_NAME) xdpgeneric obj $(OBJ) sec xdp verbose

unload:
	sudo ip link set dev $(DEV_NAME) xdpgeneric off

dump:
	llvm-objdump-10 -S --no-show-raw-insn $(OBJ)

clean:
	rm -f $(OBJ)


<|start_filename|>tc-bandwidth-limit/Makefile<|end_filename|>
init:
	# 512MB = 4KB * 128K
	dd if=/dev/zero of=/tmp/testfile bs=4096 count=131072

run:
	sudo docker run -d --rm \
		-p 10086:80 \
		-v /tmp/testfile:/home/data/testfile \
		-v $(PWD)/default.conf:/etc/nginx/conf.d/default.conf \
		--name my-nginx \
		--network my-tc-net \
		nginx:alpine

kill:
	sudo docker kill my-nginx

exec:
	sudo docker exec -it my-nginx /bin/sh

download:
	curl http://localhost:10086/downloads/testfile --output testfile

clean:
	rm -f testfile


<|start_filename|>tc-traffic-stat/bpf/trafficstat.cc<|end_filename|>
#include "trafficstat.skel.h"

#include <chrono>
#include <cstdio>
#include <thread>


const int ifindex = 7;

int main() {
    auto obj = trafficstat_bpf__open();
    if (!obj) {
        fprintf(stderr, "failed to open BPF object\n");
        return -1;
    }

    obj->bss->ifindex = ifindex;

    auto err = trafficstat_bpf__load(obj);
    if (err) {
        fprintf(stderr, "failed to load BPF object: %d\n", err);
        trafficstat_bpf__destroy(obj);
        return -1;
    }

    err = trafficstat_bpf__attach(obj);
    if (err) {
        fprintf(stderr, "failed to attach BPF object: %d\n", err);
        trafficstat_bpf__destroy(obj);
        return -1;
    }

    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
        printf("traffic in bytes: %lld\n", obj->bss->traffic);
    }
    return 0;
}


<|start_filename|>uretprobe-with-golang-the-wrong-way/tracee/Makefile<|end_filename|>
APP=tracee

build:
	go build -o $(APP)

run:
	./$(APP) 'hello world!'

clean:
	rm -f $(APP)


<|start_filename|>xdp-security-group/sg.bpf.c<|end_filename|>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>

#include "bpf_helpers.h"
#include "bpf_endian.h"

static int is_secure_source(void *data_begin, void *data_end)
{
	struct ethhdr *eth_header = data_begin;

	// ignore
	if ((void *)(eth_header + 1) > data_end) {
		return 1;
	}

	// ignore
	if (eth_header->h_proto != bpf_htons(ETH_P_IP)) {
		return 1;
	}

	struct iphdr *ip_header = (struct iphdr *)(eth_header + 1);

	// ignore
	if ((void *)(ip_header + 1) > data_end) {
		return 1;
	}

	// ignore
	if (ip_header->protocol != IPPROTO_TCP) {
		return 1;
	}

	struct tcphdr *tcp_header = (struct tcphdr *)(ip_header + 1);

	// ignore
	if ((void *)(tcp_header + 1) > data_end) {
		return 1;
	}

	if (tcp_header->dest == bpf_htons(12160)) {
		if (tcp_header->source != bpf_htons(10216)) {
			return 0;	// reject
		} else {
			return 1;	// accept
		}
	} else {
		return 1;
	}
}

SEC("xdp")
int xdp_secure_policy(struct xdp_md *ctx)
{
	void *data = (void *)(__u64)ctx->data;
	void *data_end = (void *)(__u64)ctx->data_end;
	if (is_secure_source(data, data_end)) {
		return XDP_PASS;
	} else {
		return XDP_DROP;
	}
}

char __license[] SEC("license") = "GPL";


<|start_filename|>xdp-helloworld/Makefile<|end_filename|>
BPF_HELPERS_URL=https://raw.githubusercontent.com/torvalds/linux/v5.4/tools/testing/selftests/bpf/bpf_helpers.h
BPF_HELPERS=bpf_helpers.h
DEV_NAME=br-$(shell sudo docker network inspect my-xdp-net -f '{{.Id}}' | cut -c1-12)

build: download
	clang -Wall -target bpf -O2 -g -c drop.c -o drop.o

load:
	sudo ip link set dev $(DEV_NAME) xdp obj drop.o sec xdp verbose

unload:
	sudo ip link set dev $(DEV_NAME) xdp off

download:
	if [ ! -f $(BPF_HELPERS) ]; then curl $(BPF_HELPERS_URL) --output $(BPF_HELPERS); fi

debug:
	clang -Wall -target bpf -g -c drop.c -o debug-drop.o
	llvm-objdump-11 -S --no-show-raw-insn debug-drop.o
	clang -Wall -target bpf -O2 -g -c drop.c -o debug-drop-O2.o
	llvm-objdump-11 -S --no-show-raw-insn debug-drop-O2.o

clean:
	rm -f *.o


<|start_filename|>uretprobe-with-golang-the-wrong-way/tracer/main.go<|end_filename|>
package main

import (
	"os"

	"github.com/iovisor/gobpf/bcc"
)

const bpfProgram = `
#include <uapi/linux/ptrace.h>

const int MAX_LEN = 0xFF;

int hack(struct pt_regs *ctx) {
    u64* sp = (u64*)ctx->sp;

    u64 a = 0;
    bpf_probe_read(&a, sizeof(a), sp + 0);

    char b[MAX_LEN] = {0};
    u64 addr = 0;
    bpf_probe_read(&addr, sizeof(addr), sp + 1);
    u64 size = 0;
    bpf_probe_read(&size, sizeof(size), sp + 2);
    bpf_probe_read_str(&b, ((size & MAX_LEN) + 1) & MAX_LEN, (u64*)addr);

    u64 c = 0;
    bpf_probe_read(&c, sizeof(c), sp + 3);

    bpf_trace_printk("I got it: %x %s %x\n", a, b, c);
    return 0;
}
`

const (
	bpfFuncName = "hack"
)

func main() {
	bpfModule := bcc.NewModule(bpfProgram, []string{})
	uprobeFD, err := bpfModule.LoadUprobe(bpfFuncName)
	if err != nil {
		panic(err)
	}

	hackedBinary := os.Args[1]
	hackedFuncName := os.Args[2]
	err = bpfModule.AttachUretprobe(hackedBinary, hackedFuncName, uprobeFD, -1)
	if err != nil {
		panic(err)
	}

	select {}
}
