Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make the falco driver loader downloads first, then fallback to compilation #1599

Merged
merged 6 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions docker/falco/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,9 @@
# limitations under the License.
#

# todo(leogr): remove deprecation notice within a couple of releases
if [[ ! -z "${SKIP_MODULE_LOAD}" ]]; then
echo "* SKIP_MODULE_LOAD is deprecated and will be removed soon, use SKIP_DRIVER_LOADER instead"
fi

# Set the SKIP_DRIVER_LOADER variable to skip loading the driver

if [[ -z "${SKIP_DRIVER_LOADER}" ]] && [[ -z "${SKIP_MODULE_LOAD}" ]]; then
leodido marked this conversation as resolved.
Show resolved Hide resolved
if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
echo "* Setting up /usr/src links from host"

for i in "$HOST_ROOT/usr/src"/*
Expand Down
148 changes: 69 additions & 79 deletions scripts/falco-driver-loader
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# Copyright (C) 2019 The Falco Authors.
# Copyright (C) 2021 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -16,7 +16,7 @@
# limitations under the License.
#
# Simple script that desperately tries to load the kernel instrumentation by
# looking for it in a bunch of ways. Convenient when running falco inside
# looking for it in a bunch of ways. Convenient when running Falco inside
# a container or in other weird environments.
#

Expand Down Expand Up @@ -82,7 +82,7 @@ get_kernel_config() {
echo "* Found kernel config at ${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
elif [ -f "/lib/modules/${KERNEL_RELEASE}/config" ]; then
# this code works both for native host and agent container assuming that
# This code works both for native host and containers assuming that
# Dockerfile sets up the desired symlink /lib/modules -> $HOST_ROOT/lib/modules
echo "* Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
KERNEL_CONFIG_PATH="/lib/modules/${KERNEL_RELEASE}/config"
Expand All @@ -107,12 +107,14 @@ get_target_id() {
source "${HOST_ROOT}/etc/os-release"
OS_ID=$ID
elif [ -f "${HOST_ROOT}/etc/debian_version" ]; then
# Older Debian
# fixme > can this happen on older Ubuntu?
# Older debian distros
# fixme > Can this happen on older Ubuntu?
OS_ID=debian
elif [ -f "${HOST_ROOT}/etc/centos-release" ]; then
# Older CentOS
# Older CentOS distros
OS_ID=centos
elif [ -f "${HOST_ROOT}/etc/VERSION" ]; then
OS_ID=minikube
else
>&2 echo "Detected an unsupported target system, please get in touch with the Falco community"
exit 1
Expand Down Expand Up @@ -140,18 +142,18 @@ get_target_id() {
}

load_kernel_module_compile() {
# skip dkms on UEK hosts because it will always fail
# Skip dkms on UEK hosts because it will always fail
if [[ $(uname -r) == *uek* ]]; then
echo "* Skipping dkms install for UEK host"
>&2 echo "Skipping because the dkms install always fail (on UEK hosts)"
return
fi

if ! hash dkms &>/dev/null; then
echo "* Skipping dkms install (dkms not found)"
if ! hash dkms >/dev/null 2>&1; then
>&2 echo "This program requires dkms"
leodido marked this conversation as resolved.
Show resolved Hide resolved
return
fi

# 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
echo "* Trying to dkms install ${DRIVER_NAME} module with GCC ${CURRENT_GCC}"
echo "#!/usr/bin/env bash" > /tmp/falco-dkms-make
Expand Down Expand Up @@ -181,22 +183,21 @@ load_kernel_module_compile() {
}

load_kernel_module_download() {

get_target_id

local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"

local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g)

echo "* Trying to download prebuilt module from ${URL}"
echo "* Trying to download a prebuilt ${DRIVER_NAME} module from ${URL}"
if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
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: ${DRIVER_NAME} module found and inserted"
exit $?
else
>&2 echo "Download failed, consider compiling your own ${DRIVER_NAME} module and loading it or getting in touch with the Falco community"
exit 1
>&2 echo "Unable to find a prebuilt ${DRIVER_NAME} module"
return
fi
}

Expand Down Expand Up @@ -237,33 +238,35 @@ load_kernel_module() {
exit 0
fi

if [ -n "$ENABLE_COMPILE" ]; then
load_kernel_module_compile
fi


echo "* Trying to load a system ${DRIVER_NAME} driver, if present"
echo "* Trying to load a system ${DRIVER_NAME} module, if present"
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe"
exit 0
fi


echo "* Trying to find locally a prebuilt ${DRIVER_NAME} module for kernel ${KERNEL_RELEASE}, if present"
echo "* Looking for a ${DRIVER_NAME} module locally (kernel ${KERNEL_RELEASE})"

get_target_id

local FALCO_KERNEL_MODULE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"

if [ -f "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" ]; then
echo "* Found a prebuilt module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module loaded"
echo "* Found a prebuilt ${DRIVER_NAME} module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module found and inserted"
exit $?
fi

if [ -n "$ENABLE_DOWNLOAD" ]; then
load_kernel_module_download
fi

if [ -n "$ENABLE_COMPILE" ]; then
load_kernel_module_compile
fi

# Not able to download a prebuilt module nor to compile one on-the-fly
>&2 echo "Consider compiling your own ${DRIVER_NAME} driver and loading it or getting in touch with the Falco community"
exit 1
}

clean_kernel_module() {
Expand All @@ -278,30 +281,30 @@ clean_kernel_module() {
fi

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
echo "* Unloading ${DRIVER_NAME} module succeeded"
else
else
echo "* Unloading ${DRIVER_NAME} module failed"
fi
else
echo "* No ${DRIVER_NAME} module loaded"
echo "* There is no ${DRIVER_NAME} module loaded"
fi

if ! hash dkms &>/dev/null; then
if ! hash dkms >/dev/null 2>&1; then
echo "* Skipping dkms remove (dkms not found)"
return
fi

DRIVER_VERSIONS=$(dkms status -m "${DRIVER_NAME}" | cut -d',' -f2 | sed -e 's/^[[:space:]]*//')
if [ -z "${DRIVER_VERSIONS}" ]; then
echo "* No ${DRIVER_NAME} module found in dkms"
echo "* There is no ${DRIVER_NAME} module in dkms"
return
fi
for CURRENT_VER in ${DRIVER_VERSIONS}; do
if dkms remove -m "${DRIVER_NAME}" -v "${CURRENT_VER}" --all 2>/dev/null; then
echo "* Removing ${DRIVER_NAME}/${CURRENT_VER} succeeded"
else
else
echo "* Removing ${DRIVER_NAME}/${CURRENT_VER} failed"
exit 1
fi
Expand All @@ -314,14 +317,14 @@ load_bpf_probe_compile() {

customize_kernel_build() {
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
fi
make olddefconfig > /dev/null
make modules_prepare > /dev/null
}

if [ -n "${COS}" ]; then
echo "* COS detected (build ${BUILD_ID}), using cos kernel headers"
if [ "${TARGET_ID}" == "cos" ]; then
leodido marked this conversation as resolved.
Show resolved Hide resolved
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"
KERNEL_EXTRA_VERSION="+"
Expand Down Expand Up @@ -352,7 +355,8 @@ load_bpf_probe_compile() {
}
fi

if [ -n "${MINIKUBE}" ]; then
if [ "${TARGET_ID}" == "minikube" ]; then
leodido marked this conversation as resolved.
Show resolved Hide resolved
MINIKUBE_VERSION="$(cat "${HOST_ROOT}/etc/VERSION")"
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version
kernel_version=$(uname -r)
Expand All @@ -378,14 +382,16 @@ load_bpf_probe_compile() {
fi

if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
get_kernel_config

echo "* Downloading ${BPF_KERNEL_SOURCES_URL}"

mkdir -p /tmp/kernel
cd /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
>&2 echo "Download failed"
exit 1;
>&2 echo "Unable to download the kernel sources"
return
fi

echo "* Extracting kernel sources"
Expand Down Expand Up @@ -426,70 +432,46 @@ load_bpf_probe_download() {
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
>&2 echo "Download failed"
exit 1;
>&2 echo "Unable to find a prebuilt ${DRIVER_NAME} eBPF probe"
return
fi
}

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
leodido marked this conversation as resolved.
Show resolved Hide resolved
# 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

BPF_PROBE_FILENAME="${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"

if [ -n "$ENABLE_COMPILE" ]; then
if [ -n "$ENABLE_DOWNLOAD" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping compile, 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}"
else
load_bpf_probe_compile
load_bpf_probe_download
fi
fi

if [ -n "$ENABLE_DOWNLOAD" ]; then
if [ -n "$ENABLE_COMPILE" ]; 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 compilation, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
else
load_bpf_probe_download
load_bpf_probe_compile
fi
fi

if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* eBPF probe located in ${HOME}/.falco/${BPF_PROBE_FILENAME}"

if [ ! -f /proc/sys/net/core/bpf_jit_enable ]; then
echo "******************************************************************"
echo "** BPF doesn't have JIT enabled, performance might be degraded. **"
echo "** Please ensure to run on a kernel with CONFIG_BPF_JIT on. **"
echo "******************************************************************"
fi

ln -sf "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${HOME}/.falco/${DRIVER_NAME}-bpf.o" \
&& echo "* Success: eBPF probe symlinked to ${HOME}/.falco/${DRIVER_NAME}-bpf.o"
exit $?
else
>&2 echo "Failure to find an eBPF probe"
>&2 echo "Unable to load the ${DRIVER_NAME} eBPF probe"
exit 1
fi
}
Expand All @@ -506,13 +488,14 @@ print_usage() {
echo "Options:"
echo " --help show brief help"
echo " --clean try to remove an already present driver installation"
echo " --compile try to compile the driver locally"
echo " --download try to download a prebuilt driver"
echo " --compile try to compile the driver locally (default true)"
echo " --download try to download a prebuilt driver (default true)"
echo " --source-only skip execution and allow sourcing in another script"
echo ""
echo "Environment variables:"
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_REPO specify a different URL where to look for prebuilt Falco drivers"
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 "Versions:"
echo " Falco version ${FALCO_VERSION}"
Expand All @@ -521,8 +504,15 @@ print_usage() {
}

ARCH=$(uname -m)

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/')

DRIVERS_REPO=${DRIVERS_REPO:-"@DRIVERS_REPO@"}

if [ -n "$DRIVER_INSECURE_DOWNLOAD" ]
Expand Down Expand Up @@ -556,7 +546,7 @@ while test $# -gt 0; do
case "$1" in
module|bpf)
if [ -n "$has_args" ]; then
>&2 echo "Only one driver can be passed"
>&2 echo "Only one driver per invocation"
print_usage
exit 1
else
Expand Down Expand Up @@ -614,7 +604,7 @@ if [ -z "$source_only" ]; then
fi

if [ -n "$clean" ]; then
if ! [ -z "$has_opt"]; then
if [ -n "$has_opts" ]; then
>&2 echo "Cannot use --clean with other options"
exit 1
fi
Expand All @@ -625,7 +615,7 @@ if [ -z "$source_only" ]; then
clean_kernel_module
;;
bpf)
>&2 echo "--clean not supported for driver=$DRIVER"
>&2 echo "--clean not supported for driver=bpf"
exit 1
esac
else
Expand Down