Compare commits

..

20 Commits

Author SHA1 Message Date
Leonardo Grasso
f3f512c6dd fix(.circleci): correct publishing command
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 18:16:53 +02:00
Leonardo Grasso
8d79c11953 fix(CHANGELOG.md): correct typo
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>

Co-authored-by: Leo Di Donato <leodidonato@gmail.com>
2020-05-18 16:56:21 +02:00
Leonardo Grasso
439152c8d8 docs: changelog for 0.23.0
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 16:56:21 +02:00
Leonardo Grasso
3d3d537d85 update(docker/falco-driver-loader): propagate all args
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
88dbc78a44 fix(scripts/falco-driver-loader): exit when bpf download fails
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
59c2e6b421 update(scripts/falco-driver-loader): break apart logic
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
33c93e6c29 chore(scripts/falco-driver-loader): improve messages
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 15:16:59 +02:00
Leonardo Grasso
46483339a3 fix(test): correct kernel module name
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 14:08:25 +02:00
Leonardo Grasso
762ef015b8 fix(scripts): correct kernel module name
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 14:08:25 +02:00
Leonardo Grasso
b887c92c91 docs(RELEASE.md): correct typo
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-18 11:41:05 +02:00
Reshad Patuck
efd0bf1967 fix(falco-driver-loader): target for ubuntu is ubuntu-generic
The upstream files for the generic Ubuntu kernel are all called ubuntu-generic
see: https://dl.bintray.com/falcosecurity/driver/96bd9bc560f67742738eb7255aeb4d03046b8045/

Signed-off-by: Reshad Patuck <reshad@patuck.net>
2020-05-15 19:20:29 +02:00
Leo Di Donato
5c69639a69 update(.github): remove examples and integrations from PR template
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-05-15 11:27:18 +02:00
Leonardo Grasso
b8875df48f fix(.circleci): correct no-driver image aliasing
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:20:56 +02:00
Leonardo Grasso
368817a95d fix(docker/no-driver): correct config value substitution
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:20:56 +02:00
Leonardo Grasso
622a6c1e44 fix(test/driver-loader): source script to get env vars populated
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:19:31 +02:00
Leonardo Grasso
95e7242d13 test: add driver-loader integration tests
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-15 11:19:31 +02:00
Leonardo Grasso
c42cb1858c update(docker/falco): rename folder for naminig consistency
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
Leonardo Grasso
935d9f5378 fix(docker/no-driver): enable time_format_iso_8601 by default
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
Leonardo Grasso
2345ea2770 new(docker): add falco-no-driver image
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
Leonardo Grasso
901239c3c8 docs(docker): add falcosecurity/falco-no-driver image
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2020-05-14 18:59:29 +02:00
29 changed files with 681 additions and 946 deletions

View File

@@ -138,6 +138,15 @@ jobs:
- run:
name: Execute integration tests
command: /usr/bin/entrypoint test
"tests/driver-loader/integration":
machine:
image: ubuntu-1604:202004-01
steps:
- attach_workspace:
at: /tmp/ws
- run:
name: Execute driver-loader integration tests
command: /tmp/ws/source/falco/test/driver-loader/run_test.sh /tmp/ws/build/release/
# Sign rpm packages
"rpm/sign":
docker:
@@ -208,17 +217,19 @@ jobs:
- checkout
- setup_remote_docker
- run:
name: Build and publish slim-dev
name: Build and publish no-driver-dev
command: |
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
docker build --build-arg VERSION_BUCKET=deb-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:master-slim docker/slim
docker build --build-arg VERSION_BUCKET=bin-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco-no-driver:master docker/no-driver
docker tag falcosecurity/falco-no-driver:master falcosecurity/falco:master-slim
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push falcosecurity/falco-no-driver:master
docker push falcosecurity/falco:master-slim
- run:
name: Build and publish dev
command: |
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
docker build --build-arg VERSION_BUCKET=deb-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:master docker/stable
docker build --build-arg VERSION_BUCKET=deb-dev --build-arg FALCO_VERSION=${FALCO_VERSION} -t falcosecurity/falco:master docker/falco
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push falcosecurity/falco:master
- run:
@@ -266,17 +277,21 @@ jobs:
- checkout
- setup_remote_docker
- run:
name: Build and publish slim
name: Build and publish no-driver
command: |
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco:${CIRCLE_TAG}-slim" docker/slim
docker tag "falcosecurity/falco:${CIRCLE_TAG}-slim" falcosecurity/falco:latest-slim
docker build --build-arg VERSION_BUCKET=bin --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco-no-driver:${CIRCLE_TAG}" docker/no-driver
docker tag "falcosecurity/falco-no-driver:${CIRCLE_TAG}" falcosecurity/falco-no-driver:latest
docker tag "falcosecurity/falco-no-driver:${CIRCLE_TAG}" "falcosecurity/falco:${CIRCLE_TAG}-slim"
docker tag "falcosecurity/falco-no-driver:${CIRCLE_TAG}" "falcosecurity/falco:latest-slim"
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push "falcosecurity/falco-no-driver:${CIRCLE_TAG}"
docker push "falcosecurity/falco-no-driver:latest"
docker push "falcosecurity/falco:${CIRCLE_TAG}-slim"
docker push "falcosecurity/falco:latest-slim"
- run:
name: Build and publish stable
name: Build and publish falco
command: |
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco:${CIRCLE_TAG}" docker/stable
docker build --build-arg VERSION_BUCKET=deb --build-arg FALCO_VERSION=${CIRCLE_TAG} -t "falcosecurity/falco:${CIRCLE_TAG}" docker/falco
docker tag "falcosecurity/falco:${CIRCLE_TAG}" falcosecurity/falco:latest
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
docker push "falcosecurity/falco:${CIRCLE_TAG}"
@@ -300,6 +315,9 @@ workflows:
- "tests/integration":
requires:
- "build/centos7"
- "tests/driver-loader/integration":
requires:
- "build/centos7"
- "rpm/sign":
context: falco
filters:
@@ -327,6 +345,7 @@ workflows:
only: master
requires:
- "publish/packages-dev"
- "tests/driver-loader/integration"
release:
jobs:
- "build/centos7":

View File

@@ -40,12 +40,8 @@ Please remove the leading whitespace before the `/kind <>` you uncommented.
> /area engine
> /area examples
> /area rules
> /area integrations
> /area tests
> /area proposals

View File

