반응형

-공식문서-
https://ebpf.io/blog/
https://github.com/lizrice/ebpf-beginners
https://sanjit-bhat.github.io/assets/pdf/ebpf-verifier-range-analysis22.pdf -> verifier 논문
https://www.tcpdump.org/papers/bpf-usenix93.pdf -> user단에서 제일 볼만한 논문이라고 개인적으로 여김
https://www.kerno.io/blog/programming-the-kernel-with-ebpf
https://nakryiko.com/posts/bpf-portability-and-co-re/ -> for compile
https://zplin.me/papers/GREBE.pdf
https://kim-dragon.tistory.com/273 -> 국문은 요분께 ㄹㅇ..
https://man7.org/linux/man-pages/man2/bpf.2.html -> linux kernel manual page
https://www.collabora.com/news-and-blog/blog/2019/04/05/an-ebpf-overview-part-1-introduction/ -> 시리즈글 part 1~5
https://pr0gr4m.github.io/linux/kernel/netfilter/ -> netfilter 국문

-exploitation-
https://thehackernews.com/2022/06/quick-and-simple-bpfdoor-explained.html
https://stdnoerr.github.io/writeup/2022/08/21/eBPF-exploitation-(ft.-D-3CTF-d3bpf).html
https://blog.hexrabbit.io/2021/02/07/ZDI-20-1440-writeup/
https://blog.tofile.dev/2021/08/01/bad-bpf.html
https://jinb-park.github.io/Exploit-Linux-kernel-eBPF-with-side-channel.pdf -> side channel attack
https://www.blackhat.com/docs/eu-16/materials/eu-16-Reshetova-Randomization-Can't-Stop-BPF-JIT-Spray-wp.pdf -> spray attack
https://xz.aliyun.com/t/6212?time__1311=n4%2BxnD0DRDBDy77e0QD%2Fia%2Bw07LtG%3DDgiGYD&alichlgref=https%3A%2F%2Fwww.google.com%2F -> 원본은 wei wu님이었나.. p4nda좌님의 글이었던걸로 기억함

https://a1ex.online/2021/08/15/eBPF%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E7%AC%94%E8%AE%B0/


-ebpf fuzzer-
https://github.com/google/buzzer

-flamegraph-
https://github.com/brendangregg/FlameGraph -> 데이터 시각화

반응형

'ebpf' 카테고리의 다른 글

CO-RE, BTF, and Libbpf  (0) 2024.02.11
The bpf() System Call  (0) 2024.01.25
Anatomy of an eBPF Program  (0) 2024.01.24
eBPF programming  (0) 2024.01.09
Troubleshooting - learning eBPF  (0) 2024.01.01

반응형

Learning-eBPF의 pdf에 기인한 내용(chapter4)이며 개인적으로 공부하며 작성되었기에 틀린 내용이 있다면 말씀해주시면 감사하겠습니다.

 

https://cilium.isovalent.com/hubfs/Learning-eBPF%20-%20Full%20book.pdf

 

본 chapter에서는 system call에 대해 다룬다.

우선적으로 ebpf() systemcall에 대해 살펴보자.

간만에 보는 반가운 녀석...(one-day분석때 징글징글하게 봄)

int bpf(int cmd, union bpf_attr *attr, unsigned int size);

해당 함수는 ebpf map이나  program에 대한 명령을 수행하기 위한 친구이다.

- cmd: 말그대로 수행할 command

eBPF map과program을 조절하기 위한 많은 command들이 있다.

아래의 예시는 기본적으로 사용되는 load, create map, attach programs 등등이다.

 

attr: 말그대로 각종 속성들을 저장하는 곳인데 워낙 포함되는 데이터들이 많기에 kernel code를 통해 확인하는 것을 추천한다.

이제 본격적으로 bpf syscall을 파헤치기 위해 syscall을 tracing하는 strace를 활용하여 보자.

활용될 예시 프로그램은 아래와 같으며 이는 실행될때마다 perf buffer에 message를 보내고, execve() syscall event에 대한 정보를 userspace로 전달한다. chapter2인가...에서 있었던 프로그램과 유사하지만 각 사용자 ID에 대해 서로 다른 message를 구성할 수 있다는 차이점이 있다.

