falcosecurity / driverkit

Kit for building Falco drivers: kernel modules or eBPF probes
Apache License 2.0
62 stars 52 forks source link

new(cmd,pkg): added new `local` build processor to build drivers using local kernel sources/gcc/clang #306

Closed FedeDP closed 7 months ago

FedeDP commented 7 months ago

What type of PR is this?

/kind feature

Any specific area of the project related to this PR?

/area cmd /area pkg

What this PR does / why we need it:

This PR introduces a new local build processor that will just build chosen driver version against local kernel sources using local gcc/clang. Therefore, to work, it needs kernel-headers installed (eg: /lib/modules/6.6.1-arch1-1/build) and clang/gcc on the machine. It does not use docker, of course.

Moreover, it supports building kmod through dkms, and supports directly using a provided preconfigured src-dir. The bigger aim is to completely implement driver building logic that is today part of falco-driver-loader script; this would allow us to properly use driverkit inside falcoctl to implement the drivertype.Build method (eg: https://github.com/falcosecurity/falcoctl/blob/main/pkg/driver/type/kmod.go#L183). IMHO driverkit should be the only project responsible of building drivers.

Which issue(s) this PR fixes:

Fixes #

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

new: added a local build processor to build local kernel using local kernel sources/gcc/clang
FedeDP commented 7 months ago

Example output:

./_output/bin/driverkit local --output-probe /tmp/probe.o --output-module /tmp/mod.ko -l debug
level=DEBUG msg="running without a configuration file"
level=DEBUG msg="running with options" output-module=/tmp/mod.ko output-probe=/tmp/probe.o driverversion=master kernelrelease=6.6.1-arch1-1 kernelversion=1 target=local arch=amd64 kernelurls=[] repo-org=falcosecurity repo-name=libs
level=INFO msg="driver building, it will take a few seconds" processor=local
level=DEBUG msg="doing a new local build"
make -C /lib/modules/6.6.1-arch1-1/build M=/tmp/driver modules
make[1]: ingresso nella directory «/usr/lib/modules/6.6.1-arch1-1/build»
  CC [M]  /tmp/driver/main.o
  CC [M]  /tmp/driver/dynamic_params_table.o
  CC [M]  /tmp/driver/fillers_table.o
  CC [M]  /tmp/driver/flags_table.o
  CC [M]  /tmp/driver/ppm_events.o
  CC [M]  /tmp/driver/ppm_fillers.o
  CC [M]  /tmp/driver/event_table.o
  CC [M]  /tmp/driver/syscall_table64.o
  CC [M]  /tmp/driver/ppm_cputime.o
  CC [M]  /tmp/driver/ppm_tp.o
  CC [M]  /tmp/driver/syscall_ia32_64_map.o
  LD [M]  /tmp/driver/falco.o
  MODPOST /tmp/driver/Module.symvers
  CC [M]  /tmp/driver/falco.mod.o
  LD [M]  /tmp/driver/falco.ko
  BTF [M] /tmp/driver/falco.ko
make[1]: uscita dalla directory «/usr/lib/modules/6.6.1-arch1-1/build»
filename:       /tmp/driver/module.ko
schema_version: 2.12.4
api_version:    6.0.0
build_commit:   master
version:        master
author:         the Falco authors
license:        Dual MIT/GPL
srcversion:     1748D869C7785E1E4F96844
depends:
retpoline:      Y
name:           falco
vermagic:       6.6.1-arch1-1 SMP preempt mod_unload
parm:           g_buffer_bytes_dim:This is the dimension of a single per-CPU buffer in bytes. Please note: this buffer will be mapped twice in the process virtual memory, so pay attention to its size.
parm:           max_consumers:Maximum number of consumers that can simultaneously open the devices (uint)
parm:           verbose:Enable verbose logging (bool)
make -C /lib/modules/6.6.1-arch1-1/build M=$PWD
make[1]: ingresso nella directory «/usr/lib/modules/6.6.1-arch1-1/build»
clang -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h \
        -D__KERNEL__ -fmacro-prefix-map=./= \
         \
         \
        -D__KERNEL__ \
        -D__BPF_TRACING__ \
        -Wno-gnu-variable-sized-type-not-at-end \
        -Wno-address-of-packed-member \
        -fno-jump-tables \
        -fno-stack-protector \
        -Wno-tautological-compare \
        -Wno-unknown-attributes \
        -O2 -g -emit-llvm -c /tmp/driver/bpf/probe.c -o /tmp/driver/bpf/probe.ll
llc -march=bpf -filetype=obj -o /tmp/driver/bpf/probe.o /tmp/driver/bpf/probe.ll
  MODPOST /tmp/driver/bpf/Module.symvers
make[1]: uscita dalla directory «/usr/lib/modules/6.6.1-arch1-1/build»
-rw-r--r-- 1 federico federico 6399480 21 nov 15.12 probe.o
level=INFO msg="kernel module available" path=/tmp/mod.ko
level=INFO msg="eBPF probe available" path=/tmp/probe.o

ls -la /tmp/mod.ko
-rw-r--r-- 1 federico federico 1169360 21 nov 15.11 /tmp/mod.ko

ls -la /tmp/probe.o
-rw-r--r-- 1 federico federico 6399480 21 nov 15.12 /tmp/probe.o
FedeDP commented 7 months ago

/hold for discussion, eventually :)

dwindsor commented 7 months ago

LGTM! Incorporating driverkit into falcoctl is a great idea.

Is falcoctl the only intended user of the local build processor? IOW, will we ever expect an end user to actually compile w/ local headers?

poiana commented 7 months ago

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: dwindsor, FedeDP

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files: - ~~[OWNERS](https://github.com/falcosecurity/driverkit/blob/master/OWNERS)~~ [FedeDP,dwindsor] Approvers can indicate their approval by writing `/approve` in a comment Approvers can cancel approval by writing `/approve cancel` in a comment
FedeDP commented 7 months ago

Is falcoctl the only intended user of the local build processor? IOW, will we ever expect an end user to actually compile w/ local headers?

Well, since eg: Arch builder is hit by https://github.com/falcosecurity/driverkit/issues/303, i was able to build the drivers on my machine using the new local build processor :D But yep, i think the user will be mostly falcoctl!

FedeDP commented 7 months ago

/unhold