@@ -2,6 +2,48 @@
This file documents all notable changes to Falco. The release numbering uses [semantic versioning](http://semver.org).
## v0.23.0
Released on 2020-18-05
### Major Changes
* BREAKING CHANGE: the falco-driver-loader script now references `falco-probe.o` and `falco-probe.ko` as `falco.o` and `falco.ko` [[#1158](https://github.com/falcosecurity/falco/pull/1158)]
* BREAKING CHANGE: the `falco-driver-loader` script environment variable to use a custom repository to download drivers now uses the `DRIVERS_REPO` environment variable instead of `DRIVER_LOOKUP_URL`. This variable must contain the parent URI containing the following directory structure `/$driver_version$/falco_$target$_$kernelrelease$_$kernelversion$.[ko|o]`. e.g: [[#1160](https://github.com/falcosecurity/falco/pull/1160)]
* new(scripts): options and command-line usage for `falco-driver-loader` [[#1200](https://github.com/falcosecurity/falco/pull/1200)]
* new: ability to specify exact matches when adding rules to Falco engine (only API) [[#1185](https://github.com/falcosecurity/falco/pull/1185)]
* new(docker): add an image that wraps the `falco-driver-loader` with the toolchain [[#1192](https://github.com/falcosecurity/falco/pull/1192)]
* new(docker): add `falcosecurity/falco-no-driver` image [[#1205](https://github.com/falcosecurity/falco/pull/1205)]
### Minor Changes
* update(scripts): improve `falco-driver-loader` output messages [[#1200](https://github.com/falcosecurity/falco/pull/1200)]
* update: containers look for prebuilt drivers on the Drivers Build Grid [[#1158](https://github.com/falcosecurity/falco/pull/1158)]
* update: driver version bump to 96bd9bc560f67742738eb7255aeb4d03046b8045 [[#1190](https://github.com/falcosecurity/falco/pull/1190)]
* update(docker): now `falcosecurity/falco:slim-*` alias to `falcosecurity/falco-no-driver:*` [[#1205](https://github.com/falcosecurity/falco/pull/1205)]
* docs: instructions to run unit tests [[#1199](https://github.com/falcosecurity/falco/pull/1199)]
* docs(examples): move `/examples` to `contrib` repo [[#1191](https://github.com/falcosecurity/falco/pull/1191)]
* update(docker): remove `minimal` image [[#1196](https://github.com/falcosecurity/falco/pull/1196)]
* update(integration): move `/integrations` to `contrib` repo [[#1157](https://github.com/falcosecurity/falco/pull/1157)]
* https://dl.bintray.com/driver/$driver_version$/falco_$target$_$kernelrelease$_$kernelversion$.[ko|o]` [[#1160](https://github.com/falcosecurity/falco/pull/1160)]
* update(docker/event-generator): remove the event-generator from Falco repository [[#1156](https://github.com/falcosecurity/falco/pull/1156)]
* docs(examples): set audit level to metadata for object secrets [[#1153](https://github.com/falcosecurity/falco/pull/1153)]
### Bug Fixes
* fix(scripts): upstream files (prebuilt drivers) for the generic Ubuntu kernel contains "ubuntu-generic" [[#1212](https://github.com/falcosecurity/falco/pull/1212)]
* fix: support Falco driver on Linux kernels 5.6.y [[#1174](https://github.com/falcosecurity/falco/pull/1174)]
### Rule Changes
* rule(Redirect STDOUT/STDIN to Network Connection in Container): correct rule name as per rules naming convention [[#1164](https://github.com/falcosecurity/falco/pull/1164)]
* rule(Redirect STDOUT/STDIN to Network Connection in Container): new rule to detect Redirect stdout/stdin to network connection in container [[#1152](https://github.com/falcosecurity/falco/pull/1152)]
* rule(K8s Secret Created): new rule to track the creation of Kubernetes secrets (excluding kube-system and service account secrets) [[#1151](https://github.com/falcosecurity/falco/pull/1151)]
* rule(K8s Secret Deleted): new rule to track the deletion of Kubernetes secrets (excluding kube-system and service account secrets) [[#1151](https://github.com/falcosecurity/falco/pull/1151)]
## v0.22.1
Released on 2020-17-04

View File

@@ -17,8 +17,8 @@ project(falco)
option(USE_BUNDLED_DEPS "Bundle hard to find dependencies into the Falco binary" OFF)
option(BUILD_WARNINGS_AS_ERRORS "Enable building with -Wextra -Werror flags" OFF)
# Elapsed time set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add
# a flag to enable this
# Elapsed time
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
# Make flag for parallel processing
include(ProcessorCount)
@@ -99,7 +99,8 @@ ExternalProject_Add(
BUILD_COMMAND ""
INSTALL_COMMAND "")
# curses We pull this in because libsinsp won't build without it
# curses
# We pull this in because libsinsp won't build without it
set(CURSES_NEED_NCURSES TRUE)
find_package(Curses REQUIRED)
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
@@ -214,12 +215,6 @@ ExternalProject_Add(
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
# Hedley
include(DownloadHedley)
# FlatBuffers
include(FlatBuffers)
# gRPC
include(gRPC)
@@ -241,8 +236,8 @@ add_subdirectory(rules)
# Dockerfiles
add_subdirectory(docker)
# Clang format add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT
# "Formatting ..." VERBATIM)
# Clang format
# add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT "Formatting ..." VERBATIM)
# Shared build variables
set(FALCO_SINSP_LIBRARY sinsp)
@@ -251,7 +246,6 @@ set(FALCO_ABSOLUTE_SHARE_DIR "${CMAKE_INSTALL_PREFIX}/${FALCO_SHARE_DIR}")
set(FALCO_BIN_DIR bin)
add_subdirectory(scripts)
add_subdirectory(userspace/profiler)
add_subdirectory(userspace/engine)
add_subdirectory(userspace/falco)
add_subdirectory(tests)

View File

@@ -12,7 +12,7 @@ Finally, on the proposed due date the assignees for the upcoming release proceed
### 1. Release notes
- Let `YYYY-MM-DD` the day before of the [latest release](https://github.com/falcosecurity/falco/releases)
- Check the release note block of every PR matching the `is:pr is:merged closed:>YYY-MM-DD` [filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+closed%3A%3EYYYY-MM-DD)
- Check the release note block of every PR matching the `is:pr is:merged closed:>YYYY-MM-DD` [filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+closed%3A%3EYYYY-MM-DD)
- Ensure the release note block follows the [commit convention](https://github.com/falcosecurity/falco/blob/master/CONTRIBUTING.md#commit-convention), otherwise fix its content
- If the PR has no milestone, assign it to the milestone currently undergoing release
- Check issues without a milestone (using [is:pr is:merged no:milestone closed:>YYYT-MM-DD](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+no%3Amilestone+closed%3A%3EYYYT-MM-DD) filter) and add them to the milestone currently undergoing release

View File

@@ -12,17 +12,16 @@
#
include(ExternalProject)
set(CATCH2_PREFIX ${CMAKE_BINARY_DIR}/catch2-prefix)
set(CATCH2_INCLUDE ${CATCH2_PREFIX}/include)
set(CATCH2_INCLUDE ${CMAKE_BINARY_DIR}/catch2-prefix/include)
set(CATCH_EXTERNAL_URL URL https://github.com/catchorg/catch2/archive/v2.12.1.tar.gz URL_HASH
SHA256=e5635c082282ea518a8dd7ee89796c8026af8ea9068cd7402fb1615deacd91c3)
ExternalProject_Add(
catch2
PREFIX ${CATCH2_PREFIX}
PREFIX ${CMAKE_BINARY_DIR}/catch2-prefix
${CATCH_EXTERNAL_URL}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CATCH2_PREFIX}/src/catch2/single_include/catch2/catch.hpp
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/catch2-prefix/src/catch2/single_include/catch2/catch.hpp
${CATCH2_INCLUDE}/catch.hpp)

View File

@@ -1,26 +0,0 @@
#
# Copyright (C) 2019 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
include(ExternalProject)
set(HEDLEY_PREFIX ${CMAKE_BINARY_DIR}/hedley-prefix)
set(HEDLEY_INCLUDE ${HEDLEY_PREFIX}/include)
message(STATUS "Found hedley: include: ${HEDLEY_INCLUDE}")
ExternalProject_Add(
hedley
PREFIX ${HEDLEY_PREFIX}
GIT_REPOSITORY "https://github.com/nemequ/hedley.git"
GIT_TAG "v13"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${HEDLEY_PREFIX}/src/hedley/hedley.h ${HEDLEY_INCLUDE}/hedley.h)

View File

@@ -1,82 +0,0 @@
#
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
if(NOT USE_BUNDLED_DEPS)
find_program(FLATBUFFERS_FLATC_EXECUTABLE NAMES flatc)
find_path(FLATBUFFERS_INCLUDE_DIR NAMES flatbuffers/flatbuffers.h)
if(FLATBUFFERS_FLATC_EXECUTABLE AND FLATBUFFERS_INCLUDE_DIR)
message(STATUS "Found flatbuffers: include: ${FLATBUFFERS_INCLUDE_DIR}, flatc: ${FLATBUFFERS_FLATC_EXECUTABLE}")
else()
message(FATAL_ERROR "Couldn't find system flatbuffers")
endif()
else()
include(ExternalProject)
set(FLATBUFFERS_PREFIX ${CMAKE_BINARY_DIR}/flatbuffers-prefix)
set(FLATBUFFERS_FLATC_EXECUTABLE
${FLATBUFFERS_PREFIX}/bin/flatc
CACHE INTERNAL "FlatBuffer compiler")
set(FLATBUFFERS_INCLUDE_DIR
${FLATBUFFERS_PREFIX}/include
CACHE INTERNAL "FlatBuffer include directory")
ExternalProject_Add(
flatbuffers
PREFIX ${FLATBUFFERS_PREFIX}
GIT_REPOSITORY "https://github.com/google/flatbuffers.git"
GIT_TAG "v1.12.0"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${FLATBUFFERS_PREFIX}
-DCMAKE_BUILD_TYPE=Release
-DFLATBUFFERS_CODE_COVERAGE=OFF
-DFLATBUFFERS_BUILD_TESTS=OFF
-DFLATBUFFERS_INSTALL=ON
-DFLATBUFFERS_BUILD_FLATLIB=OFF
-DFLATBUFFERS_BUILD_FLATC=ON
-DFLATBUFFERS_BUILD_FLATHASH=OFF
-DFLATBUFFERS_BUILD_GRPCTEST=OFF
-DFLATBUFFERS_BUILD_SHAREDLIB=OFF
BUILD_BYPRODUCTS ${FLATBUFFERS_FLATC_EXECUTABLE})
endif()
# From FindFlatBuffer.cmake
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FlatBuffers DEFAULT_MSG FLATBUFFERS_FLATC_EXECUTABLE FLATBUFFERS_INCLUDE_DIR)
if(FLATBUFFERS_FOUND)
function(FLATBUFFERS_GENERATE_C_HEADERS Name)
set(FLATC_OUTPUTS)
foreach(FILE ${ARGN})
get_filename_component(FLATC_OUTPUT ${FILE} NAME_WE)
set(FLATC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FLATC_OUTPUT}_generated.h")
list(APPEND FLATC_OUTPUTS ${FLATC_OUTPUT})
add_custom_command(
OUTPUT ${FLATC_OUTPUT}
COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE} ARGS -c -o "${CMAKE_CURRENT_BINARY_DIR}/" ${FILE}
DEPENDS ${FILE}
COMMENT "Building C++ header for ${FILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endforeach()
set(${Name}_OUTPUTS
${FLATC_OUTPUTS}
PARENT_SCOPE)
endfunction()
set(FLATBUFFERS_INCLUDE_DIRS ${FLATBUFFERS_INCLUDE_DIR})
include_directories(${CMAKE_BINARY_DIR})
else()
set(FLATBUFFERS_INCLUDE_DIR)
endif()

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2020 The Falco Authors.
# Copyright (C) 2019 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at

View File

@@ -6,9 +6,9 @@ This directory contains various ways to package Falco as a container and related
| Name | Directory | Description |
|---|---|---|
| [falcosecurity/falco:latest](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:master](https://hub.docker.com/repository/docker/falcosecurity/falco) | docker/stable | Falco (DEB built from git tag or from the master) with all the building toolchain. |
| [falcosecurity/falco:latest-slim](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:_tag_-slim](https://hub.docker.com/repository/docker/falcosecurity/falco),[falcosecurity/falco:master-slim](https://hub.docker.com/repository/docker/falcosecurity/falco) | docker/slim | Falco (DEB build from git tag or from the master) without the building toolchain. |
| [falcosecurity/falco:latest](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco), [falcosecurity/falco:master](https://hub.docker.com/repository/docker/falcosecurity/falco) | docker/falco | Falco (DEB built from git tag or from the master) with all the building toolchain. |
| [falcosecurity/falco-driver-loader:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-driver-loader), [falcosecurity/falco-driver-loader:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco-driver-loader), [falcosecurity/falco-driver-loader:master](https://hub.docker.com/repository/docker/falcosecurity/falco-driver-loader) | docker/driver-loader | `falco-driver-loader` as entrypoint with the building toolchain. |
| [falcosecurity/falco-no-driver:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-no-driver), [falcosecurity/falco-no-driver:_tag_](https://hub.docker.com/repository/docker/falcosecurity/falco-no-driver),[falcosecurity/falco-no-driver:master](https://hub.docker.com/repository/docker/falcosecurity/falco-no-driver) | docker/no-driver | Falco (TGZ built from git tag or from the master) without the building toolchain. |
| [falcosecurity/falco-builder:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-builder) | docker/builder | The complete build tool chain for compiling Falco from source. See [the documentation](https://falco.org/docs/source/) for more details on building from source. Used to build Falco (CI). |
| [falcosecurity/falco-tester:latest](https://hub.docker.com/repository/docker/falcosecurity/falco-tester) | docker/tester | Container image for running the Falco test suite. Used to run Falco integration tests (CI). |
| _to not be published_ | docker/local | Built on-the-fly and used by falco-tester. |

View File

@@ -25,4 +25,4 @@ do
ln -s "$i" "/usr/src/$base"
done
/usr/bin/falco-driver-loader $1
/usr/bin/falco-driver-loader "$@"

View File

@@ -0,0 +1,61 @@
FROM ubuntu:18.04 as ubuntu
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG FALCO_VERSION
ARG VERSION_BUCKET=bin
ENV FALCO_VERSION=${FALCO_VERSION}
ENV VERSION_BUCKET=${VERSION_BUCKET}
WORKDIR /
ADD https://bintray.com/api/ui/download/falcosecurity/${VERSION_BUCKET}/x86_64/falco-${FALCO_VERSION}-x86_64.tar.gz /
RUN apt-get update -y && \
apt-get install -y libyaml-0-2 binutils && \
tar -xvf falco-${FALCO_VERSION}-x86_64.tar.gz && \
rm -f falco-${FALCO_VERSION}-x86_64.tar.gz && \
mv falco-${FALCO_VERSION}-x86_64 falco && \
strip falco/usr/bin/falco && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /falco/etc/falco/falco.yaml > /falco/etc/falco/falco.yaml.new \
&& mv /falco/etc/falco/falco.yaml.new /falco/etc/falco/falco.yaml
FROM scratch
COPY --from=ubuntu /lib/x86_64-linux-gnu/libanl.so.1 \
/lib/x86_64-linux-gnu/libc.so.6 \
/lib/x86_64-linux-gnu/libdl.so.2 \
/lib/x86_64-linux-gnu/libgcc_s.so.1 \
/lib/x86_64-linux-gnu/libm.so.6 \
/lib/x86_64-linux-gnu/libnsl.so.1 \
/lib/x86_64-linux-gnu/libnss_compat.so.2 \
/lib/x86_64-linux-gnu/libnss_files.so.2 \
/lib/x86_64-linux-gnu/libnss_nis.so.2 \
/lib/x86_64-linux-gnu/libpthread.so.0 \
/lib/x86_64-linux-gnu/librt.so.1 \
/lib/x86_64-linux-gnu/libz.so.1 \
/lib/x86_64-linux-gnu/
COPY --from=ubuntu /usr/lib/x86_64-linux-gnu/libstdc++.so.6 \
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
COPY --from=ubuntu /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.5 \
/usr/lib/x86_64-linux-gnu/libyaml-0.so.2
COPY --from=ubuntu /etc/ld.so.cache \
/etc/nsswitch.conf \
/etc/ld.so.cache \
/etc/passwd \
/etc/group \
/etc/
COPY --from=ubuntu /etc/default/nss /etc/default/nss
COPY --from=ubuntu /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=ubuntu /falco /
CMD ["/usr/bin/falco", "-o", "time_format_iso_8601=true"]

View File

@@ -1,48 +0,0 @@
FROM ubuntu:18.04
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
LABEL RUN="docker run -i -t -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro --name <name> <image>"
ARG FALCO_VERSION=latest
ARG VERSION_BUCKET=deb
ENV FALCO_VERSION=${FALCO_VERSION}
ENV VERSION_BUCKET=${VERSION_BUCKET}
ENV HOST_ROOT /host
ENV HOME /root
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# bash-completion \
# bc \
ca-certificates \
curl \
gnupg2 \
jq \
# netcat \
# xz-utils \
&& rm -rf /var/lib/apt/lists/*
RUN curl -s https://falco.org/repo/falcosecurity-3672BA8F.asc | apt-key add - \
&& echo "deb https://dl.bintray.com/falcosecurity/${VERSION_BUCKET} stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list \
&& apt-get update -y \
&& if [ "$FALCO_VERSION" = "latest" ]; then apt-get install -y --no-install-recommends falco; else apt-get install -y --no-install-recommends falco=${FALCO_VERSION}; fi \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Change the falco config within the container to enable ISO 8601
# output.
RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /etc/falco/falco.yaml > /etc/falco/falco.yaml.new \
&& mv /etc/falco/falco.yaml.new /etc/falco/falco.yaml
# Some base images have an empty /lib/modules by default
# If it's not empty, docker build will fail instead of
# silently overwriting the existing directory
RUN rm -df /lib/modules \
&& ln -s $HOST_ROOT/lib/modules /lib/modules
CMD ["/usr/bin/falco", "-o", "time_format_iso_8601=true"]

View File

@@ -64,8 +64,8 @@ do_start()
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
if [ ! -d /sys/module/falco_probe ]; then
/sbin/modprobe falco-probe || exit 1
if [ ! -d /sys/module/falco ]; then
/sbin/modprobe falco || exit 1
fi
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
@@ -96,7 +96,7 @@ do_stop()
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
/sbin/rmmod falco-probe
/sbin/rmmod falco
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"

View File

@@ -23,8 +23,7 @@
#
# Returns 1 if $cos_ver > $base_ver, 0 otherwise
#
cos_version_greater()
{
cos_version_greater() {
if [[ $cos_ver == "${base_ver}" ]]; then
return 0
fi
@@ -68,29 +67,29 @@ cos_version_greater()
get_kernel_config() {
if [ -f /proc/config.gz ]; then
echo "Found kernel config at /proc/config.gz"
echo "* Found kernel config at /proc/config.gz"
KERNEL_CONFIG_PATH=/proc/config.gz
elif [ -f "/boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at /boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at /boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH=/boot/config-${KERNEL_RELEASE}
elif [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at ${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at ${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="${HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
elif [ -f "/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
echo "* Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
elif [ -n "${HOST_ROOT}" ] && [ -f "${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
echo "Found kernel config at ${HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
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
# Dockerfile sets up the desired symlink /lib/modules -> $HOST_ROOT/lib/modules
echo "Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
echo "* Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
KERNEL_CONFIG_PATH="/lib/modules/${KERNEL_RELEASE}/config"
fi
if [ -z "${KERNEL_CONFIG_PATH}" ]; then
echo "Cannot find kernel config"
>&2 echo "Cannot find kernel config"
exit 1
fi
@@ -131,7 +130,7 @@ get_target_id() {
if [[ $KERNEL_RELEASE == *"aws"* ]]; then
TARGET_ID="ubuntu-aws"
else
TARGET_ID="ubuntu"
TARGET_ID="ubuntu-generic"
fi
;;
(*)
@@ -140,6 +139,59 @@ get_target_id() {
esac
}
load_kernel_module_compile() {
# skip dkms on UEK hosts because it will always fail
if [[ $(uname -r) == *uek* ]]; then
echo "* Skipping dkms install for UEK host"
else
if hash dkms &>/dev/null; then
echo "* Trying to dkms install ${DRIVER_NAME} module"
if dkms install -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
echo "* ${DRIVER_NAME} 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
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms"
exit 0
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)"
exit 0
else
echo "* Unable to insmod ${DRIVER_NAME} module"
fi
else
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
if [ -f "${DKMS_LOG}" ]; then
echo "* Running dkms build failed, dumping ${DKMS_LOG}"
cat "${DKMS_LOG}"
else
echo "* Running dkms build failed, couldn't find ${DKMS_LOG}"
fi
fi
else
echo "* Skipping dkms install (dkms not found)"
fi
fi
}
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}"
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"
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
fi
}
load_kernel_module() {
if ! hash lsmod > /dev/null 2>&1; then
>&2 echo "This program requires lsmod"
@@ -177,67 +229,160 @@ load_kernel_module() {
exit 0
fi
# skip dkms on UEK hosts because it will always fail`
if [[ $(uname -r) == *uek* ]]; then
echo "* Skipping dkms install for UEK host"
else
if hash dkms &>/dev/null && dkms install -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
echo "* Trying to load a dkms ${DRIVER_NAME} module, if present"
if insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko" > /dev/null 2>&1; then
echo "${DRIVER_NAME} module found and loaded in dkms"
exit 0
elif insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko.xz" > /dev/null 2>&1; then
echo "${DRIVER_NAME} module found and loaded in dkms (xz)"
exit 0
else
echo "* Unable to insmod"
fi
else
DKMS_LOG="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/build/make.log"
if [ -f "${DKMS_LOG}" ]; then
echo "* Running dkms build failed, dumping ${DKMS_LOG}"
cat "${DKMS_LOG}"
else
echo "* Running dkms build failed, couldn't find ${DKMS_LOG}"
fi
fi
if [ -n "$ENABLE_COMPILE" ]; then
load_kernel_module_compile
fi
echo "* Trying to load a system ${DRIVER_NAME} driver, if present"
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
echo "${DRIVER_NAME} module found and loaded with modprobe"
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe"
exit 0
fi
fi
echo "* Trying to find a prebuilt ${DRIVER_NAME} module for kernel ${KERNEL_RELEASE}"
echo "* Trying to find locally a prebuilt ${DRIVER_NAME} module for kernel ${KERNEL_RELEASE}, if present"
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 "* 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"
exit $?
fi
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${FALCO_KERNEL_MODULE_FILENAME}" | sed s/+/%2B/g)
if [ -n "$ENABLE_DOWNLOAD" ]; then
load_kernel_module_download
fi
}
echo "* Trying to download prebuilt module from ${URL}"
if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
echo "Download succeeded, loading module"
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}"
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
load_bpf_probe_compile() {
local BPF_KERNEL_SOURCES_URL=""
local STRIP_COMPONENTS=1
customize_kernel_build() {
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
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"
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
KERNEL_EXTRA_VERSION="+"
STRIP_COMPONENTS=0
customize_kernel_build() {
pushd usr/src/* > /dev/null || exit
# Note: this overrides the KERNELDIR set while untarring the tarball
KERNELDIR=$(pwd)
export KERNELDIR
sed -i '/^#define randomized_struct_fields_start struct {$/d' include/linux/compiler-clang.h
sed -i '/^#define randomized_struct_fields_end };$/d' include/linux/compiler-clang.h
popd > /dev/null || exit
# Might need to configure our own sources depending on COS version
cos_ver=${BUILD_ID}
base_ver=11553.0.0
cos_version_greater
greater_ret=$?
if [[ greater_ret -eq 1 ]]; then
export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
fi
}
fi
if [ -n "${MINIKUBE}" ]; then
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version
kernel_version=$(uname -r)
local -r kernel_version_major=$(echo "${kernel_version}" | cut -d. -f1)
local -r kernel_version_minor=$(echo "${kernel_version}" | cut -d. -f2)
local -r kernel_version_patch=$(echo "${kernel_version}" | cut -d. -f3)
if [ "${kernel_version_patch}" == "0" ]; then
kernel_version="${kernel_version_major}.${kernel_version_minor}"
fi
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
local -r kernel_version_major=$(uname -r | cut -d. -f1)
local -r kernel_version=$(uname -r | cut -d- -f1)
KERNEL_EXTRA_VERSION="-$(uname -r | cut -d- -f2)"
echo "* Using downloaded kernel sources for kernel version ${kernel_version}..."
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
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;
fi
echo "* Extracting kernel sources"
mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"
cd kernel-sources || exit
KERNELDIR=$(pwd)
export KERNELDIR
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
zcat "${KERNEL_CONFIG_PATH}" > .config
else
cat "${KERNEL_CONFIG_PATH}" > .config
fi
echo "* Configuring kernel"
customize_kernel_build
fi
echo "* Trying to compile the eBPF probe (${BPF_PROBE_FILENAME})"
make -C "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf" > /dev/null
mkdir -p "${HOME}/.falco"
mv "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf/probe.o" "${HOME}/.falco/${BPF_PROBE_FILENAME}"
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
rm -r /tmp/kernel
fi
}
load_bpf_probe_download() {
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
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;
fi
}
load_bpf_probe() {
echo "* Mounting debugfs"
if [ ! -d /sys/kernel/debug/tracing ]; then
@@ -262,128 +407,27 @@ load_bpf_probe() {
get_target_id
local 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 [ ! -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
local BPF_KERNEL_SOURCES_URL=""
local STRIP_COMPONENTS=1
customize_kernel_build() {
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
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..."
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
KERNEL_EXTRA_VERSION="+"
STRIP_COMPONENTS=0
customize_kernel_build() {
pushd usr/src/* > /dev/null || exit
# Note: this overrides the KERNELDIR set while untarring the tarball
KERNELDIR=$(pwd)
export KERNELDIR
sed -i '/^#define randomized_struct_fields_start struct {$/d' include/linux/compiler-clang.h
sed -i '/^#define randomized_struct_fields_end };$/d' include/linux/compiler-clang.h
popd > /dev/null || exit
# Might need to configure our own sources depending on COS version
cos_ver=${BUILD_ID}
base_ver=11553.0.0
cos_version_greater
greater_ret=$?
if [[ greater_ret -eq 1 ]]; then
export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
fi
}
fi
if [ -n "${MINIKUBE}" ]; then
echo "* Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version
kernel_version=$(uname -r)
local -r kernel_version_major=$(echo "${kernel_version}" | cut -d. -f1)
local -r kernel_version_minor=$(echo "${kernel_version}" | cut -d. -f2)
local -r kernel_version_patch=$(echo "${kernel_version}" | cut -d. -f3)
if [ "${kernel_version_patch}" == "0" ]; then
kernel_version="${kernel_version_major}.${kernel_version_minor}"
fi
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
local -r kernel_version_major=$(uname -r | cut -d. -f1)
local -r kernel_version=$(uname -r | cut -d- -f1)
KERNEL_EXTRA_VERSION="-$(uname -r | cut -d- -f2)"
echo "* Using downloaded kernel sources for kernel version ${kernel_version}..."
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
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
exit 1;
fi
echo "* Extracting kernel sources"
mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"
cd kernel-sources || exit
KERNELDIR=$(pwd)
export KERNELDIR
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
zcat "${KERNEL_CONFIG_PATH}" > .config
else
cat "${KERNEL_CONFIG_PATH}" > .config
fi
echo "* Configuring kernel"
customize_kernel_build
fi
echo "* Trying to compile the eBPF probe (${BPF_PROBE_FILENAME})"
make -C "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf" > /dev/null
mkdir -p "${HOME}/.falco"
mv "/usr/src/${DRIVER_NAME}-${DRIVER_VERSION}/bpf/probe.o" "${HOME}/.falco/${BPF_PROBE_FILENAME}"
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
rm -r /tmp/kernel
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 [ ! -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
echo "* Trying to download a prebuilt eBPF probe from ${URL}"
curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${URL}"
if [ -n "$ENABLE_DOWNLOAD" ]; then
if [ -f "${HOME}/.falco/${BPF_PROBE_FILENAME}" ]; then
echo "* Skipping download, eBPF probe is already present in ${HOME}/.falco/${BPF_PROBE_FILENAME}"
else
load_bpf_probe_download
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. **"
@@ -391,20 +435,37 @@ load_bpf_probe() {
echo "******************************************************************"
fi
echo "* eBPF probe located, it's now possible to start Falco"
ln -sf "${HOME}/.falco/${BPF_PROBE_FILENAME}" "${HOME}/.falco/${DRIVER_NAME}-bpf.o"
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
echo "* Failure to find an eBPF probe"
>&2 echo "Failure to find an eBPF probe"
exit 1
fi
}
print_usage() {
echo ""
echo "Usage:"
echo " falco-driver-loader [driver] [options]"
echo ""
echo "Available drivers:"
echo " module kernel module (default)"
echo " bpf eBPF probe"
echo ""
echo "Options:"
echo " --help show brief help"
echo " --compile try to compile the driver locally"
echo " --download try to download a prebuilt driver"
echo " --source-only skip execution and allow sourcing in another script"
echo ""
}
ARCH=$(uname -m)
KERNEL_RELEASE=$(uname -r)
KERNEL_VERSION=$(uname -v | sed 's/#\([[:digit:]]\+\).*/\1/')
DRIVERS_REPO=${DRIVERS_REPO:-"@DRIVERS_REPO@"}
if [ -n "$DRIVER_INSECURE_DOWNLOAD" ]
then
FALCO_DRIVER_CURL_OPTIONS=-fsSk
@@ -420,18 +481,84 @@ fi
DRIVER_VERSION="@PROBE_VERSION@"
DRIVER_NAME="@PROBE_NAME@"
if [ "$(id -u)" != 0 ]; then
echo "Installer must be run as root (or with sudo)."
exit 1
DRIVER="module"
if [ -v FALCO_BPF_PROBE ]; then
DRIVER="bpf"
fi
if ! hash curl > /dev/null 2>&1; then
echo "This program requires curl"
exit 1
ENABLE_COMPILE=
ENABLE_DOWNLOAD=
has_args=
has_opts=
source_only=
while test $# -gt 0; do
case "$1" in
module|bpf)
if [ -n "$has_args" ]; then
>&2 echo "Only one driver can be passed"
print_usage
exit 1
else
DRIVER="$1"
has_args="true"
shift
fi
;;
-h|--help)
print_usage
exit 0
;;
--compile)
ENABLE_COMPILE="yes"
has_opts="true"
shift
;;
--download)
ENABLE_DOWNLOAD="yes"
has_opts="true"
shift
;;
--source-only)
source_only="true"
shift
;;
--*)
>&2 echo "Unknown option: $1"
print_usage
exit 1
;;
*)
>&2 echo "Unknown driver: $1"
print_usage
exit 1
;;
esac
done
if [ -z "$has_opts" ]; then
ENABLE_COMPILE="yes"
ENABLE_DOWNLOAD="yes"
fi
if [ -v FALCO_BPF_PROBE ] || [ "${1}" = "bpf" ]; then
load_bpf_probe
else
load_kernel_module
fi
if [ -z "$source_only" ]; then
if [ "$(id -u)" != 0 ]; then
>&2 echo "This program must be run as root (or with sudo)"
exit 1
fi
if ! hash curl > /dev/null 2>&1; then
>&2 echo "This program requires curl"
exit 1
fi
echo "* Running falco-driver-loader with: driver=$DRIVER, compile=${ENABLE_COMPILE:-"no"}, download=${ENABLE_DOWNLOAD:-"no"}"
case $DRIVER in
module)
load_kernel_module
;;
bpf)
load_bpf_probe
;;
esac
fi

View File

@@ -53,8 +53,8 @@ start() {
# [ -f $config ] || exit 6
echo -n $"Starting $prog: "
daemon $exec --daemon --pidfile=$pidfile
if [ ! -d /sys/module/falco_probe ]; then
/sbin/modprobe falco-probe || return $?
if [ ! -d /sys/module/falco ]; then
/sbin/modprobe falco || return $?
fi
retval=$?
echo
@@ -67,7 +67,7 @@ stop() {
killproc -p $pidfile
retval=$?
echo
/sbin/rmmod falco-probe
/sbin/rmmod falco
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}

48
test/driver-loader/run_test.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
#
# Copyright (C) 2020 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set -euo pipefail
BUILD_DIR=$1
SCRIPT=$(readlink -f $0)
SCRIPTDIR=$(dirname $SCRIPT)
RUNNERDIR="${SCRIPTDIR}/runner"
FALCO_VERSION=$(cat ${BUILD_DIR}/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
DRIVER_VERSION=$(cat ${BUILD_DIR}/userspace/falco/config_falco.h | grep 'DRIVER_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
FALCO_PACKAGE="falco-${FALCO_VERSION}-x86_64.tar.gz"
cp "${BUILD_DIR}/${FALCO_PACKAGE}" "${RUNNERDIR}"
pushd ${RUNNERDIR}
docker build --build-arg FALCO_VERSION="$FALCO_VERSION" \
-t falcosecurity/falco:test-driver-loader \
-f "${RUNNERDIR}/Dockerfile" ${RUNNERDIR}
popd
rm -f "${RUNNERDIR}/${FALCO_PACKAGE}"
docker run --rm --privileged \
-e FALCO_VERSION="$FALCO_VERSION" \
-e DRIVER_VERSION="$DRIVER_VERSION" \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
-v /etc:/host/etc:ro \
falcosecurity/falco:test-driver-loader
docker rmi -f falcosecurity/falco:test-driver-loader

View File

@@ -0,0 +1,33 @@
FROM ubuntu:18.04
ARG FALCO_VERSION=
RUN test -n FALCO_VERSION
ENV FALCO_VERSION ${FALCO_VERSION}
ENV DRIVER_VERSION=
ENV HOST_ROOT=/host
# Minimal set of deps required to run falco-driver-loader and falco
RUN apt-get update -y
RUN apt-get install -y --no-install-recommends \
ca-certificates \
libyaml-0-2 \
dkms \
curl \
gcc \
clang-7 \
llvm-7 \
libelf-dev
RUN rm -rf /usr/bin/clang \
&& rm -rf /usr/bin/llc \
&& ln -s /usr/bin/clang-7 /usr/bin/clang \
&& ln -s /usr/bin/llc-7 /usr/bin/llc
RUN rm -rf /lib/modules \
&& ln -s $HOST_ROOT/lib/modules /lib/modules
ADD falco-${FALCO_VERSION}-x86_64.tar.gz /
RUN cp -R /falco-${FALCO_VERSION}-x86_64/* /
COPY test.sh /
CMD /test.sh

136
test/driver-loader/runner/test.sh Executable file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env bash
#
# Copyright (C) 2020 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set -euo pipefail
FALCO="falco -M 1"
FALCO_DRIVER_LOADER=falco-driver-loader
function init() {
# We need this here since is not part of the falco-driver-loader script
#
# todo(leogr): maybe this can be moved into falco-driver-loader directly
# since it depends on HOST_ROOT
if [ -n "${HOST_ROOT}" ]; then
echo "INIT: Setting up /usr/src links from host"
for i in "$HOST_ROOT/usr/src"/*
do
base=$(basename "$i")
ln -s "$i" "/usr/src/$base"
done
fi
local EXPECTED_DRIVER_VERSION=${DRIVER_VERSION}
# We need some env vars to be populated
# Just source falco-driver-loader, and call get_target_id
# Loaded driver will be cleaned up later, if any.
echo "INIT: Sourcing ${FALCO_DRIVER_LOADER} to get env vars populated"
set +eu
source $FALCO_DRIVER_LOADER --source-only
get_target_id
set -eu
if [ ! "${EXPECTED_DRIVER_VERSION}" = "${DRIVER_VERSION}" ]; then
echo "INIT: Unexpected DRIVER_VERSION in falco-driver-loader"
echo "Expected: ${EXPECTED_DRIVER_VERSION}"
echo "Found: ${DRIVER_VERSION}"
exit 1
fi
FALCO_KERNEL_MODULE_PATH="${HOME}/.falco/${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.ko"
FALCO_BPF_PROBE_PATH="${HOME}/.falco/${DRIVER_NAME}_${TARGET_ID}_${KERNEL_RELEASE}_${KERNEL_VERSION}.o"
cleanup_drivers
}
function cleanup_drivers() {
echo "CLEANUP: remove drivers, if any"
# kernel module
rmmod "$DRIVER_NAME" > /dev/null 2>&1 || true
dkms uninstall "$DRIVER_NAME/$DRIVER_VERSION" > /dev/null 2>&1 || true
rm -f "$FALCO_KERNEL_MODULE_PATH"
# bpf probe
local PROBE_INSTALL_PATH="${HOME}/.falco/${DRIVER_NAME}-bpf.o"
rm -f "$FALCO_BPF_PROBE_PATH"
rm -f "$PROBE_INSTALL_PATH"
}
function run_test() {
echo ""
echo "TEST: $1"
echo ""
$1
echo ""
echo "PASS: $1"
echo ""
cleanup_drivers
}
function assert_kernel_module() {
echo "ASSERT: module loaded"
local KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
if ! lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
echo "FAIL: module not loaded"
exit 1
fi
echo "ASSERT: falco works with module"
if ! $FALCO; then
echo "FAIL: falco does not work with module"
exit 1
fi
}
function assert_bpf_probe() {
local PROBE_INSTALL_PATH="${HOME}/.falco/${DRIVER_NAME}-bpf.o"
echo "ASSERT: eBPF probe at $PROBE_INSTALL_PATH"
if ! test -f "$PROBE_INSTALL_PATH"; then
echo "FAIL: eBPF probe not found"
exit 1
fi
echo "ASSERT: falco works with bpf"
if ! FALCO_BPF_PROBE="" $FALCO; then
echo "FAIL: falco does not work with bpf"
exit 1
fi
}
function test_kernel_module() {
$FALCO_DRIVER_LOADER
assert_kernel_module
}
function test_bpf_probe() {
$FALCO_DRIVER_LOADER bpf
assert_bpf_probe
}
echo "falco-driver-loader tester"
echo ""
echo "Falco version: $FALCO_VERSION"
echo "Driver version: $DRIVER_VERSION"
echo "HOST_ROOT: ${HOST_ROOT}"
echo ""
init
run_test "test_kernel_module"
run_test "test_bpf_probe"

View File

@@ -411,8 +411,8 @@ class FalcoTest(Test):
md5_output = subprocess.check_output(["md5sum", "/boot/config-{}".format(kernel_release)]).rstrip()
config_hash = md5_output.split(" ")[0]
probe_filename = "falco-probe-{}-{}-{}-{}.ko".format(falco_version, arch, kernel_release, config_hash)
driver_path = os.path.join(self.falcodir, "driver", "falco-probe.ko")
probe_filename = "falco-{}-{}-{}-{}.ko".format(falco_version, arch, kernel_release, config_hash)
driver_path = os.path.join(self.falcodir, "driver", "falco.ko")
module_path = os.path.join(self.module_dir, probe_filename)
self.log.debug("Copying {} to {}".format(driver_path, module_path))
shutil.copyfile(driver_path, module_path)

View File

@@ -14,9 +14,9 @@
# License for the specific language governing permissions and limitations under
# the License.
#
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp falco/test_webserver.cpp engine/test_rulesets.cpp profiler/test_profiler.cpp)
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp engine/test_rulesets.cpp falco/test_webserver.cpp)
set(FALCO_TESTED_LIBRARIES falco_engine falco_profiler)
set(FALCO_TESTED_LIBRARIES falco_engine)
SET(FALCO_TESTS_ARGUMENTS "" CACHE STRING "Test arguments to pass to the Falco test suite")
@@ -43,12 +43,12 @@ if(FALCO_BUILD_TESTS)
"${YAMLCPP_INCLUDE_DIR}"
"${CIVETWEB_INCLUDE_DIR}"
"${PROJECT_SOURCE_DIR}/userspace/falco")
add_dependencies(falco_test catch2 hedley)
add_dependencies(falco_test catch2)
include(CMakeParseArguments)
include(CTest)
include(Catch)
catch_discover_tests(falco_test)
separate_arguments(FALCO_TESTS_ARGUMENTS)
add_custom_target(tests COMMAND ${CMAKE_CTEST_COMMAND} ${FALCO_TESTS_ARGUMENTS} DEPENDS falco_test flatbuffer_profiler)
add_custom_target(tests COMMAND ${CMAKE_CTEST_COMMAND} ${FALCO_TESTS_ARGUMENTS} DEPENDS falco_test)
endif()

View File

@@ -1,353 +0,0 @@
/*
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "profiler.h"
#include <catch.hpp>
#include <thread>
#include <chrono>
#include <algorithm>
#include <hedley.h>
#include <cstdlib>
#include <iostream>
#include <thread>
#include <flatbuffers/flatbuffers.h>
#include "profile_generated.h"
// void profile_recurse(int times)
// {
// PROFILEME();
// for(int i = 1; i < times; i++)
// {
// profile_recurse(1);
// }
// }
void profiler_sleep_1sec()
{
PROFILEME();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void profiler_sleep_2sec()
{
PROFILEME();
profiler_sleep_1sec();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
TEST_CASE("profiler stores labels and chunks", "[profiler]")
{
SECTION("profiler needs to be allocated before usage")
{
profiler::alloc_chunk();
REQUIRE(profiler::chunks.size() == 1);
REQUIRE(profiler::labels.empty());
}
SECTION("calling a profiled function results in labels and chunks increase")
{
profiler_sleep_1sec();
REQUIRE(profiler::labels.size() == 1);
REQUIRE(profiler::chunks.size() == 1);
}
SECTION("calling just another profiled function that calls the one previously called should only increase labels by one")
{
profiler_sleep_2sec();
REQUIRE(profiler::labels.size() == 2);
REQUIRE(profiler::chunks.size() == 1);
}
SECTION("clean")
{
profiler::labels.clear();
profiler::chunks.clear();
REQUIRE(profiler::labels.empty());
REQUIRE(profiler::chunks.empty());
}
}
void bb()
{
PROFILEME();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void aa()
{
PROFILEME();
bb();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void aa_threaded()
{
profiler::alloc_chunk();
PROFILEME();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void cc()
{
PROFILEME();
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
void profiler_fake_root_func()
{
PROFILEME();
aa();
std::this_thread::sleep_for(std::chrono::microseconds(1));
bb();
std::this_thread::sleep_for(std::chrono::microseconds(1));
cc();
std::this_thread::sleep_for(std::chrono::microseconds(1));
aa();
}
TEST_CASE("profiler computes parents (single chunk)", "[profiler]")
{
profiler::alloc_chunk();
profiler_fake_root_func();
REQUIRE(profiler::labels.size() == 4);
REQUIRE(profiler::chunks.size() == 1);
REQUIRE(profiler::chunks[0].begin[5] == 0); // profiler_fake_root_func is root (parent = 0)
auto predicate = [](int x) {
return [=](const profiler::label &l) {
return l.label == profiler::chunks[0].begin[x];
};
};
// Ctor ordering:
// profile_fake_root
// AA1
// BB1
// BB2
// CC1
// AA2
// BB3
// Dtor ordering:
// BB1
// AA1
// BB2
// CC1
// BB3
// AA2
// profile_fake_root
auto root = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(0));
REQUIRE(root->func == "profiler_fake_root_func"); // function name is "profiler_fake_root_func"
REQUIRE(profiler::chunks[0].begin[5 + CHUNK_ELEMENTS] == root->label); // aa (call aa1) has parent "profiler_fake_root_func"
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(CHUNK_ELEMENTS));
REQUIRE(it->func == "aa"); // function name is "aa" (call aa1)
REQUIRE(profiler::chunks[0].begin[5 + (2 * CHUNK_ELEMENTS)] == it->label); // bb (call bb1) has parent "aa" (call aa1)
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(2 * CHUNK_ELEMENTS));
REQUIRE(it->func == "bb"); // function name is "bb" (call bb1)
REQUIRE(profiler::chunks[0].begin[5 + (3 * CHUNK_ELEMENTS)] == root->label); // bb (call bb2) has parent "profiler_fake_root_func"
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(3 * CHUNK_ELEMENTS));
REQUIRE(it->func == "bb"); // function name is "bb" (call bb2)
REQUIRE(profiler::chunks[0].begin[5 + (4 * CHUNK_ELEMENTS)] == root->label); // cc (call cc1) has parent "profiler_fake_root_func"
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(4 * CHUNK_ELEMENTS));
REQUIRE(it->func == "cc"); // function name is "cc" (call cc1)
REQUIRE(profiler::chunks[0].begin[5 + (5 * CHUNK_ELEMENTS)] == root->label); // aa (call aa2) has parent "profiler_fake_root_func"
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(5 * CHUNK_ELEMENTS));
REQUIRE(it->func == "aa"); // function name is "aa" (call aa2)
REQUIRE(profiler::chunks[0].begin[5 + (6 * CHUNK_ELEMENTS)] == it->label); // bb (call bb3) has parent "aa" (call aa2)
}
{
auto it = std::find_if(std::begin(profiler::labels), std::end(profiler::labels), predicate(6 * CHUNK_ELEMENTS));
REQUIRE(it->func == "bb"); // function name is "bb" (call bb3)
}
for(std::vector<int>::size_type j = 0; j != profiler::chunks.size(); j++)
{
auto *c = profiler::chunks[j].begin;
for(int i = 0; i < CHUNK_SIZE; i += CHUNK_ELEMENTS)
{
if(c[i] == 0)
{
break;
}
auto parent = c[i + 5];
auto e = ((unsigned long long)c[i + 4]) | (((unsigned long long)c[i + 3]) << 32);
auto s = ((unsigned long long)c[i + 2]) | (((unsigned long long)c[i + 1]) << 32);
char b[1024];
if(i == 0)
{
sprintf(b, "#;idx;parent ;function ;clocks");
std::cout << std::string(b) << std::endl;
}
sprintf(b, "%ld;%03d;%010u;%u;%lld", j, i, parent, c[i], e - s);
std::cout << std::string(b) << std::endl;
}
}
profiler::labels.clear();
profiler::chunks.clear();
REQUIRE(profiler::labels.empty());
REQUIRE(profiler::chunks.empty());
}
// TEST_CASE("profile computes recursive parents (more chunks)", "[profiler]")
// {
// alloc_chunk();
// REQUIRE(chunks.size() == 1);
// size_t expected_chunks = 2;
// int how_many_times = (CHUNK_SIZE / CHUNK_ELEMENTS) * HEDLEY_STATIC_CAST(int, expected_chunks);
// profile_recurse(how_many_times);
// REQUIRE(labels.size() == 1);
// REQUIRE(chunks.size() == expected_chunks + 1);
// for(std::vector<int>::size_type j = 0; j != chunks.size(); j++)
// {
// auto *c = chunks[j].begin;
// for(int i = 0; i < CHUNK_SIZE; i++)
// {
// char b[1024];
// sprintf(b, "%ld - %03d: %u", j, i, c[i]);
// std::cout << std::string(b) << std::endl;
// }
// }
// labels.clear();
// chunks.clear();
// REQUIRE(labels.empty());
// REQUIRE(chunks.empty());
// }
TEST_CASE("profiler flatbuffer serialization deserialization", "[profiler]")
{
flatbuffers::FlatBufferBuilder builder;
auto node_one = profiler::CreateNodeDirect(
builder,
"do_init",
"falco_engine.cpp",
345,
500);
auto node_two_one = profiler::CreateNodeDirect(
builder,
"do_match2",
"ruleset.cpp",
690,
100);
std::vector<flatbuffers::Offset<profiler::Node>> third_level;
third_level.push_back(node_two_one);
auto node_two = profiler::CreateNodeDirect(
builder,
"do_match",
"ruleset.cpp",
678,
250,
&third_level);
std::vector<flatbuffers::Offset<profiler::Node>> second_level;
second_level.push_back(node_one);
second_level.push_back(node_two);
auto root = profiler::CreateNodeDirect(
builder,
"main",
"falco.cpp",
123,
750,
&second_level);
profiler::FinishNodeBuffer(builder, root);
SECTION("binary output has identifier")
{
REQUIRE(profiler::NodeBufferHasIdentifier(builder.GetBufferPointer()) == true);
}
SECTION("deserialization")
{
auto node = profiler::GetNode(builder.GetBufferPointer());
REQUIRE(node->cycles() == 750);
REQUIRE(node->line() == 123);
REQUIRE(node->func()->str() == "main");
REQUIRE(node->file()->str() == "falco.cpp");
REQUIRE(node->childs() != nullptr);
REQUIRE(node->childs()->size() == 2);
REQUIRE(node->childs()->Get(0) == flatbuffers::GetTemporaryPointer(builder, node_one));
REQUIRE(node->childs()->Get(1) == flatbuffers::GetTemporaryPointer(builder, node_two));
auto expect_one = node->childs()->Get(0);
REQUIRE(expect_one->cycles() == 500);
REQUIRE(expect_one->line() == 345);
REQUIRE(expect_one->func()->str() == "do_init");
REQUIRE(expect_one->file()->str() == "falco_engine.cpp");
REQUIRE(expect_one->childs() == nullptr);
auto expect_two = node->childs()->Get(1);
REQUIRE(expect_two->cycles() == 250);
REQUIRE(expect_two->line() == 678);
REQUIRE(expect_two->func()->str() == "do_match");
REQUIRE(expect_two->file()->str() == "ruleset.cpp");
REQUIRE(expect_two->childs() != nullptr);
REQUIRE(expect_two->childs()->size() == 1);
REQUIRE(expect_two->childs()->Get(0) == flatbuffers::GetTemporaryPointer(builder, node_two_one));
auto expect_two_one = expect_two->childs()->Get(0);
REQUIRE(expect_two_one->cycles() == 100);
REQUIRE(expect_two_one->line() == 690);
REQUIRE(expect_two_one->func()->str() == "do_match2");
REQUIRE(expect_two_one->file()->str() == "ruleset.cpp");
REQUIRE(expect_two_one->childs() == nullptr);
}
}
void profile_fake_root_launching_threads()
{
PROFILEME();
std::thread ta(aa_threaded);
std::this_thread::sleep_for(std::chrono::microseconds(1));
bb();
ta.join();
}
TEST_CASE("profiler multi threading", "[profiler]")
{
profiler::alloc_chunk();
REQUIRE(profiler::chunks.size() == 1);
profile_fake_root_launching_threads();
}

View File

@@ -69,8 +69,6 @@ target_include_directories(
falco
PUBLIC
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
"${HEDLEY_INCLUDE}"
"${PROJECT_SOURCE_DIR}/userspace/profiler"
"${PROJECT_SOURCE_DIR}/userspace/engine"
"${PROJECT_BINARY_DIR}/userspace/falco"
"${PROJECT_BINARY_DIR}/driver/src"
@@ -86,7 +84,6 @@ target_link_libraries(
falco
falco_engine
sinsp
falco_profiler
"${GPR_LIB}"
"${GRPC_LIB}"
"${GRPCPP_LIB}"

View File

@@ -45,7 +45,6 @@ limitations under the License.
#include "statsfilewriter.h"
#include "webserver.h"
#include "grpc_server.h"
#include "profiler.h"
#include "banned.h" // This raises a compilation error when certain functions are used
typedef function<void(sinsp* inspector)> open_t;
@@ -236,7 +235,6 @@ uint64_t do_inspect(falco_engine *engine,
bool all_events,
int &result)
{
PROFILEME();
uint64_t num_evts = 0;
int32_t rc;
sinsp_evt* ev;
@@ -1293,7 +1291,6 @@ exit:
//
int main(int argc, char **argv)
{
alloc_chunk();
int rc;
// g_restart will cause the falco loop to exit, but we

View File

@@ -1,19 +0,0 @@
#
# Copyright (C) 2020 The Falco Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
add_library(falco_profiler INTERFACE)
target_include_directories(falco_profiler INTERFACE "${HEDLEY_INCLUDE}" "${FLATBUFFER_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}")
flatbuffers_generate_c_headers(PROFILE "profile.fbs")
add_custom_target(flatbuffer_profiler DEPENDS ${PROFILE_OUTPUTS})

View File

@@ -1,14 +0,0 @@
namespace profiler;
file_identifier "FPRO";
file_extension "fpro";
table Node {
func:string;
file:string;
line:int;
cycles:uint64;
childs:[Node];
}
root_type Node;

View File

@@ -1,172 +0,0 @@
/*
Copyright (C) 2020 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <cstdint>
#include <thread>
#include <vector>
#include <mutex>
#include <memory>
#include <hedley.h>
namespace profiler
{
#define CHUNK_ELEMENTS 7
#define CHUNK_SIZE ((1 << 20) * CHUNK_ELEMENTS) // 20 MiB = 5242880 * sizeof(uint32_t)
#define LABEL_MASK 0x80000000 // Largest positive int32 + 1
struct cursor
{
uint32_t* current;
uint32_t* end;
};
struct chunk
{
uint32_t* begin;
uint32_t* end;
std::thread::id thread;
};
struct label
{
uint32_t label;
std::string file;
std::string func;
int line;
};
thread_local cursor c;
std::vector<label> labels;
std::vector<chunk> chunks;
size_t nchunks;
std::mutex mu;
HEDLEY_NEVER_INLINE void alloc_chunk()
{
auto d = new uint32_t[CHUNK_SIZE];
c.current = d;
c.end = d + CHUNK_SIZE;
mu.lock();
chunks.push_back({d, d + CHUNK_SIZE, std::this_thread::get_id()});
nchunks += 1;
mu.unlock();
}
HEDLEY_NEVER_INLINE uint32_t create_label(char const* file, int line, char const* func)
{
label l;
l.label = labels.size() | LABEL_MASK;
l.file = file;
l.func = func;
l.line = line;
mu.lock();
labels.push_back(l);
mu.unlock();
return l.label;
}
struct profile
{
uint32_t* data;
int n;
int epochs; // (max) depth at the moment of execution
explicit profile(uint32_t label)
{
data = c.current;
auto next = data + CHUNK_ELEMENTS;
n = nchunks;
epochs = (next - chunks[n - 1].begin) / CHUNK_ELEMENTS; // (next - start) / data size
if(HEDLEY_LIKELY(next != c.end))
c.current = next; // adds 28 bytes
else
alloc_chunk(); // note: changes `c` values (current and end)
data[0] = label;
data[5] = 0; // unknown parent
data[6] = 0; // mark current instance as init
unsigned int lo, hi;
__asm__ __volatile__("rdtsc"
: "=a"(lo), "=d"(hi));
data[1] = hi;
data[2] = lo;
}
~profile()
{
unsigned int lo, hi;
__asm__ __volatile__("rdtsc"
: "=a"(lo), "=d"(hi));
data[3] = hi;
data[4] = lo;
if(HEDLEY_LIKELY(epochs > 1))
{
for(int i = 0; i < epochs - 1; i++)
{
// Check whether the i-th destructor before this has been called (>0) or not (0)
if(data[-1 - (i * CHUNK_ELEMENTS)] == 0)
{
// The head of the first destructor which has not been called yet is the parent of the current one
data[5] = data[-((i + 1) * CHUNK_ELEMENTS)];
break;
}
}
}
else if(n > 1)
{
// TODO: make it span across more chunks (until n - 2 == 0)
uint32_t* cdata = chunks[n - 2].end;
for(int i = 0; i < (CHUNK_SIZE / CHUNK_ELEMENTS); i++)
{
if(cdata[-1 - (i * CHUNK_ELEMENTS)] == 0)
{
data[5] = cdata[-((i + 1) * CHUNK_ELEMENTS)];
break;
}
}
}
if(n > 1 && data[5] == 0)
{
// TODO: same as above
// TODO: make it span across more chunks (until n - 2 == 0)
uint32_t* cdata = chunks[n - 2].end;
for(int i = 0; i < (CHUNK_SIZE / CHUNK_ELEMENTS); i++)
{
if(cdata[-1 - (i * CHUNK_ELEMENTS)] == 0)
{
data[5] = cdata[-((i + 1) * CHUNK_ELEMENTS)];
break;
}
}
}
data[6] = n; // mark current instance as done storing the chunk index (+ 1)
}
};
#define PROFILE_VARIABLE_IMPL(arg1, arg2) arg1##arg2
#define PROFILE_VARIABLE(arg1, arg2) PROFILE_VARIABLE_IMPL(arg1, arg2)
#define PROFILEME() \
static uint32_t PROFILE_VARIABLE(_label, __LINE__) = profiler::create_label(__FILE__, __LINE__, __FUNCTION__); \
profiler::profile PROFILE_VARIABLE(_profile_, __LINE__)(PROFILE_VARIABLE(_label, __LINE__));
}; // namespace profiler