#!/usr/bin/python3  
# -*- coding: utf-8 -*-
from bcc import BPF
import ctypes as ct

program = r"""
struct user_msg_t {
   char message[12];
};

BPF_HASH(config, u32, struct user_msg_t);

BPF_PERF_OUTPUT(output); 

struct data_t {     
   int pid;
   int uid;
   char command[16];
   char message[12];
};

int hello(void *ctx) {
   struct data_t data = {}; 
   struct user_msg_t *p;
   char message[12] = "Hello World";

   data.pid = bpf_get_current_pid_tgid() >> 32;
   data.uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;

   bpf_get_current_comm(&data.command, sizeof(data.command));

   p = config.lookup(&data.uid);
   if (p != 0) {
      bpf_probe_read_kernel(&data.message, sizeof(data.message), p->message);       
   } else {
      bpf_probe_read_kernel(&data.message, sizeof(data.message), message); 
   }

   output.perf_submit(ctx, &data, sizeof(data)); 
 
   return 0;
}
"""

b = BPF(text=program)
syscall = b.get_syscall_fnname("execve")
b.attach_kprobe(event=syscall, fn_name="hello")
b["config"][ct.c_int(0)] = ct.create_string_buffer(b"Hey root!")
b["config"][ct.c_int(501)] = ct.create_string_buffer(b"Hi user 501!")

def print_event(cpu, data, size):
   data = b["output"].event(data)
   print(f"{data.pid} {data.uid} {data.command.decode()} {data.message.decode()}")

b["output"].open_perf_buffer(print_event)
while True:
   b.perf_buffer_poll()

line 7~9: message출력할 배열 선언

line 11: data를 저장할 hash table map(type을 따로 지정하지 않을 시에 default는 u64)

line 32: helper function을 통해 userID를 받아온다. 매칭되는 userID에 따라 출력될 메세지를 결정한다. 

 

상기의 코드를 실행해 보자.

sudo python3 ./hello-buffer-config.py

 

ls와 sudo ls 수행시의 output

 

이후에 strace로 확인

옵션 ref

https://itwiki.kr/w/%EB%A6%AC%EB%88%85%EC%8A%A4_strace

sudo strace -e bpf ./hello-buffer-config.py

output

 

상기의 output을 가지고 분석해보자.

bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_PERF_EVENT_ARRAY, , key_size=4,
value_size=4, max_entries=4, ... map_name="output", ...}, 128) = 4

출력에 사용될 perf buffer map을 생성

-map_type : PERF_EVENT_ARRAY

-name : output

-key / value size : 4

-return value(문장 상에서 제일 마지막에 있는 4) : 4(fd를 의미)  -> userspace에서 output map에 access하기 위해 사용

bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_HASH, key_size=4, value_size=12,
max_entries=10240... map_name="config", ...btf_fd=3,...}, 128) = 5

 

hash table map생성

key : 4byte  -> u32type의 userID담김

value : 12byte -> msg_t의 크기(char[12])

btf_fd : 3 -> kernel에서 사용될 요소

bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_KPROBE, insn_cnt=44,
insns=0xffffa836abe8, license="GPL", ... prog_name="hello", ...
expected_attach_type=BPF_CGROUP_INET_INGRESS, prog_btf_fd=3,...}, 128) = 6

 

prog_type : program type, kprobe에 연결

insn_cnt : instruction count, program의 bytecode 명령어 수

- 바이트코드 명령어는 insns 필드에 지정된 주소의 메모리에 보관

license = "GPL" : GPL-licensed BPF helper functions를 사용할 수 있도록 선언

program name : hello

expected_attatch_type : 해당 혜제에서는 일부 프로그램 유형에서만 활용(설명 미기재), 첫항목이기에 value는 0

prog_btf_fd : 3(fd)

 

만약 해당 프로그램이 verifier에 의해 거부된다면 -1의 value를 가지지만, value가 6이기에 적상적으로 통화되었음을 알 수 있으며 각 fd에 대한 정리는 아래와 같다.

 

bpf(BPF_MAP_UPDATE_ELEM, {map_fd=5, key=0xffffa7842490, value=0xffffa7a2b410,
flags=BPF_ANY}, 128) = 0

 

