update(scripts): look for a prebuilt Falco eBPF probe before trying to compile one

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
This commit is contained in:
Leonardo Di Donato 2021-03-29 15:44:10 +00:00 committed by poiana
parent 2a7b32e279
commit 75261d4518

View File

@ -107,12 +107,14 @@ get_target_id() {
source "${HOST_ROOT}/etc/os-release" source "${HOST_ROOT}/etc/os-release"
OS_ID=$ID OS_ID=$ID
elif [ -f "${HOST_ROOT}/etc/debian_version" ]; then elif [ -f "${HOST_ROOT}/etc/debian_version" ]; then
# Older Debian # Older debian distros
# fixme > can this happen on older Ubuntu? # fixme > Can this happen on older Ubuntu?
OS_ID=debian OS_ID=debian
elif [ -f "${HOST_ROOT}/etc/centos-release" ]; then elif [ -f "${HOST_ROOT}/etc/centos-release" ]; then
# Older CentOS # Older CentOS distros
OS_ID=centos OS_ID=centos
elif [ -f "${HOST_ROOT}/etc/VERSION" ]; then
OS_ID=minikube
else else
>&2 echo "Detected an unsupported target system, please get in touch with the Falco community" >&2 echo "Detected an unsupported target system, please get in touch with the Falco community"
exit 1 exit 1
@ -153,20 +155,20 @@ load_kernel_module_compile() {
# Try to compile using all the available gcc versions # Try to compile using all the available gcc versions
for CURRENT_GCC in $(which gcc) $(ls "$(dirname "$(which gcc)")"/gcc-* | grep 'gcc-[0-9]\+' | sort -r); do for CURRENT_GCC in $(which gcc) $(ls "$(dirname "$(which gcc)")"/gcc-* | grep 'gcc-[0-9]\+' | sort -r); do
echo "* Trying to dkms install ${DRIVER_NAME} module with GCC ${CURRENT_GCC}" echo "* Trying to dkms install the Falco module with GCC ${CURRENT_GCC}"
echo "#!/usr/bin/env bash" > /tmp/falco-dkms-make echo "#!/usr/bin/env bash" > /tmp/falco-dkms-make
echo "make CC=${CURRENT_GCC} \$@" >> /tmp/falco-dkms-make echo "make CC=${CURRENT_GCC} \$@" >> /tmp/falco-dkms-make
chmod +x /tmp/falco-dkms-make chmod +x /tmp/falco-dkms-make
if dkms install --directive="MAKE='/tmp/falco-dkms-make'" -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then if dkms install --directive="MAKE='/tmp/falco-dkms-make'" -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
echo "* ${DRIVER_NAME} module installed in dkms, trying to insmod" echo "* Falco module installed in dkms, trying to insmod"
if insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko" > /dev/null 2>&1; then if insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko" > /dev/null 2>&1; then
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms" echo "* Success: Falco module found and loaded in dkms"
exit 0 exit 0
elif insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko.xz" > /dev/null 2>&1; then elif insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko.xz" > /dev/null 2>&1; then
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms (xz)" echo "* Success: Falco module found and loaded in dkms (xz)"
exit 0 exit 0
else else
echo "* Unable to insmod ${DRIVER_NAME} module" echo "* Unable to insmod the Falco module"
fi fi
else else
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log" DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
@ -188,13 +190,13 @@ load_kernel_module_download() {
local URL local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g) URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g)
echo "* Trying to download prebuilt ${DRIVER_NAME} module from ${URL}" echo "* Trying to download a prebuilt Falco module from ${URL}"
if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
echo "* Download succeeded" echo "* Download succeeded"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module loaded" insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: Falco module found and inserted"
exit $? exit $?
else else
>&2 echo "Unable to find a prebuilt ${DRIVER_NAME} module" >&2 echo "Unable to find a prebuilt Falco module"
return return
fi fi
} }
@ -215,42 +217,42 @@ load_kernel_module() {
exit 1 exit 1
fi fi
echo "* Unloading ${DRIVER_NAME} module, if present" echo "* Unloading the Falco module, if present"
rmmod "${DRIVER_NAME}" 2>/dev/null rmmod "${DRIVER_NAME}" 2>/dev/null
WAIT_TIME=0 WAIT_TIME=0
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_") KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
if rmmod "${DRIVER_NAME}" 2>/dev/null; then if rmmod "${DRIVER_NAME}" 2>/dev/null; then
echo "* Unloading ${DRIVER_NAME} module succeeded after ${WAIT_TIME}s" echo "* Unloading the Falco module succeeded after ${WAIT_TIME}s"
break break
fi fi
((++WAIT_TIME)) ((++WAIT_TIME))
if (( WAIT_TIME % 5 == 0 )); then if (( WAIT_TIME % 5 == 0 )); then
echo "* ${DRIVER_NAME} module still loaded, waited ${WAIT_TIME}s (max wait ${MAX_RMMOD_WAIT}s)" echo "* Falco module still loaded, waited ${WAIT_TIME}s (max wait ${MAX_RMMOD_WAIT}s)"
fi fi
sleep 1 sleep 1
done done
if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" > /dev/null 2>&1; then if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" > /dev/null 2>&1; then
echo "* ${DRIVER_NAME} module seems to still be loaded, hoping the best" echo "* Falco} module seems to still be loaded, hoping the best"
exit 0 exit 0
fi fi
echo "* Trying to load a system ${DRIVER_NAME} driver, if present" echo "* Trying to load a system Falco module, if present"
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe" echo "* Success: Falco module found and loaded with modprobe"
exit 0 exit 0
fi fi
echo "* Looking for a prebuilt ${DRIVER_NAME} module for kernel ${KERNEL_RELEASE} locally" echo "* Looking for a prebuilt Falco module for kernel ${KERNEL_RELEASE} locally"
get_target_id get_target_id
local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko" local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
if [ -f "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" ]; then if [ -f "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" ]; then
echo "* Found a prebuilt ${DRIVER_NAME} module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it" echo "* Found a prebuilt Falco module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module loaded" insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: Falco module found and inserted"
exit $? exit $?
fi fi
@ -263,7 +265,7 @@ load_kernel_module() {
fi fi
# Not able to download a prebuilt module nor to compile one on-the-fly # Not able to download a prebuilt module nor to compile one on-the-fly
>&2 echo "Consider compiling your own ${DRIVER_NAME} module and loading it or getting in touch with the Falco community" >&2 echo "Consider compiling your own Falco driver and loading it or getting in touch with the Falco community"
exit 1 exit 1
} }
@ -281,12 +283,12 @@ clean_kernel_module() {
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_") KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}"; then if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}"; then
if rmmod "${DRIVER_NAME}" 2>/dev/null; then if rmmod "${DRIVER_NAME}" 2>/dev/null; then
echo "* Unloading ${DRIVER_NAME} module succeeded" echo "* Unloading the Falco module succeeded"
else else
echo "* Unloading ${DRIVER_NAME} module failed" echo "* Unloading the Falco module failed"
fi fi
else else
echo "* No ${DRIVER_NAME} module loaded" echo "* There is no Falco module loaded"
fi fi
if ! hash dkms >/dev/null 2>&1; then if ! hash dkms >/dev/null 2>&1; then
@ -296,14 +298,14 @@ clean_kernel_module() {
DRIVER_VERSIONS=$(dkms status -m "${DRIVER_NAME}" | cut -d',' -f2 | sed -e 's/^[[:space:]]*//') DRIVER_VERSIONS=$(dkms status -m "${DRIVER_NAME}" | cut -d',' -f2 | sed -e 's/^[[:space:]]*//')
if [ -z "${DRIVER_VERSIONS}" ]; then if [ -z "${DRIVER_VERSIONS}" ]; then
echo "* No ${DRIVER_NAME} module found in dkms" echo "* There is no Falco module in dkms"
return return
fi fi
for CURRENT_VER in ${DRIVER_VERSIONS}; do for CURRENT_VER in ${DRIVER_VERSIONS}; do
if dkms remove -m "${DRIVER_NAME}" -v "${CURRENT_VER}" --all 2>/dev/null; then if dkms remove -m "${DRIVER_NAME}" -v "${CURRENT_VER}" --all 2>/dev/null; then
echo "* Removing ${DRIVER_NAME}/${CURRENT_VER} succeeded" echo "* Removing the Falco module (version ${CURRENT_VER}) succeeded"
else else
echo "* Removing ${DRIVER_NAME}/${CURRENT_VER} failed" echo "* Removing the Falco module (version ${CURRENT_VER}) failed"
exit 1 exit 1
fi fi
done done
@ -321,8 +323,8 @@ load_bpf_probe_compile() {
make modules_prepare > /dev/null make modules_prepare > /dev/null
} }
if [ -n "${COS}" ]; then if [ "${TARGET_ID}" == "cos" ]; then
echo "* COS detected (build ${BUILD_ID}), using cos kernel headers" echo "* COS detected (build ${BUILD_ID}), using COS kernel headers"
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz" BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
KERNEL_EXTRA_VERSION="+" KERNEL_EXTRA_VERSION="+"
@ -353,7 +355,8 @@ load_bpf_probe_compile() {
} }
fi fi
if [ -n "${MINIKUBE}" ]; then if [ "${TARGET_ID}" == "minikube" ]; then
MINIKUBE_VERSION="$(cat "${HOST_ROOT}/etc/VERSION")"
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel" echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version local kernel_version
kernel_version=$(uname -r) kernel_version=$(uname -r)
@ -379,14 +382,16 @@ load_bpf_probe_compile() {
fi fi
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
get_kernel_config
echo "* Downloading ${BPF_KERNEL_SOURCES_URL}" echo "* Downloading ${BPF_KERNEL_SOURCES_URL}"
mkdir -p /tmp/kernel mkdir -p /tmp/kernel
cd /tmp/kernel || exit cd /tmp/kernel || exit
cd "$(mktemp -d -p /tmp/kernel)" || exit cd "$(mktemp -d -p /tmp/kernel)" || exit
if ! curl -L -o kernel-sources.tgz --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" "${BPF_KERNEL_SOURCES_URL}"; then if ! curl -L -o kernel-sources.tgz --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" "${BPF_KERNEL_SOURCES_URL}"; then
>&2 echo "Download failed" >&2 echo "Unable to download the kernel sources"
exit 1; return
fi fi
echo "* Extracting kernel sources" echo "* Extracting kernel sources"
@ -427,46 +432,16 @@ load_bpf_probe_download() {
echo "* Trying to download a prebuilt eBPF probe from ${URL}" echo "* Trying to download a prebuilt eBPF probe from ${URL}"
if ! curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${URL}"; then if ! curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${URL}"; then
>&2 echo "Download failed" >&2 echo "Unable to find a prebuilt Falco eBPF probe"
exit 1; return
fi fi
} }
load_bpf_probe() { load_bpf_probe() {
echo "* Mounting debugfs"
if [ ! -d /sys/kernel/debug/tracing ]; then
mount -t debugfs nodev /sys/kernel/debug
fi
get_kernel_config
if [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/etc/os-release" ]; then
# shellcheck source=/dev/null
source "${HOST_ROOT}/etc/os-release"
if [ "${ID}" == "cos" ]; then
COS=1
fi
fi
if [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/etc/VERSION" ]; then
MINIKUBE=1
MINIKUBE_VERSION="$(cat "${HOST_ROOT}/etc/VERSION")"
fi
get_target_id get_target_id
BPF_PROBE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o" BPF_PROBE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"
if [ -n "$ENABLE_COMPILE" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping compile, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
else
load_bpf_probe_compile
fi
fi
if [ -n "$ENABLE_DOWNLOAD" ]; then if [ -n "$ENABLE_DOWNLOAD" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping download, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}" echo "* Skipping download, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
@ -475,6 +450,14 @@ load_bpf_probe() {
fi fi
fi fi
if [ -n "$ENABLE_COMPILE" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping compilation, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
else
load_bpf_probe_compile
fi
fi
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* eBPF probe located in ${HOME}/.falco/${BPF_PROBE_FILENAME}" echo "* eBPF probe located in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
@ -489,7 +472,7 @@ load_bpf_probe() {
&& echo "* Success: eBPF probe symlinked to ${HOME}/.falco/${DRIVER_NAME}-bpf.o" && echo "* Success: eBPF probe symlinked to ${HOME}/.falco/${DRIVER_NAME}-bpf.o"
exit $? exit $?
else else
>&2 echo "Failure to find an eBPF probe" >&2 echo "Unable to load the Falco eBPF probe"
exit 1 exit 1
fi fi
} }
@ -506,13 +489,14 @@ print_usage() {
echo "Options:" echo "Options:"
echo " --help show brief help" echo " --help show brief help"
echo " --clean try to remove an already present driver installation" echo " --clean try to remove an already present driver installation"
echo " --compile try to compile the driver locally" echo " --compile try to compile the driver locally (default on)"
echo " --download try to download a prebuilt driver" echo " --download try to download a prebuilt driver (default on)"
echo " --source-only skip execution and allow sourcing in another script" echo " --source-only skip execution and allow sourcing in another script"
echo "" echo ""
echo "Environment variables:" echo "Environment variables:"
echo " DRIVER_REPO specify a different URL where to look for prebuilt Falco drivers" echo " DRIVER_REPO specify a different URL where to look for prebuilt Falco drivers"
echo " DRIVER_NAME specify a different name for the driver" echo " DRIVER_NAME specify a different name for the driver"
echo " DRIVER_INSECURE_DOWNLOAD whether you want to allow insecure downloads or not"
echo "" echo ""
echo "Versions:" echo "Versions:"
echo " Falco version ${FALCO_VERSION}" echo " Falco version ${FALCO_VERSION}"
@ -521,8 +505,15 @@ print_usage() {
} }
ARCH=$(uname -m) ARCH=$(uname -m)
KERNEL_RELEASE=$(uname -r) KERNEL_RELEASE=$(uname -r)
if ! hash sed > /dev/null 2>&1; then
>&2 echo "This program requires sed"
exit 1
fi
KERNEL_VERSION=$(uname -v | sed 's/#\([[:digit:]]\+\).*/\1/') KERNEL_VERSION=$(uname -v | sed 's/#\([[:digit:]]\+\).*/\1/')
DRIVERS_REPO=${DRIVERS_REPO:-"@DRIVERS_REPO@"} DRIVERS_REPO=${DRIVERS_REPO:-"@DRIVERS_REPO@"}
if [ -n "$DRIVER_INSECURE_DOWNLOAD" ] if [ -n "$DRIVER_INSECURE_DOWNLOAD" ]
@ -625,7 +616,7 @@ if [ -z "$source_only" ]; then
clean_kernel_module clean_kernel_module
;; ;;
bpf) bpf)
>&2 echo "--clean not supported for driver=$DRIVER" >&2 echo "--clean not supported for driver=bpf"
exit 1 exit 1
esac esac
else else