"
18 | for f in "${files[@]}"; do
19 | rest=$(( i % 3 ))
20 | if [ "$rest" -eq "0" ]; then
21 | if [ ! "$i" -eq "0" ]; then
22 | echo ""
23 | fi
24 | echo "
"
30 | fi
31 | fi
32 | i=$(( i + 1 ))
33 | done
34 | echo "
"
35 | fi
--------------------------------------------------------------------------------
/input/2_0_scap_bpf_load_initial_setup.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | scap_bpf_load()->>set_runtime_params(): call
9 | set_runtime_params()->>kernel: setrlimit(INFINITY)
10 | kernel-->>set_runtime_params(): error status
11 | set_runtime_params()->>kernel: /proc/sys/net/core/bpf_jit_enable = 1
12 | kernel-->>set_runtime_params(): error status
13 | set_runtime_params()->>kernel: /proc/sys/net/core/bpf_jit_harden = 0
14 | kernel-->>set_runtime_params(): error status
15 | set_runtime_params()->>kernel: /proc/sys/net/core/bpf_jit_kallsyms = 1
16 | kernel-->>set_runtime_params(): error status
17 | set_runtime_params()-->>scap_bpf_load(): error status
18 | Note over scap_bpf_load(): ...
19 | ```
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/input/3_0_falco_event_loop.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | loop always
9 | falco->>libsinsp: next(&ev)
10 | libsinsp->>libsinsp: pop container events, if any
11 | libsinsp->>libscap: scap_next()
12 | libscap-->>libsinsp: event + error status
13 | libsinsp->>libsinsp: update_k8s_state()
14 | libsinsp-->>falco: error status
15 |
16 | Note right of falco: As the inspector has no filter at its level, all events are returned
17 | Note right of falco: The Falco engine will match the current event against the current set of rules
18 | falco->>falco_engine: process_sinsp_event(ev)
19 | falco_engine-->>falco: rule_result "res"
20 |
21 | opt res
22 | Note right of falco: When a match is found, pass the event to the Falco outputs
23 | falco->>falco_outputs: handle_event(res)
24 | end
25 | end
26 | ```
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/input/1_1_scap_open_internals.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | Note over scap_open(): case SCAP_MODE_LIVE
9 | alt userspace
10 | scap_open()->>scap_open_udig_int(): call
11 | scap_open_udig_int()-->>scap_open(): scap_t
12 | else
13 | scap_open()->>scap_open_live_int(): call
14 | scap_open_live_int()->>scap_open_live_int(): bpf_probe = getenv("FALCO_BPF_PROBE")
15 | alt FALCO_BPF_PROBE set
16 | Note over scap_open_live_int(): bpf = true
17 | opt FALCO_BPF_PROBE empty
18 | scap_open_live_int()->>scap_open_live_int(): bpf_probe = $HOME/.falco/falco-bpf.o
19 | Note over scap_open_live_int(): fallback to standard path
20 | end
21 | else
22 | Note over scap_open_live_int(): bpf = false
23 | end
24 | Note over scap_open_live_int(): ...
25 | end
26 | scap_open_live_int()-->>scap_open(): scap_t
27 | ```
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/input/4_2_falco_grpc_server_thread_processing.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | Note over grpc_server: thread_process()
9 | loop cq->Next(&tag, &ok)
10 | Note over grpc_server: tag = this (scope of the current context)
11 | Note over grpc_server: read from the cq, blocking until an event is available or the queue is shutting down
12 | grpc_server->>request_context_base: cast tag
13 | request_context_base-->>grpc_server: ctx
14 | opt !ok
15 | opt ctx->state != request_context_base/REQUEST
16 | Note over grpc_server: server completion queue failing to read for tag = this
17 | grpc_server->>request_context_base: end(this, error = true)
18 | end
19 | Note over grpc_server: go to next iteration
20 | end
21 | alt ctx->state == request_context_base/{REQUEST,WRITE}
22 | Note over grpc_server: process event, stop current iteration
23 | grpc_server->>request_context_base: process(this)
24 | else ctx->state == request_context_base/FINISH
25 | Note over grpc_server: completion, stop current iteration
26 | grpc_server->>request_context_base: end(this, error = false)
27 | end
28 | end
29 | ```
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/input/1_2_scap_open_live_int.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | Note over scap_open_live_int(): !userspace
9 | scap_open_live_int()->>sysconf(): _SC_NPROCESSORS_ONLN, _SC_PHYS_PAGES, _SC_PAGESIZE
10 | scap_open_live_int()->>scap_create_iflist(): create interface list
11 | scap_create_iflist()-->>scap_open_live_int(): error status
12 | scap_open_live_int()->>scap_create_userlist(): create user list
13 | scap_create_userlist()-->>scap_open_live_int(): error status
14 | alt bpf == true
15 | scap_open_live_int()->>scap_bpf_load(): load eBPF probe
16 | Note over scap_bpf_load(): REF: SCAP BPF LOAD
17 | scap_bpf_load()-->>scap_open_live_int(): error status
18 | else kernel module
19 | Note over scap_open_live_int(): allocate the ring buffer
20 | Note over scap_open_live_int(): open the devices
21 | Note over scap_open_live_int(): map the ring buffer
22 | end
23 | scap_open_live_int()->>scap_proc_scan_proc_dir(): create process list
24 | scap_proc_scan_proc_dir()-->>scap_open_live_int(): error status
25 | scap_open_live_int()->>scap_start_capture(): start the capture
26 | scap_start_capture()-->>scap_open_live_int(): error status
27 | ```
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/.github/workflows/compile_mermaid.yaml:
--------------------------------------------------------------------------------
1 | name: "Compile mermaid"
2 |
3 | on:
4 | push:
5 | paths:
6 | - "**/*.mermaid"
7 | - "**/*.mmd"
8 | - "**/*.md"
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | with:
16 | fetch-depth: 2
17 | - name: Get input files with changes
18 | id: getfile
19 | run: |
20 | echo "::set-output name=files::$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} | grep -e 'input/.*\.md$' -e 'input/.*\.*mmd$' -e 'input/.*\.mermaid$' | xargs)"
21 | - name: Output input files with changes
22 | run: |
23 | echo ${{ steps.getfile.outputs.files }}
24 | - name: Compile mermaid files
25 | uses: neenjaw/compile-mermaid-markdown-action@master
26 | if: startsWith(steps.getfile.outputs.files, 'input/')
27 | with:
28 | files: ${{ steps.getfile.outputs.files }}
29 | output: "output"
30 | env:
31 | HIDE_CODEBLOCKS: 1
32 | ABSOLUTE_IMAGE_LINKS: 1
33 | - name: Commit
34 | run: |
35 | if [[ $(git diff --exit-code) ]]; then
36 | git config --local user.email "leodidonato@gmail.com"
37 | git config --local user.name "Leonardo Di Donato"
38 | git add -A && git commit -m "new: diagrams"
39 | fi
40 | - name: Push
41 | uses: ad-m/github-push-action@master
42 | with:
43 | github_token: ${{ secrets.GITHUB_TOKEN }}
44 |
--------------------------------------------------------------------------------
/input/4_0_falco_grpc_server_on.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | Note over falco: inspector (libsinsp), engine, outputs init ...
9 | falco->>falco: look for Falco config file or fallback to defaults
10 | falco->>configurator: init()
11 | Note over configurator: read configs from falco.yaml
12 | opt threadiness == 0
13 | configurator->>configurator: threadiness = hardware_concurrency()
14 | end
15 | configurator-->>falco: config values (enabled, bind_address, threadiness, private_key, cert_chain, root_certs, outputs_enabled)
16 | opt gRPC outputs enabled
17 | falco->>falco_outputs: add gRPC output to the list of output methods
18 | end
19 | opt gRPC enabled
20 | falco->>grpc_server: init(bind_address, threadiness, ...)
21 | grpc_server->>grpc_server: setup dispatching of gRPC logs
22 | grpc_server->>grpc/ServerBuilder: addListeningPort(bind_address, server_credentials)
23 | falco->>grpc_server: new thread run()
24 | Note over grpc_server: ... THREADING MODEL ...
25 | loop is_running
26 | Note over grpc_server: this_thread::sleep_for(...)
27 | end
28 | grpc_server->>grpc_server: stop()
29 | Note over grpc_server: shutdown gRPC server
30 | Note over grpc_server: shutdown completion queue
31 | Note over grpc_server: wait threads to complete
32 | Note over grpc_server: drain all the remaining gRPC events
33 | end
34 | ```
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/input/2_4_scap_bpf_load_events_per_cpu.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | scap_bpf_load()->>scap_bpf_load(): nOnline = 0
9 | loop i := range nCPUs
10 | scap_bpf_load()->>scap_bpf_load(): attr = new perf_event_attr
11 | opt i > 0
12 | scap_bpf_load()->>scap_bpf_load(): online = /sys/devices/system/cpu/cpu/online
13 | opt ! online
14 | Note over scap_bpf_load(): jump to the next CPU
15 | end
16 | end
17 | opt nOnline++ > nDevices
18 | Note over scap_bpf_load(): set error status and return it
19 | end
20 | scap_bpf_load()->>kernel: syscall(__NR_perf_event_open, attr , pid = -1, cpu = , group_fd = -1, flags = 0)
21 | kernel-->>scap_bpf_load(): pmu_fd
22 | scap_bpf_load()->>kernel: syscall(BPF_MAP_UPDATE, ...)
23 | Note right of scap_bpf_load(): store pmu_fd at the i-th position of the SYSDIG_PERF_MAP map
24 | kernel-->>scap_bpf_load(): error status
25 | scap_bpf_load()->>kernel: ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0)
26 | kernel-->>scap_bpf_load(): error status
27 | scap_bpf_load()->>perf_event_mmap(): map the ring buffer
28 | perf_event_mmap()-->>scap_bpf_load(): error status
29 | scap_bpf_load()->>scap_bpf_load(): nOnline++
30 | end
31 | opt nOnline != nDevices
32 | Note over scap_bpf_load(): set error status and return it
33 | end
34 | Note over scap_bpf_load(): ...
35 | ```
36 |
37 |
38 |
39 |
40 | TODO:
41 |
42 | - Show `perf_event_attr`
43 | - Sho `perf_event_open` (set up performance monitoring for one event, read man)
44 | - pid -1 & cpu >= 0 measures all processes/threads on the specified CPU (`CAP_SYS_ADMIN` capability required)
45 | - `ioctl` to enable events
46 |
--------------------------------------------------------------------------------
/input/2_2_scap_bpf_load_populate_routing_syscall_table.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | scap_bpf_load()->>populate_syscall_routing_table_map(): call
9 | loop i := 0, i < SYSCALL_TABLE_SIZE, i++
10 | populate_syscall_routing_table_map()->>syscall_table: g_syscall_code_routing_table[i]
11 | syscall_table-->>populate_syscall_routing_table_map(): x = system-independent syscall code
12 | populate_syscall_routing_table_map()->>eBPF VM: sys_bpf(BPF_MAP_UPDATE_ELEM, ...)
13 | Note right of populate_syscall_routing_table_map(): store x at the i-th position of the SYSDIG_SYSCALL_CODE_ROUTING_TABLE map
14 | eBPF VM-->>populate_syscall_routing_table_map(): error status
15 | end
16 | populate_syscall_routing_table_map()-->>scap_bpf_load(): error status
17 | scap_bpf_load()->>populate_syscall_table_map(): call
18 | loop i := 0, i < SYSCALL_TABLE_SIZE, i++
19 | populate_syscall_table_map()->>syscall_table: g_syscall_table[i]
20 | Note right of syscall_table: eg., x = {UF_USED | UF_NEVER_DROP, PPME_SYSCALL_OPEN_E, PPME_SYSCALL_OPEN_X}
21 | syscall_table-->>populate_syscall_table_map(): x = {syscall_flags values + ..., ppm_event_type value}
22 | populate_syscall_table_map()->>eBPF VM: sys_bpf(BPF_MAP_UPDATE_ELEM, ...)
23 | Note left of populate_syscall_table_map(): store x at the i-th position of the SYSDIG_SYSCALL_TABLE map
24 | eBPF VM-->>populate_syscall_table_map(): error status
25 | end
26 | populate_syscall_table_map()-->>scap_bpf_load(): error status
27 | Note over scap_bpf_load(): ...
28 | ```
29 |
30 |
31 |
32 |
33 | TODO:
34 |
35 | - What type of eBPF maps SYSDIG_SYSCALL_CODE_ROUTING_TABLE and SYSDIG_SYSCALL_TABLE are?
36 | - Show syscall_flags enum
37 | - Show ppm_event_type enum (start, exit)
38 |
39 |
--------------------------------------------------------------------------------
/input/4_3_falco_grpc_server_bidirectional_handling.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | alt state == request_context_base/REQUEST
9 | request_bidi_context{outputs}/process(...)->>bidi_context: bidi_ctx = new(srv_ctx)
10 | request_bidi_context{outputs}/process(...)->>request_bidi_context{outputs}/process(...): state = request_context_base/WRITE
11 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Read(req, this)
12 | else state == request_context_base/WRITE
13 | request_bidi_context{outputs}/process(...)->>request_bidi_context{outputs}/process(...): create response res
14 | request_bidi_context{outputs}/process(...)->>server_impl: process_func(bidi_ctx, req, res)
15 | server_impl->>server_impl: sub(bidi_ctx, req, res)
16 | opt bidi_ctx not running
17 | request_bidi_context{outputs}/process(...)->>request_bidi_context{outputs}/process(...): state = request_context_base/FINISH
18 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Finish(grpc/Status/Ok, this)
19 | Note over request_bidi_context{outputs}/process(...): return
20 | end
21 | opt bidi_ctx has more
22 | Note over request_bidi_context{outputs}/process(...): current context has still more responses to stream
23 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Write(res, this)
24 | Note over request_bidi_context{outputs}/process(...): return
25 | end
26 | Note over request_bidi_context{outputs}/process(...): no other responses to stream, but ready to write
27 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Read(req, this)
28 | end
29 | ```
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/input/4_4_falco_grpc_server_stream_handling.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | request_stream_context{outputs}/process(...)->>request_stream_context{outputs}/process(...): create response res
9 | opt state == request_context_base/REQUEST
10 | request_stream_context{outputs}/process(...)->>request_stream_context{outputs}/process(...): state = request_context_base/WRITE
11 | request_stream_context{outputs}/process(...)->>stream_context: stream_ctx = new(srv_ctx)
12 | end
13 | request_stream_context{outputs}/process(...)->>server_impl: process_func(stream_ctx, req, res)
14 | server_impl->>server_impl: get(srv_ctx, req, res)
15 | opt stream_ctx not running
16 | request_stream_context{outputs}/process(...)->>request_stream_context{outputs}/process(...): state = request_context_base/FINISH
17 | request_stream_context{outputs}/process(...)->>grpc/ServerAsyncWriter{outputs}: res_writer->Finish(grpc/Status/Ok, this)
18 | Note over request_stream_context{outputs}/process(...): return
19 | end
20 | opt stream_ctx has more
21 | Note over request_stream_context{outputs}/process(...): current context has still more responses to stream
22 | request_stream_context{outputs}/process(...)->>grpc/ServerAsyncWriter{outputs}: res_writer->Write(res, this)
23 | Note over request_stream_context{outputs}/process(...): return
24 | end
25 | Note over request_stream_context{outputs}/process(...): no other responses to stream
26 | Note over request_stream_context{outputs}/process(...): communicate to the gRPC core we have completed
27 | request_stream_context{outputs}/process(...)->>request_stream_context{outputs}/process(...): state = request_context_base/FINISH
28 | request_stream_context{outputs}/process(...)->>grpc/ServerAsyncWriter{outputs}: res_writer->Finish(grpc/Status/Ok, this)
29 | ```
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/input/2_3_scap_bpf_load_populate_event_table_and_fillers_table.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | scap_bpf_load()->>populate_event_table_map(): call
9 | loop i := 0, i < PPM_EVENT_MAX, i++
10 | populate_event_table_map()->>event_table: g_event_info[i]
11 | Note left of event_table: eg., x = {"rename", EC_FILE, EF_NONE, 3, {{"res", PT_ERRNO, PF_DEC}, {"oldpath", PT_FSPATH, PF_NA}, {"newpath", PT_FSPATH, PF_NA}}}
12 | event_table-->>populate_event_table_map(): x = ppm_event_info{name, category, flags, num params, params descriptions}
13 | populate_event_table_map()->>eBPF VM: sys_bpf(BPF_MAP_UPDATE_ELEM, ...)
14 | Note right of populate_event_table_map(): store x at the i-th position of SYSDIG_EVENT_INFO_TABLE map
15 | eBPF VM-->>populate_event_table_map(): error status
16 | end
17 | populate_event_table_map()-->>scap_bpf_load(): error status
18 | scap_bpf_load()->>populate_fillers_table_map(): call
19 | loop i := 0, i < PPM_EVENT_MAX, i++
20 | populate_fillers_table_map()->>fillers_table: g_ppm_events[i]
21 | Note left of fillers_table: eg., x = {FILLER_REF(sys_open_x)},
22 | fillers_table-->>populate_fillers_table_map(): x = ppm_event_entry{filler callback, ...}
23 | populate_fillers_table_map()->>eBPF VM: sys_bpf(BPF_MAP_UPDATE_ELEM, ...)
24 | Note left of populate_fillers_table_map(): store x at the i-th position of the SYSDIG_FILLERS_TABLE map
25 | eBPF VM-->>populate_fillers_table_map(): error status
26 | end
27 | populate_fillers_table_map()->>populate_fillers_table_map(): check no filler is missing
28 | populate_fillers_table_map()-->>scap_bpf_load(): error status
29 | Note over scap_bpf_load(): ...
30 | ```
31 |
32 |
33 |
34 |
35 | TODO:
36 |
37 | - What eBPF map types are SYSDIG_EVENT_INFO_TABLE and SYSDIG_FILLERS_TABLE?
38 | - Show ppm_event_info (and nested types) example
39 | - SHow ppm_event_entry (and nested types) example
40 |
--------------------------------------------------------------------------------
/input/1_0_scap_open.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | Note over scap_open(): case SCAP_MODE_LIVE
9 | alt userspace
10 | scap_open()->>scap_open_udig_int(): call
11 | scap_open_udig_int()-->>scap_open(): scap_t
12 | else
13 | scap_open()->>scap_open_live_int(): call
14 | scap_open_live_int()->>scap_open_live_int(): bpf_probe = getenv("FALCO_BPF_PROBE")
15 | alt FALCO_BPF_PROBE set
16 | Note over scap_open_live_int(): bpf = true
17 | opt FALCO_BPF_PROBE empty
18 | scap_open_live_int()->>scap_open_live_int(): bpf_probe = $HOME/.falco/falco-bpf.o
19 | Note over scap_open_live_int(): fallback to standard path
20 | end
21 | else
22 | Note over scap_open_live_int(): bpf = false
23 | end
24 | scap_open_live_int()->>sysconf(): _SC_NPROCESSORS_ONLN, _SC_PHYS_PAGES, _SC_PAGESIZE
25 | scap_open_live_int()->>scap_create_iflist(): create interface list
26 | scap_create_iflist()-->>scap_open_live_int(): error status
27 | scap_open_live_int()->>scap_create_userlist(): create user list
28 | scap_create_userlist()-->>scap_open_live_int(): error status
29 | alt bpf == true
30 | scap_open_live_int()->>scap_bpf_load(): load eBPF probe
31 | Note over scap_bpf_load(): REF: SCAP BPF LOAD
32 | scap_bpf_load()-->>scap_open_live_int(): error status
33 | else kernel module
34 | Note over scap_open_live_int(): allocate the ring buffer
35 | Note over scap_open_live_int(): open the devices
36 | Note over scap_open_live_int(): map the ring buffer
37 | end
38 | scap_open_live_int()->>scap_proc_scan_proc_dir(): create process list
39 | scap_proc_scan_proc_dir()-->>scap_open_live_int(): error status
40 | scap_open_live_int()->>scap_start_capture(): start the capture
41 | scap_start_capture()-->>scap_open_live_int(): error status
42 | scap_open_live_int()-->>scap_open(): scap_t
43 | end
44 | ```
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/input/4_1_falco_grpc_server_spawing_threads.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | loop svc := range svcList
9 | grpc_server->>grpc/ServerBuilder: RegisterService(svc)
10 | end
11 | grpc_server->>grpc/ServerBuilder: AddCompletionQueue()
12 | grpc/ServerBuilder-->>grpc_server: unique_ptr grpc/ServerCompletionQueue
13 | grpc_server->>grpc/ServerBuilder: BuildAndStart()
14 | grpc/ServerBuilder-->>grpc_server: unique_ptr grpc/Server
15 | loop threadiness
16 | loop 10 times
17 | grpc_server->>request_context: create(server = this)
18 | request_context->>request_context: process_func = server_impl/version
19 | request_context->>request_context: request_func = version/service/AsyncService/Requestversion
20 | request_context->>request_context: start(server)
21 | rect rgb(0, 172, 199)
22 | Note over request_context: start() sets state to request_context_base/REQUEST
23 | request_context->>grpc/ServerContext: new
24 | grpc/ServerContext-->>request_context: server context (srv_ctx)
25 | request_context->>grcp/ServerAsyncResponseWriter: new(server context)
26 | grcp/ServerAsyncResponseWriter-->>request_context: response writer version/response (res_writer)
27 | request_context->>request_context: get hold of concurrent queue from server (cq)
28 | Note over request_context: request to start processing falco/request requests by calling request_func(srv_ctx, req = version/request, res_writer, cq, cq, this)
29 | Note over request_context: where the memory address of the current context (this) acts as the tag uniquely identifying the request
30 | Note over request_context: this way, different contexts can serve different requests concurrently
31 | end
32 | grpc_server->>request_stream_context: create
33 | rect rgb(0, 172, 199)
34 | Note over request_stream_context: Same logic, with:
35 | Note over request_stream_context: process_func = server_impl/get
36 | Note over request_stream_context: request_func = outputs/service/AsyncService/Requestget
37 | Note over request_stream_context: grpc/ServerAsyncWriter outputs::response
38 | end
39 | grpc_server->>request_bidi_context: create
40 | rect rgb(0, 172, 199)
41 | Note over request_bidi_context: Same logic, with:
42 | Note over request_bidi_context: process_func = server_impl/sub
43 | Note over request_bidi_context: request_func = outputs/service/AsyncService/Requestgsub
44 | Note over request_bidi_context: grpc/ServerAsyncReaderWriter outputs::response, outputs::request
45 | end
46 | end
47 | Note over grpc_server: SPAWN thread_process() INTO A NEW THREAD
48 | end
49 | Note over grpc_server: ...
50 | ```
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/input/2_1_scap_bpf_load_probe_elf_loading.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | Mermaid markup
5 |
6 | ```mermaid
7 | sequenceDiagram
8 | scap_bpf_load()->>load_bpf_file(): call
9 | load_bpf_file()->>load_bpf_file(): struct bpf_map_data maps[BPF_MAP_MAX]
10 | load_bpf_file()->>load_bpf_file(): osname = uname()
11 | opt ELF version == nil
12 | load_bpf_file()-->>load_bpf_file(): error, goto cleanup
13 | end
14 | load_bpf_file()->>load_bpf_file(): fd = open(probepath)
15 | load_bpf_file()->>libelf: elf_begin()
16 | Note left of libelf: read ELF format
17 | libelf-->>load_bpf_file(): elf descriptor
18 | load_bpf_file()->>gelf: gelf_getehdr()
19 | note left of gelf: read ELF header
20 | gelf-->>load_bpf_file(): elf header
21 | loop i := 0, i < shnum, i++
22 | load_bpf_file()->>libelf: get_elf_section()
23 | Note left of libelf: get section i-th header, name, data
24 | Note over load_bpf_file(): store index of maps
25 | Note over load_bpf_file(): store data and links of symbols
26 | opt shname == "kernel_version" && shdata != osname.release
27 | Note right of load_bpf_file(): eBPF probe compiled for another kernel release
28 | load_bpf_file()-->>load_bpf_file(): error, goto cleanup
29 | end
30 | opt shname == "probe_version" && shdata != driver version
31 | Note right of load_bpf_file(): eBPF probe version does not match the Falco driver version
32 | load_bpf_file()-->>load_bpf_file(): error, goto cleanup
33 | end
34 | end
35 |
36 | load_bpf_file()->>load_elf_maps_section(): call
37 | load_elf_maps_section()->>libelf: elf_getscn
38 | load_elf_maps_section()->>libelf: elf_getdata
39 | Note over load_elf_maps_section(): count number of maps
40 | Note over load_elf_maps_section(): sort the maps
41 | loop i := 0, i < numMaps, i++
42 | Note over load_elf_maps_section(): def = bpf_map_def{}
43 | Note over load_elf_maps_section(): assign to def the corresponding portion of ELF data
44 | Note over load_elf_maps_section(): update maps[i] ELF offset
45 | Note over load_elf_maps_section(): maps[i].def = def
46 | end
47 | load_elf_maps_section()-->>load_bpf_file(): error status
48 | load_bpf_file()->>load_maps(): call
49 | loop i := 0, i < numMaps, i++
50 | opt i == PERF_MAP || LOCAL_STATE_MAP || ...
51 | Note over load_maps(): set the max_entries attribute of current map equal to the number of online CPUs
52 | end
53 | load_maps()->>eBPF VM: sys_bpf(BPF_MAP_CREATE, ...)
54 | eBPF VM-->>load_maps(): file descriptor fd
55 | Note over load_maps(): store fd if valid
56 | opt maps[i].type == MAP_TYPE_PROG_ARRAY
57 | Note over load_maps(): store the index i as the position where this eBPF map is
58 | end
59 | end
60 | load_maps()-->>load_bpf_file(): error status
61 |
62 |
63 | loop i := 0, i < shnum, i++
64 | Note over load_bpf_file(): get section i-th header, name, data
65 | opt shtype == SHT_REL
66 | load_bpf_file()->>parse_relocations(): call
67 | parse_reloactions()-->>load_bpf_file(): error status
68 | end
69 | end
70 | loop i := 0, i < shnum, i++
71 | Note over load_bpf_file(): get section i-th header, name, data
72 | opt shname starts with "[raw_]tracepoint/"
73 | load_bpf_file()->>load_tracepoint(): call
74 | load_tracepoint()-->>load_bpf_file(): error status
75 | end
76 | end
77 | opt cleanup or error
78 | load_bpf_file()->>libelf: elf_end()
79 | load_bpf_file()->>load_bpf_file(): close(fd)
80 | load_bpf_file()-->>scap_bpf_load(): status
81 | end
82 | Note over scap_bpf_load(): ...
83 | ```
84 |
85 |
86 |
87 |
88 | TODO:
89 |
90 | - sysdig_map_types
91 |
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # falco-diagrams
2 |
3 | > Diagrams to **visually** explain [Falco](https://github.com/falcosecurity/falco)
4 |
5 | Diagrams are done with [Mermaid](https://mermaid-js.github.io).
6 |
7 | Since I believe a picture is worth a thousand words, even more when trying to explain complicated stuff as Falco and its eBPF driver are... Here we are!
8 |
9 | This repo also provides tooling for automating the making of these diagrams:
10 |
11 | a GiHub action to automatically **generate, commit, and push Falco diagrams** to the `output/` directory.
12 |
13 | But since I didn't like so much the quality of the resulting diagram images, I created a **simple** in-place mermaid **editor** that you can use to:
14 |
15 | 1. **draw** diagrams with a **custom Falco theme**
16 | 2. **download** them as **PNG** images with a good resolution
17 |
18 | I've already created some of them for my [talks](https://youtube.com/playlist?list=PL-YnLgW35W60wX9lhu6-a8ln4I9yfT1ug) and [decks](https://github.com/leodido/presentations) in the past, so you can find them in the [`themed/`](./themed) directory. Enjoy them!
19 |
20 | **Disclaimer**: it's possible that you'll find some of these diagrams and illustrations (and many others) in the upcoming [Falco Cookbook](https://gum.co/falco). Grab it until it's hot!
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | ## Contribute a diagram
56 |
57 | It's simple!
58 |
59 | Just create a `.md` file containing some Mermaid syntax in the `input/` directory. Something like:
60 |
61 | ```mermaid
62 | sequenceDiagram
63 | autonumber
64 | falco->>sinsp: new()
65 | sinsp-->>falco: inspector
66 | falco->>sinsp: open()
67 | Note over sinsp: open_live_common(..., SCAP_MODE_LIVE)
68 | sinsp->>scap: scap_open()
69 | Note over scap: REF: SCAP OPEN
70 | scap-->>sinsp: scap_t
71 | sinsp->>sinsp: init
72 | sinsp-->>falco: void
73 | ```
74 |
75 | This repo's tooling will do the rest for you and you'll obtain in a minute the resulting diagram in the `output/` directory.
76 |
77 | Notice that also the input file will be edited by the tooling by inserting into it the diagram image just generated.
78 |
79 | ## TODOs
80 |
81 | - [ ] Make the in-place editor work also on other browsers other than Google Chrome
82 | - [ ] Create a real in-place editor with a text-area or similar
83 | - At the moment, you need to copy the diagram source in the HTML and re-open it
84 | - [ ] Publish the editor
85 | - [ ] Fix the GitHub action compiling the Mermaid diagrams
86 | - Sizing of the resulting image
87 |
88 | ---
89 |
90 | [](https://github.com/igrigorik/ga-beacon)
91 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | sequenceDiagram
14 | alt state == request_context_base/REQUEST
15 | request_bidi_context{outputs}/process(...)->>bidi_context: bidi_ctx = new(srv_ctx)
16 | request_bidi_context{outputs}/process(...)->>request_bidi_context{outputs}/process(...): state = request_context_base/WRITE
17 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Read(req, this)
18 | else state == request_context_base/WRITE
19 | request_bidi_context{outputs}/process(...)->>request_bidi_context{outputs}/process(...): create response res
20 | request_bidi_context{outputs}/process(...)->>server_impl: process_func(bidi_ctx, req, res)
21 | server_impl->>server_impl: sub(bidi_ctx, req, res)
22 | opt bidi_ctx not running
23 | request_bidi_context{outputs}/process(...)->>request_bidi_context{outputs}/process(...): state = request_context_base/FINISH
24 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Finish(grpc/Status/Ok, this)
25 | Note over request_bidi_context{outputs}/process(...): return
26 | end
27 | opt bidi_ctx has more
28 | Note over request_bidi_context{outputs}/process(...): current context has still more responses to stream
29 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Write(res, this)
30 | Note over request_bidi_context{outputs}/process(...): return
31 | end
32 | Note over request_bidi_context{outputs}/process(...): no other responses to stream, but ready to write
33 | request_bidi_context{outputs}/process(...)->>grpc/ServerAsyncReaderWriter{outputs}: reader_writer->Read(req, this)
34 | end
35 |
36 |
37 |