BPF_MAP_UPDATE_ELEM : map의 key-value쌍을 업데이트

BPF_ANY flag : map내에 key가 존재하지 않는 경우, 생성되어야함을 알리는 flag

map_fd : 어떤 map이 현재 사용되는지 식별

- 이때, key / value는 모두 pointer이므로, strace에 의해 수치화된 값이 나오는 것은 아니지만, bpftool을 활용하여 아래와 같이 요소들의 내용을 볼 수 있다.

#bpftool map dump name config output

[{
 "key": 0,
 "value": {
 "message": "Hey root!"
 }
 },{
 "key": 501,
 "value": {
 "message": "Hi user 501!"
 }
 }
]

해당 요소들을 가져올 수 있는 이유는 BTF 정보 내에 정의된 것들을 사용하기 때문이다.

 

● BPF Program and Map References

- pinning

이미 chapter 3에서 나왔던 부분이다.

pinned object는 실제로 disk에 영구적으로 있는 파일이 아니다. 일반적인 file system과 같이 동작하는 pesudo filesystem으로써 존재한다. 그러나 메모리에 보관되기에 재부팅 시에 유지되지 않는다.

-about pseudo file system-

https://superuser.com/questions/1198292/what-is-a-pseudo-file-system-in-linux

 

pinning되지 않은 채로 ebpf program이 load되는 것을 허용한다면, bpftool이 종료될 때 fd가 해제되고 reference가 0이 될시에 program이 삭제될 것이다. 허나 pinng된 ebpf program의 경우 command가 수행된 이후에도 지속될 것이다. 

reference counter는 trigger되는 hook이 연결될 때에도 증가한다. count는 eBPF program type에 의존적이며 tracing과 연관있고(chapter 7에서 다뤄질 예정) 항상 user space process와 연결된다. 이러한 경우, process가 종료되면 kernel의 참조 횟수가 감소한다. 

 

netwrok stack이나 cgroup과 함께 부착된 program은 어떠한 user space process와 연관있지 않기에 load가 종료된 이후에도 유지된다. 이전에 봤던 XDP program에 대한 예시와 같다.

(아마 이전 챕터에서 실습 때, 따로 unload해주지 않으면 유지되어 있는 모습을 떠올리면 될 듯하다.)

ip link set dev eth0 xdp obj hello.bpf.o sec xdp

 

ip명령어가 수행된 이후 pinned location에 대한 정의가 없지만, bpftool은 XDP program이 kernel에 load된 상태를 보여준다.

$ bpftool prog list
…
1255: xdp name hello tag 9d0e949f89f1a82c gpl
 loaded_at 2022-11-01T19:21:14+0000 uid 0
 xlated 48B jited 108B memlock 4096B map_ids 612

reference count는 0이 아니며, 이는 XDP hook이 ip link명령어가 수행된 이후에 지속적으로 부착되어 있기 때문이다.

eBPF map역시 reference count를 가지며 0이 될 시에 초기화 된다. map역시 사용하는 각 eBPF program의 counter를 증가시켜 user space의 program이 map을 가지고 있게 해준다.

map은 file system에 고정될 수도 있으며, user space program은 map 경로를 알면 map에 접근할 수 있다.

 

위와 같이 fd와 reference counter를 통해 참조하게 할 수도 있지만 다른 방법으로는 eBPF link도 있다.

 

● BPF link

BPF link는 eBPF program과 event같의 추상화된 layer를 제공한다. BPF link는 자체적으로 file system에 고정되어 program에 대해 추가적인 참조를 생성할 수 있다. 이는 kernel에 load한 user space process가 종료되어도 program이 load된 상태로 남아 있을 수 있다는 의미라고 한다.

user space loader program의 fd가 해제되어도 program에 대한 reference count는 감소하지만, BPF link에 의해 0이 되지는 않는다. 

 

이후의 내용들은 너무 deep해서 현시점의 나에겐 이해하기에 너무 어려워 생략한다.

대략적으로 다루는 내용은 perf buffers, ring buffers, kprobes, and map iterations에 관련된 syscall에 대해 자세히 본다.

 

이상 chapter 4

반응형

'ebpf' 카테고리의 다른 글

ebpf 공부용 링크들 다시 정리  (0) 2024.06.19
CO-RE, BTF, and Libbpf  (0) 2024.02.11
Anatomy of an eBPF Program  (0) 2024.01.24
eBPF programming  (0) 2024.01.09
Troubleshooting - learning eBPF  (0) 2024.01.01
반응형

Learning-eBPF의 pdf에 기인한 내용(chapter3)이며 개인적으로 공부하며 작성되었기에 틀린 내용이 있다면 말씀해주시면 감사하겠습니다.

 

https://cilium.isovalent.com/hubfs/Learning-eBPF%20-%20Full%20book.pdf

1. compile with clang

hello.bpf.o: %.o: %.c	
 clang \	
 -target bpf \	
 -I/usr/include/$(shell uname -m)-linux-gnu \	
 -g \	
 -O2 -c $< -o $@

 

line1: .o파일을 .c파일로부터 만듦(% : 와일드 카드)

line2: LLVM 컴파일러인 Clang을 사용하여 소스 코드를 컴파일

line3: Clang이 BPF 목표 아키텍처를 컴파일하도록 지정하는 옵션

line4: 헤더 파일을 조회할 디렉터리 지정

line5: 디버그 정보를 포함하여 컴파일

line6: O2 - 최적화 레벨,   $< - 현재 목표의 종속 항목 중 첫번째 (해당 코드에서는 .c파일) , $@ - 현재 목표 (해당 코드에서는 .c파일)  => .c를 compile하여 .o파일로 생성

https://hyeonbell.tistory.com/174

 

2. llvm-objdump -S hello.bpf.o

- eBPF IR파악을 위한 dump

https://github.com/chubin/cheat.sheets/blob/master/sheets/objdump

 

result

hello.bpf.o:    file format elf64-bpf

Disassembly of section xdp:

0000000000000000 <hello>:
;     bpf_printk("Hello World %d", counter);
       0:       18 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r6 = 0 ll
       2:       61 63 00 00 00 00 00 00 r3 = *(u32 *)(r6 + 0)
       3:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
       5:       b7 02 00 00 0f 00 00 00 r2 = 15
       6:       85 00 00 00 06 00 00 00 call 6
;     counter++; 
       7:       61 61 00 00 00 00 00 00 r1 = *(u32 *)(r6 + 0)
       8:       07 01 00 00 01 00 00 00 r1 += 1
       9:       63 16 00 00 00 00 00 00 *(u32 *)(r6 + 0) = r1
;     return XDP_PASS;
      10:       b7 00 00 00 02 00 00 00 r0 = 2
      11:       95 00 00 00 00 00 00 00 exit

IR opcode에 대한 reference

https://github.com/iovisor/bpf-docs/blob/master/eBPF.md

 

3. load program with "bpftool" (require root previlige)

sudo bpftool prog load hello.bpf.o /sys/fs/bpf/hello

 

how to check

 ls /sys/fs/bpf

 

4. list bpf programs

sudo bpftool prog list

 

get output with prettified JSON

sudo bpftool prog show id 101 --pretty

output

{
    "id": 101,
    "type": "xdp",
    "name": "hello",
    "tag": "d35b94b4c0c10efb",
    "gpl_compatible": true,
    "loaded_at": 1706073152,
    "uid": 0,
    "bytes_xlated": 96,
    "jited": true,
    "bytes_jited": 64,
    "bytes_memlock": 4096,
    "map_ids": [4,5
    ],
    "btf_id": 159
}

-program ID: 101

-xdp event를 통한 attach

-program name: hello

-identifier

-GPL compatible license
-program이 로딩된 시점의 timestamp - 부팅이후의 시점부터

-userID 0 (root) 로 load

-eBPF bytecode로 변환된 프로그램의 크기

-JIT compiled 및 컴파일 이후 machine code의 크기

-BPF map ID들

- -g flag로 컴파일 했을시 포함되는 정보이며, 해당 BTF id 는 단일 블록의 BTF 정보를 포함

 

program ID는 load와 unload를 할때마다 바뀌지만 tag는 유지된다 -> tag가 고유한 것은 아니다.

같은 name으로 program을 생성할 수 있으며 여러 인스턴스를 가질 수 있지만, ID와 pinned path는 고유하다. 

그리고 아래의 instruction들을 통해 bpf program의 정보를 파악할 수 있다. (네가지 모두 동일한 output)

• bpftool prog show id 540
• bpftool prog show name hello
• bpftool prog show tag d35b94b4c0c10efb
• bpftool prog show pinned /sys/fs/bpf/hello

 

Translated Byte code확인

sudo bpftool prog dump xlated name hello

output

int hello(struct xdp_md * ctx):
; bpf_printk("Hello World %d", counter);
   0: (18) r6 = map[id:4][0]+0
   2: (61) r3 = *(u32 *)(r6 +0)
   3: (18) r1 = map[id:5][0]+0
   5: (b7) r2 = 15
   6: (85) call bpf_trace_printk#-66752
; counter++; 
   7: (61) r1 = *(u32 *)(r6 +0)
   8: (07) r1 += 1
   9: (63) *(u32 *)(r6 +0) = r1
; return XDP_PASS;
  10: (b7) r0 = 2
  11: (95) exit

상기의 output은 verifier를 통과한 이후의 bytecode이다.

 

해당 bytecode는 저수준언어와 유사하게 생겼지만 machine code 급은 아니다(?) 그 사이 어딘가 애매한 상태이다.

eBPF는 JIT compiler를 통해 eBPF bytecode를 machine code로 변환한다.

-> 퍼포먼스를 위해서!

 

JITed code를 assembly어의 형태로!

sudo bpftool prog dump jited name hello

output

int hello(struct xdp_md * ctx):
bpf_prog_d35b94b4c0c10efb_hello:
; bpf_printk("Hello World %d", counter);
   0:   nopl    (%rax,%rax)
   5:   nop
   7:   pushq   %rbp
   8:   movq    %rsp, %rbp
   b:   pushq   %rbx
   c:   movabsq $-99790339293184, %rbx
  16:   movl    (%rbx), %edx
  19:   movabsq $-124354625743600, %rdi
  23:   movl    $15, %esi
  28:   callq   0xffffffffce103260
; counter++; 
  2d:   movl    (%rbx), %edi
  30:   addq    $1, %rdi
  34:   movl    %edi, (%rbx)
; return XDP_PASS;
  37:   movl    $2, %eax
  3c:   popq    %rbx
  3d:   leave
  3e:   retq
  3f:   int3

 

ps. JIT compilation을 활용하기 위해서는 CONFIG_BPF_JIT옵션이 켜져있는 kernel이어야 한다.

상기의 IR은 내가 보던 pdf와 달랐는데, 느낌상으로는 내 pc와 예제의 환경이 상이하여 발생한 차이인듯하다.

 

이제 program이 load된 것을 보았으니 event와 attach하고 trigger해보자.

attach할 때, 유의할 부분이 type이다.

위에서 우린 xdp event에 attach하겠다고 하였으므로 bpftool을 사용하여 eBPF 프로그램에 xdp event를 attach해보자.

sudo bpftool net attach xdp id 101 dev enp5s0

뒷쪽의 id와 device는 적절하게 맞추어 주자!

현재 본인의 경우..

ifconfig로 확인하자~

cf. lo는 loopback interface이다. 해당 interface는 traffic을 내 machine에 보내기 위해 사용

enp5s0

-ref-

https://unix.stackexchange.com/questions/134483/why-is-my-ethernet-interface-called-enp0s10-instead-of-eth0

https://blog.naver.com/snrndi121/220999725150

이후에 network interface가 추가된 것을 볼 수 있다.

sudo bpftool net list

output( enp5s0 interface가 attach된 상태)

xdp:
enp5s0(2) generic id 101

tc:

flow_dissector:

netfilter:

 

ip link명령어로도 확인가능

현 상태에서는 network packet 수신에 대해 output을 매번 trace utput으로 저장해야 되며 아래의 명령을 통해 확인가능하다.

cat /sys/kernel/debug/tracing/trace_pipe

요로코롬

아래의 명령어로도 tracelog를 확인할 수 있다.

sudo bpftool prog tracelog

kernel에 load된 map들을 보고싶다면!

그리고 생성된 program에 대해 section도 관찰할 수 있다.

sudo bpftool map dump name hello.bss

output(.bss section(초기화되지 않은 전역변수)의 전역변수를 볼 수 있다.)

[{
        "value": {
            ".bss": [{
                    "counter": 124555
                }
            ]
        }
    }
]

.rodata section

sudo bpftool map dump name hello.rodata

output

[{
        "value": {
            ".rodata": [{
                    "hello.____fmt": "Hello World %d"
                }
            ]
        }
    }
]

 

attach했던 program을 해제하고 싶다면!

sudo bpftool net detach xdp dev enp5s0

이후에 net list를 입력해보면 비어있는 것을 확인할 수 있다.

다음으로 unload하고 싶다면!

sudo rm /sys/fs/bpf/hello
sudo bpftool prog show name hello

output이 아무것도 없다면 된다. 더이상 load된 program이 없기 때문~

 

마저 진행해보자!

 

tail call에 대해서부터 시작이다.

간단한 예제코드를 먼저 보자.

#include <linux/bpf.h>
#include <bpf_helpers.h>

static __attribute((noinline)) int get_opcode(struct bpf_raw_tracepoint_args *ctx) {
    return ctx->args[1];
}

SEC("raw_tp/")
int hello(struct bpf_raw_tracepoint_args *ctx) {
    int opcode = get_opcode(ctx);
    bpf_printk("Syscall: %d", opcode);
    return 0;
}

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

- opcode를 추출하는 간단한 함수인데 compiler에서 저 함수만을 지속적으로 처리할 경우, 인라인 처리 하는 것을 방지하기 위해 noinline 속성으로 정의한다.

 

- opcode를 추출하여 printk로 출력

 

이제 이전 글에서 수행했던 것 처럼 파일을 load해보자.

sudo bpftool prog load hello-func.bpf.o /sys/fs/bpf/hello
sudo bpftool prog list name hello

output

166: raw_tracepoint  name hello  tag 3d9eb0c23d4ab186  gpl
        loaded_at 2024-01-25T08:36:33+0900  uid 0
        xlated 80B  jited 62B  memlock 4096B  map_ids 37
        btf_id 207

 

이제 get_opcode() 함수를 보기 위해 eBPF 바이트코드 살펴보자.

sudo bpftool prog dump xlated name hello

output

int hello(struct bpf_raw_tracepoint_args * ctx):
; int opcode = get_opcode(ctx);
   0: (85) call pc+7#bpf_prog_cbacc90865b1b9a5_get_opcode
; bpf_printk("Syscall: %d", opcode);
   1: (18) r1 = map[id:37][0]+0
   3: (b7) r2 = 12
   4: (bf) r3 = r0
   5: (85) call bpf_trace_printk#-66752
; return 0;
   6: (b7) r0 = 0
   7: (95) exit
int get_opcode(struct bpf_raw_tracepoint_args * ctx):
; return ctx->args[1];
   8: (79) r0 = *(u64 *)(r1 +8)
; return ctx->args[1];
   9: (95) exit

- hello()이 get_opcode()를 호출하며 eBPF IR기준으로 offset 0은 0x85이며 이는 "Function call"을 의미한다.

이후에, offset 1에 있는 다음 명령어를 실행하는 대신, 7개의 IR을 건너뛰어(pc+7에 의해) offset 8을 향하게 된다.

 

- 해당 위치에 get_opcode()이 존재한다.

 

하지만 위와 같은 tail call은 stack size가 512byte로 제한적인 eBPF 에서는 많이 활용되기 어렵다.

 

이상으로 chapter3의 내용을 마친다.

 

반응형

'ebpf' 카테고리의 다른 글

CO-RE, BTF, and Libbpf  (0) 2024.02.11
The bpf() System Call  (0) 2024.01.25
eBPF programming  (0) 2024.01.09
Troubleshooting - learning eBPF  (0) 2024.01.01
JIT for BPF  (0) 2023.09.21

반응형

https://cilium.isovalent.com/hubfs/Learning-eBPF%20-%20Full%20book.pdf


상기의 내용을 기반으로 아래의 링크에서 학습하던 와중 생긴 에러에 대한 처리

https://github.com/lizrice/learning-ebpf

 

GitHub - lizrice/learning-ebpf: Learning eBPF, published by O'Reilly - out now! Here's where you'll find a VM config for the exa

Learning eBPF, published by O'Reilly - out now! Here's where you'll find a VM config for the examples, and more - GitHub - lizrice/learning-ebpf: Learning eBPF, published by O'Reill...

github.com

 

처음에 계속 libbpf/src를 시작할떼 make build를 수행해 주었으나 path를 잡지 못해 에러를 처리하지 못하고 있었다.

그렇기에 기본으로 주어지는 makefile을 뜯어보니 참조하는 디렉터리가 달랐기에 수정하였다.

makefile의 -I플래그로 -I/home/username/bpf/learning-ebpf/libbpf/src \ 추가

 -I 플래그 : 해당 디렉터리를 포함하도록 지정

수정된 makefile

TARGETS = hello hello-func

all: $(TARGETS)
.PHONY: all

$(TARGETS): %: %.bpf.o

%.bpf.o: %.bpf.c
        clang \
            -target bpf \
                -I/home/hackin/bpf/learning-ebpf/libbpf/src \
                -I/usr/include/$(shell uname -m)-linux-gnu \
                -g \
            -O2 -o $@ -c $<

clean: 
        - rm *.bpf.o
        - rm -f /sys/fs/bpf/hello 
        - rm -f /sys/fs/bpf/hello-func

또한, 헤더파일들이 위치한 디렉터리는 src디렉터리 이기에 c code들도 모두 수정해 주었다.

각 소스코드의 <bpf/bpf_helper.h> -> <bpf_helper.h> 로 변경

이제 정상적으로 생성된 것을 확인할 수 있다.

 

그리고 정상적으로 이제 덤프가 떠지는 것까지 확인!

 

추후에 상기에 언급해뒀던 pdf 내용들도 좀 정리해야겠다....

 

 

옛날에는 이걸 못해서 학습이 막혔었는데.. 이걸 왜 못했을까...

반응형

'ebpf' 카테고리의 다른 글

Anatomy of an eBPF Program  (0) 2024.01.24
eBPF programming  (0) 2024.01.09
JIT for BPF  (0) 2023.09.21
JIT(Just In Time) Compiler - Verifier - SAT/SMT solver  (0) 2023.09.17
Buzzer(eBPF fuzzer) build  (0) 2023.08.11
반응형

내가 봐야할 문서들 정리..!

필요하신 분도 보면 좋을 듯

 

https://www.usenix.org/sites/default/files/conference/protected-files/osdi20_slides_nelson.pdf

https://www.usenix.org/system/files/osdi20-nelson.pdf

https://cdn.open-nfp.org/media/documents/demystify-ebpf-jit-compiler.pdf

 

최근에 접한 eBPF ppt

https://docs.google.com/presentation/d/1AcB4x7JCWET0ysDr0gsX-EIdQSTyBtmi6OAW7bE0jm0/edit#slide=id.g70356bf6e4_0_1128

 

여태 본 것들중 제일 정리가 잘 된 글이라고 느껴진다.

https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/

 

 

겸사겸사 늘 시도해보지만 맘대로 못다루는 IO Visor project의 블로그

https://www.iovisor.org/resources/blog

 

이전에 올린적 있는 사이트 인것 같으나 한번 더  올리기(낭낭함)

https://www.collabora.com/news-and-blog/blog/2019/04/15/an-ebpf-overview-part-2-machine-and-bytecode/

반응형

'ebpf' 카테고리의 다른 글

eBPF programming  (0) 2024.01.09
Troubleshooting - learning eBPF  (0) 2024.01.01
JIT(Just In Time) Compiler - Verifier - SAT/SMT solver  (0) 2023.09.17
Buzzer(eBPF fuzzer) build  (0) 2023.08.11
eBPF references - Blackhat  (0) 2023.08.06
반응형

Kernel 내에서의 JIT compiler는 eBPF code를 machine code로 변환시켜주는 역할을 한다.

이는 eBPF의 장점 중 하나인 kernel을 새로 build하지 않고도 kernel code를 수행하게 하도록 도와주며, performance를 향상시킨다.

 

-Compile-

 

https://www.usenix.org/sites/default/files/conference/protected-files/osdi20_slides_nelson.pdf

상기의 사진은 BPF program의 compile과정을 설명한다.

1. BPF program을 kernel내에 주입

2. BPF safety checker(verifier.c 수행)가 해당 code안전한지 여부(ex. infinite loop)를 확인

3. JIT compiler가 machine code로 변환

 

-Runtime-

https://www.usenix.org/sites/default/files/conference/protected-files/osdi20_slides_nelson.pdf

runtime시, 해당 code는 kernel function처럼 동작하며,

return value, memory accesses, function calls를 통하여 kernel과 소통한다.

 

아래의 글은 JIT관련하여 https://sanjit-bhat.github.io/assets/pdf/ebpf-verifier-range-analysis22.pdf의 Jitterbug에 관해 알아보다가 산으로 왔다... JIT관련 정리는 추후에 다시..

 

하지만, 꼭 알아줬으면 하는 내용이다.

아래의 내용은 BPF의 verifier에서 boundary check에 연관되는 개념이기도 하다.(아직 위의 pdf다 못보고 이 글을 씀...)

=============================

이해를 위한 기본 식

SAT(boolean SATisfiability problem)

: 어떠한 논리식이 참인 결과를 찾는 것

satisfiable하다 == 어떠한 논리식을 참으로 만드는 assignment가 1개 이상 존재한다.(assignment: 값 대입/할당)

ex.

 

unsatisfiable하다 == 어떠한 논리식을 참으로 만드는 assignment가 1개 이상 존재하지 않는다.

ex. x and ~x가 참을 만족하는 식이 있을 수 없다.(하단의 사진 참고)

 

SAT solver: SAT문제를 풀어주는 프로그램. 단, 모든 형태의 input을 허용하지 않는다.

input으로 CNF formular를 만족하여 들어온 것들만 풀어준다.

=================================

CNF(Conjunctive Normal From)란,

: clause안에 연산자가 무조건 or만 있는 것, clause를 묶는 것은 무조건 and

ex.

DNF(Disjunctive Normal Form)은 CNF의 역

ex.

cf. Conjuction == or

==================================

output은 그 논리식이 satisfiable하다면, satisfiable과 assignment하나를 같이 출력한다.(여러개가 있더라도 랜덤한 하나의 assignment를 출력한다)

만약, 논리식이 unsatisfiable하다면, unsatisfiable을 출력한다.

ex. 

output

ref. https://microsoft.github.io/z3guide/docs/logic/basiccommands/ 

 

SMT(Satisfiability Modulo Theory)

: SAT과 theory의 결합

theory의 대표적 예시 Linear Real Arithmetic

theory 의 ex.

p = x + y < 10

q = x * 3y - 10 <= 30

r = y + 7 <= 15

 

 

SMT solver는 상기의 식을 SAT처럼 참 거짓을 판별한다. (software 검증에도 사용된다)

 

SMT solver로 문제를 풀 때, 내부적인 동작

1. 각각의 부등식을 SAT처럼 p, q, r로 변환

2. DPLL알고리즘으로 이를 푼다.

2-1. if unsatisfiable이면, unsatisfiable하다고 출력

3. satisfiable하다면, 그 식이 theory의 관점에서도 satisfiable한지 확인한다.(아래의 경우와 같은 예시로 인하여)

부등식일 경우 만족하는 값 UNSAT, 아닐 경우는 SAT

3-1. if satisfiable하다면, satisfiable하다고 출력

3-2. unsatisfiable하다면, DPLL알고리즘을 다시 수행하는데, unsatisfiable한 경우의 수를 제외하도록 수식을 추가한 후 수행한다.

 

-DPLL-

http://rosaec.snu.ac.kr/meet/file/20110626o.pdf

 

-ref-

chapter 4를 메인, sub로는 chapter 6를 참고

https://arxiv.org/abs/2109.10317

반응형

'ebpf' 카테고리의 다른 글

Troubleshooting - learning eBPF  (0) 2024.01.01
JIT for BPF  (0) 2023.09.21
Buzzer(eBPF fuzzer) build  (0) 2023.08.11
eBPF references - Blackhat  (0) 2023.08.06
O’Reilly Report What is eBPF? - tutorial 4  (0) 2023.07.21

+ Recent posts