Compare commits

..

5 Commits

Author SHA1 Message Date
Lorenzo Fontana
1d9188a316 wip: pointer to pointer in hawk_engine rules_cb
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2020-11-04 19:06:41 +01:00
Leonardo Di Donato
5cc102545f wip
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-11-04 12:05:07 +00:00
Leonardo Di Donato
2801c62666 new(userspace/falco): destroy rules watcher when needed
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-10-29 11:33:12 +00:00
Leonardo Di Donato
c6cffc1f48 new(userspace): make hawk_watch_rules aware of the engine
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-10-29 10:58:28 +00:00
Lorenzo Fontana
4894c93d5e new(userspace): initial draft for libhawk
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <fontanalorenz@gmail.com>
2020-10-28 15:43:27 +01:00
53 changed files with 800 additions and 1286 deletions

View File

@@ -282,8 +282,6 @@ jobs:
- run:
name: Execute integration tests
command: /usr/bin/entrypoint test
- store_test_results:
path: /build/release/integration-tests-xunit
"tests/integration-static":
docker:
- image: falcosecurity/falco-tester:latest
@@ -299,8 +297,6 @@ jobs:
- run:
name: Execute integration tests
command: /usr/bin/entrypoint test
- store_test_results:
path: /build-static/release/integration-tests-xunit
"tests/driver-loader/integration":
machine:
image: ubuntu-1604:202004-01

20
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- cncf
- roadmap
- "help wanted"
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
Issues labeled "cncf", "roadmap" and "help wanted" will not be automatically closed.
Please refer to a maintainer to get such label added if you think this should be kept open.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@@ -1,67 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '28 10 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'cpp', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,13 +1,5 @@
# Change Log
## v0.26.2
Released on 2020-11-10
### Major Changes
* update: DRIVERS_REPO now defaults to https://download.falco.org/driver [[#1460](https://github.com/falcosecurity/falco/pull/1460)] - [@leodido](https://github.com/leodido)
## v0.26.1
Released on 2020-10-01

View File

@@ -60,7 +60,7 @@ if(MUSL_OPTIMIZED_BUILD)
set(MUSL_FLAGS "-static -Os")
endif()
set(CMAKE_COMMON_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
set(CMAKE_COMMON_FLAGS "-Wall -pg -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
if(BUILD_WARNINGS_AS_ERRORS)
set(CMAKE_SUPPRESSED_WARNINGS
@@ -83,7 +83,7 @@ include(GetFalcoVersion)
set(PACKAGE_NAME "falco")
set(PROBE_NAME "falco")
set(PROBE_DEVICE_NAME "falco")
set(DRIVERS_REPO "https://download.falco.org/driver")
set(DRIVERS_REPO "https://dl.bintray.com/falcosecurity/driver")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX
/usr
@@ -115,8 +115,20 @@ set(CURSES_NEED_NCURSES TRUE)
find_package(Curses REQUIRED)
message(STATUS "Found ncurses: include: ${CURSES_INCLUDE_DIR}, lib: ${CURSES_LIBRARIES}")
# b64
include(b64)
# libb64
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
message(STATUS "Using bundled b64 in '${B64_SRC}'")
set(B64_INCLUDE "${B64_SRC}/include")
set(B64_LIB "${B64_SRC}/src/libb64.a")
ExternalProject_Add(
b64
URL "https://github.com/libb64/libb64/archive/ce864b17ea0e24a91e77c7dd3eb2d1ac4175b3f0.tar.gz"
URL_HASH "SHA256=d07173e66f435e5c77dbf81bd9313f8d0e4a3b4edd4105a62f4f8132ba932811"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
INSTALL_COMMAND "")
# yaml-cpp
include(yaml-cpp)
@@ -130,16 +142,52 @@ if(NOT MINIMAL_BUILD)
endif()
# LuaJIT
include(luajit)
set(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
ExternalProject_Add(
luajit
URL "https://github.com/LuaJIT/LuaJIT/archive/v2.0.3.tar.gz"
URL_HASH "SHA256=8da3d984495a11ba1bce9a833ba60e18b532ca0641e7d90d97fafe85ff014baa"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
INSTALL_COMMAND "")
# Lpeg
include(lpeg)
set(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
message(STATUS "Using bundled lpeg in '${LPEG_SRC}'")
set(LPEG_DEPENDENCIES "")
list(APPEND LPEG_DEPENDENCIES "luajit")
ExternalProject_Add(
lpeg
DEPENDS ${LPEG_DEPENDENCIES}
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
INSTALL_COMMAND "")
# libyaml
include(libyaml)
# lyaml
include(lyaml)
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
ExternalProject_Add(
lyaml
DEPENDS luajit libyaml
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
INSTALL_COMMAND sh -c
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua")
# One TBB
set(TBB_SRC "${PROJECT_BINARY_DIR}/tbb-prefix/src/tbb")
@@ -172,7 +220,6 @@ if(NOT MINIMAL_BUILD)
COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/include
BUILD_IN_SOURCE 1
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
BUILD_BYPRODUCTS ${CIVETWEB_LIB}
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
endif()

View File

@@ -5,9 +5,7 @@
[![Build Status](https://img.shields.io/circleci/build/github/falcosecurity/falco/master?style=for-the-badge)](https://circleci.com/gh/falcosecurity/falco) [![CII Best Practices Summary](https://img.shields.io/cii/summary/2317?label=CCI%20Best%20Practices&style=for-the-badge)](https://bestpractices.coreinfrastructure.org/projects/2317) [![GitHub](https://img.shields.io/github/license/falcosecurity/falco?style=for-the-badge)](COPYING)
Want to talk? Join us on the [#falco](https://kubernetes.slack.com/archives/CMWH3EH32) channel in the [Kubernetes Slack](https://slack.k8s.io).
### Latest releases
#### Latest releases
Read the [change log](CHANGELOG.md).
@@ -41,7 +39,7 @@ If you would like to run Falco in **production** please adhere to the [official
Falco is designed to be extensible such that it can be built into cloud-native applications and infrastructure.
Falco has a [gRPC](https://falco.org/docs/grpc/) endpoint and an API defined in [protobuf](https://github.com/falcosecurity/falco/blob/master/userspace/falco/outputs.proto).
Falco has a [gRPC](https://falco.org/docs/grpc/) endpoint and an API defined in [protobuf](https://github.com/falcosecurity/falco/blob/update-readme/userspace/falco/outputs.proto).
The Falco Project supports various SDKs for this endpoint.
##### SDKs
@@ -65,7 +63,6 @@ For example, Falco can easily detect incidents including but not limited to:
- Unexpected read of a sensitive file, such as `/etc/shadow`.
- A non-device file is written to `/dev`.
- A standard system binary, such as `ls`, is making an outbound network connection.
- A privileged pod is started in a Kubernetes cluster.
### Documentation
@@ -75,13 +72,6 @@ The [Official Documentation](https://falco.org/docs/) is the best resource to le
To get involved with The Falco Project please visit [the community repository](https://github.com/falcosecurity/community) to find more.
How to reach out?
- Join the #falco channel on the [Kubernetes Slack](https://slack.k8s.io)
- [Join the Falco mailing list](https://lists.cncf.io/g/cncf-falco-dev)
- [Read the Falco documentation](https://falco.org/docs/)
### Contributing
See the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md).
@@ -104,4 +94,4 @@ Falco is licensed to you under the [Apache 2.0](./COPYING) open source license.
[3]: https://dl.bintray.com/falcosecurity/deb-dev/stable
[4]: https://dl.bintray.com/falcosecurity/deb/stable
[5]: https://dl.bintray.com/falcosecurity/bin-dev/x86_64
[6]: https://dl.bintray.com/falcosecurity/bin/x86_64
[6]: https://dl.bintray.com/falcosecurity/bin/x86_64

View File

@@ -30,15 +30,9 @@ if(NOT CPACK_GENERATOR)
endif()
message(STATUS "Using package generators: ${CPACK_GENERATOR}")
message(STATUS "Package architecture: ${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
endif()
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
endif()
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.falco.org")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA

View File

@@ -1,27 +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.
#
set(B64_SRC "${PROJECT_BINARY_DIR}/b64-prefix/src/b64")
message(STATUS "Using bundled b64 in '${B64_SRC}'")
set(B64_INCLUDE "${B64_SRC}/include")
set(B64_LIB "${B64_SRC}/src/libb64.a")
externalproject_add(
b64
URL "https://github.com/libb64/libb64/archive/ce864b17ea0e24a91e77c7dd3eb2d1ac4175b3f0.tar.gz"
URL_HASH "SHA256=d07173e66f435e5c77dbf81bd9313f8d0e4a3b4edd4105a62f4f8132ba932811"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${B64_LIB}
INSTALL_COMMAND ""
)

View File

@@ -115,7 +115,7 @@ else()
grpc
DEPENDS openssl
GIT_REPOSITORY https://github.com/grpc/grpc.git
GIT_TAG v1.32.0
GIT_TAG v1.31.1
GIT_SUBMODULES "third_party/protobuf third_party/zlib third_party/cares/cares third_party/abseil-cpp third_party/re2"
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${GRPC_LIB} ${GRPCPP_LIB}

View File

@@ -15,13 +15,12 @@ set(LIBYAML_SRC "${PROJECT_BINARY_DIR}/libyaml-prefix/src/libyaml")
set(LIBYAML_INSTALL_DIR "${LIBYAML_SRC}/target")
message(STATUS "Using bundled libyaml in '${LIBYAML_SRC}'")
set(LIBYAML_LIB "${LIBYAML_SRC}/src/.libs/libyaml.a")
externalproject_add(
libyaml
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${LIBYAML_LIB}
INSTALL_COMMAND ${CMD_MAKE} install
)
ExternalProject_Add(
libyaml
URL "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz"
URL_HASH "SHA256=c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4"
CONFIGURE_COMMAND ./configure --prefix=${LIBYAML_INSTALL_DIR} CFLAGS=-fPIC CPPFLAGS=-fPIC --enable-static=true --enable-shared=false
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
INSTALL_COMMAND ${CMD_MAKE} install)

View File

@@ -1,28 +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.
#
set(LPEG_SRC "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg")
set(LPEG_LIB "${PROJECT_BINARY_DIR}/lpeg-prefix/src/lpeg/build/lpeg.a")
message(STATUS "Using bundled lpeg in '${LPEG_SRC}'")
set(LPEG_DEPENDENCIES "")
list(APPEND LPEG_DEPENDENCIES "luajit")
ExternalProject_Add(
lpeg
DEPENDS ${LPEG_DEPENDENCIES}
URL "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz"
URL_HASH "SHA256=48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe"
BUILD_COMMAND LUA_INCLUDE=${LUAJIT_INCLUDE} "${PROJECT_SOURCE_DIR}/scripts/build-lpeg.sh" "${LPEG_SRC}/build"
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${LPEG_LIB}
CONFIGURE_COMMAND ""
INSTALL_COMMAND "")

View File

@@ -1,27 +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.
#
set(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
externalproject_add(
luajit
GIT_REPOSITORY "https://github.com/LuaJIT/LuaJIT"
GIT_TAG "1d8b747c161db457e032a023ebbff511f5de5ec2"
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${LUAJIT_LIB}
INSTALL_COMMAND ""
)

View File

@@ -1,28 +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.
#
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
externalproject_add(
lyaml
DEPENDS luajit libyaml
URL "https://github.com/gvvaughan/lyaml/archive/release-v6.0.tar.gz"
URL_HASH "SHA256=9d7cf74d776999ff6f758c569d5202ff5da1f303c6f4229d3b41f71cd3a3e7a7"
BUILD_COMMAND ${CMD_MAKE}
BUILD_IN_SOURCE 1
BUILD_BYPRODUCTS ${LYAML_LIB}
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
INSTALL_COMMAND sh -c
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua"
)

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
@@ -25,4 +25,4 @@ ExternalProject_Add(
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch && patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/luajit.patch)
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch)

View File

@@ -1,8 +1,8 @@
diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c
index 6f51588e..5f9ea84e 100644
index e9faea51..a1b3b501 100644
--- a/userspace/libscap/scap.c
+++ b/userspace/libscap/scap.c
@@ -55,7 +55,7 @@ limitations under the License.
@@ -52,7 +52,7 @@ limitations under the License.
//#define NDEBUG
#include <assert.h>
@@ -11,16 +11,7 @@ index 6f51588e..5f9ea84e 100644
//
// Probe version string size
@@ -114,7 +114,7 @@ scap_t* scap_open_udig_int(char *error, int32_t *rc,
static uint32_t get_max_consumers()
{
uint32_t max;
- FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers", "r");
+ FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers", "r");
if(pfile != NULL)
{
int w = fscanf(pfile, "%"PRIu32, &max);
@@ -186,7 +186,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
@@ -171,7 +171,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
return NULL;
}
@@ -29,27 +20,7 @@ index 6f51588e..5f9ea84e 100644
bpf_probe = buf;
}
}
@@ -344,7 +344,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
else if(errno == EBUSY)
{
uint32_t curr_max_consumers = get_max_consumers();
- snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
+ snprintf(error, SCAP_LASTERR_SIZE, "Too many Falco instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
}
else
{
@@ -579,8 +579,8 @@ scap_t* scap_open_udig_int(char *error, int32_t *rc,
//
// Map the ppm_ring_buffer_info that contains the buffer pointers
//
- if(udig_alloc_ring_descriptors(&(handle->m_devs[0].m_bufinfo_fd),
- &handle->m_devs[0].m_bufinfo,
+ if(udig_alloc_ring_descriptors(&(handle->m_devs[0].m_bufinfo_fd),
+ &handle->m_devs[0].m_bufinfo,
&handle->m_devs[0].m_bufstatus,
error) != SCAP_SUCCESS)
{
@@ -2175,7 +2175,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
@@ -1808,7 +1808,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
const char* scap_get_host_root()
{

View File

@@ -1,57 +0,0 @@
diff --git a/userspace/libsinsp/chisel.cpp b/userspace/libsinsp/chisel.cpp
index 0a6e3cf8..0c2e255a 100644
--- a/userspace/libsinsp/chisel.cpp
+++ b/userspace/libsinsp/chisel.cpp
@@ -98,7 +98,7 @@ void lua_stackdump(lua_State *L)
// Lua callbacks
///////////////////////////////////////////////////////////////////////////////
#ifdef HAS_LUA_CHISELS
-const static struct luaL_reg ll_sysdig [] =
+const static struct luaL_Reg ll_sysdig [] =
{
{"set_filter", &lua_cbacks::set_global_filter},
{"set_snaplen", &lua_cbacks::set_snaplen},
@@ -134,7 +134,7 @@ const static struct luaL_reg ll_sysdig [] =
{NULL,NULL}
};
-const static struct luaL_reg ll_chisel [] =
+const static struct luaL_Reg ll_chisel [] =
{
{"request_field", &lua_cbacks::request_field},
{"set_filter", &lua_cbacks::set_filter},
@@ -146,7 +146,7 @@ const static struct luaL_reg ll_chisel [] =
{NULL,NULL}
};
-const static struct luaL_reg ll_evt [] =
+const static struct luaL_Reg ll_evt [] =
{
{"field", &lua_cbacks::field},
{"get_num", &lua_cbacks::get_num},
diff --git a/userspace/libsinsp/lua_parser.cpp b/userspace/libsinsp/lua_parser.cpp
index 0e26617d..78810d96 100644
--- a/userspace/libsinsp/lua_parser.cpp
+++ b/userspace/libsinsp/lua_parser.cpp
@@ -32,7 +32,7 @@ extern "C" {
#include "lauxlib.h"
}
-const static struct luaL_reg ll_filter [] =
+const static struct luaL_Reg ll_filter [] =
{
{"rel_expr", &lua_parser_cbacks::rel_expr},
{"bool_op", &lua_parser_cbacks::bool_op},
diff --git a/userspace/libsinsp/lua_parser_api.cpp b/userspace/libsinsp/lua_parser_api.cpp
index c89e9126..c3d8008a 100644
--- a/userspace/libsinsp/lua_parser_api.cpp
+++ b/userspace/libsinsp/lua_parser_api.cpp
@@ -266,7 +266,7 @@ int lua_parser_cbacks::rel_expr(lua_State *ls)
string err = "Got non-table as in-expression operand\n";
throw sinsp_exception("parser API error");
}
- int n = luaL_getn(ls, 4); /* get size of table */
+ int n = lua_objlen (ls, 4); /* get size of table */
for (i=1; i<=n; i++)
{
lua_rawgeti(ls, 4, i);

View File

@@ -29,8 +29,8 @@ file(MAKE_DIRECTORY ${SYSDIG_CMAKE_WORKING_DIR})
# default below In case you want to test against another sysdig version just pass the variable - ie., `cmake
# -DSYSDIG_VERSION=dev ..`
if(NOT SYSDIG_VERSION)
set(SYSDIG_VERSION "5c0b863ddade7a45568c0ac97d037422c9efb750")
set(SYSDIG_CHECKSUM "SHA256=9de717b3a4b611ea6df56afee05171860167112f74bb7717b394bcc88ac843cd")
set(SYSDIG_VERSION "2aa88dcf6243982697811df4c1b484bcbe9488a2")
set(SYSDIG_CHECKSUM "SHA256=a737077543a6f3473ab306b424bcf7385d788149829ed1538252661b0f20d0f6")
endif()
set(PROBE_VERSION "${SYSDIG_VERSION}")
@@ -57,7 +57,6 @@ add_subdirectory("${SYSDIG_SOURCE_DIR}/driver" "${PROJECT_BINARY_DIR}/driver")
# Add libscap directory
add_definitions(-D_GNU_SOURCE)
add_definitions(-DHAS_CAPTURE)
add_definitions(-DNOCURSESUI)
if(MUSL_OPTIMIZED_BUILD)
add_definitions(-DMUSL_OPTIMIZED)
endif()

View File

@@ -3,7 +3,7 @@ FROM falcosecurity/falco:${FALCO_IMAGE_TAG}
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
LABEL usage="docker run -i -t --privileged -v /root/.falco:/root/.falco -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 --name NAME IMAGE"
LABEL usage="docker run -i -t -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"
ENV HOST_ROOT /host
ENV HOME /root

View File

@@ -2,7 +2,7 @@ FROM debian:stable
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
LABEL usage="docker run -i -t --privileged -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 -v /etc:/host/etc --name NAME IMAGE"
LABEL usage="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

View File

@@ -1,5 +1,7 @@
FROM ubuntu:18.04 as ubuntu
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG FALCO_VERSION
ARG VERSION_BUCKET=bin
@@ -20,14 +22,6 @@ RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /falco/
FROM scratch
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro --name NAME IMAGE"
# NOTE: for the "least privileged" use case, please refer to the official documentation
ENV HOST_ROOT /host
ENV HOME /root
COPY --from=ubuntu /falco /
CMD ["/usr/bin/falco", "-o", "time_format_iso_8601=true"]

View File

@@ -28,10 +28,7 @@
# The files will be read in the order presented here, so make sure if
# you have overrides they appear in later files.
rules_file:
- /etc/falco/falco_rules.yaml
- /etc/falco/falco_rules.local.yaml
- /etc/falco/k8s_audit_rules.yaml
- /etc/falco/rules.d
- /tmp/falco
# If true, the times displayed in log messages and output messages
# will be in ISO 8601. By default, times are displayed in the local
@@ -87,23 +84,6 @@ syscall_event_drops:
rate: .03333
max_burst: 10
# Falco continuously monitors outputs performance. When an output channel does not allow
# to deliver an alert within a given deadline, an error is reported indicating
# which output is blocking notifications.
# The timeout error will be reported to the log according to the above log_* settings.
# Note that the notification will not be discarded from the output queue; thus,
# output channels may indefinitely remain blocked.
# An output timeout error indeed indicate a misconfiguration issue or I/O problems
# that cannot be recovered by Falco and should be fixed by the user.
#
# The "output_timeout" value specifies the duration in milliseconds to wait before
# considering the deadline exceed.
#
# With a 2000ms default, the notification consumer can block the Falco output
# for up to 2 seconds without reaching the timeout.
output_timeout: 2000
# A throttling mechanism implemented as a token bucket limits the
# rate of falco notifications. This throttling is controlled by the following configuration
# options:

View File

@@ -1,9 +1,5 @@
# Falco Drivers Storage S3
Supersedes: [20200818-artifacts-storage.md#drivers](20200818-artifacts-storage.md#drivers)
Supersedes: [20200901-artifacts-cleanup.md#drivers](20200901-artifacts-cleanup.md#drivers)
## Introduction
In the past days, as many people probably noticed, Bintray started rate-limiting our users, effectively preventing them from downloading any kernel module, rpm/deb package or any pre-built dependency we host there.
@@ -45,7 +41,7 @@ Before today, we had many issues with storage even without the spike in users we
## Context on AWS
Amazon AWS, recently gave credits to the Falco project to operate some parts of the infrastructure on AWS. The CNCF is providing a sub-account we are already using for the migration of the other pieces (like Prow).
Amazon AWS, recently gave credits to the Falco project to operate some parts of the infrastructure on AWS. The CNCF is providing a sub-account we are already using for the migration of the other pieces (like Prow).
## Interactions with other teams and the CNCF
@@ -59,7 +55,7 @@ We want to propose to move the drivers and the container dependencies to S3.
#### Moving means:
* We create a public S3 bucket with [stats enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html)
* We create a public S3 bucket with[ stats enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html)
* We attach the bucket to a cloudfront distribution behind the download.falco.org subdomain
@@ -117,7 +113,7 @@ export DRIVERS_REPO=https://your-url-here
Pass it as environment variable using the docker run flag -e - for example:
docker run -e DRIVERS_REPO=[https://your-url-here](https://your-url-here)
docker run -e DRIVERS_REPO=[https://your-url-here](https://your-url-here)
**Kubernetes**

View File

@@ -1213,9 +1213,6 @@
fd.name startswith /etc/ssh/ssh_monitor_config_ or
fd.name startswith /etc/ssh/ssh_config_))
- macro: multipath_writing_conf
condition: (proc.name = multipath and fd.name startswith /etc/multipath/)
# Add conditions to this macro (probably in a separate file,
# overwriting this macro) to allow for specific combinations of
# programs writing below specific directories below
@@ -1336,7 +1333,6 @@
and not automount_using_mtab
and not mcafee_writing_cma_d
and not avinetworks_supervisor_writing_ssh
and not multipath_writing_conf
- rule: Write below etc
desc: an attempt to write to any file below /etc
@@ -1870,7 +1866,6 @@
- list: falco_privileged_images
items: [
docker.io/calico/node,
calico/node,
docker.io/cloudnativelabs/kube-router,
docker.io/docker/ucp-agent,
docker.io/falcosecurity/falco,
@@ -2319,9 +2314,6 @@
- macro: user_known_user_management_activities
condition: (never_true)
- macro: chage_list
condition: (proc.name=chage and (proc.cmdline contains "-l" or proc.cmdline contains "--list"))
- rule: User mgmt binaries
desc: >
activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded.
@@ -2340,7 +2332,6 @@
not run_by_yum and
not run_by_ms_oms and
not run_by_google_accounts_daemon and
not chage_list and
not user_known_user_management_activities
output: >
User management binary command run outside of container
@@ -2434,9 +2425,9 @@
- rule: Contact K8S API Server From Container
desc: Detect attempts to contact the K8S API Server from a container
condition: >
evt.type=connect and evt.dir=< and
evt.type=connect and evt.dir=< and
(fd.typechar=4 or fd.typechar=6) and
container and
container and
not k8s_containers and
k8s_api_server and
not user_known_contact_k8s_api_server_activities
@@ -2656,7 +2647,7 @@
- rule: Delete or rename shell history
desc: Detect shell history deletion
condition: >
(modify_shell_history or truncate_shell_history) and
(modify_shell_history or truncate_shell_history) and
not var_lib_docker_filepath and
not proc.name in (docker_binaries)
output: >
@@ -2872,22 +2863,12 @@
- list: k8s_client_binaries
items: [docker, kubectl, crictl]
- list: user_known_k8s_ns_kube_system_images
items: [
k8s.gcr.io/fluentd-gcp-scaler,
k8s.gcr.io/node-problem-detector/node-problem-detector
]
- list: user_known_k8s_images
items: [
mcr.microsoft.com/aks/hcp/hcp-tunnel-front
]
# Whitelist for known docker client binaries run inside container
# - k8s.gcr.io/fluentd-gcp-scaler in GCP/GKE
- macro: user_known_k8s_client_container
condition: >
(k8s.ns.name="kube-system" and container.image.repository in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images)
(k8s.ns.name="kube-system" and container.image.repository=k8s.gcr.io/fluentd-gcp-scaler) or
container.image.repository=mcr.microsoft.com/aks/hcp/hcp-tunnel-front
- macro: user_known_k8s_client_container_parens
condition: (user_known_k8s_client_container)
@@ -2900,7 +2881,7 @@
tags: [container, mitre_execution]
# This rule is enabled by default.
# This rule is enabled by default.
# If you want to disable it, modify the following macro.
- macro: consider_packet_socket_communication
condition: (always_true)
@@ -3060,16 +3041,6 @@
priority: WARNING
tags: [network]
- list: white_listed_modules
items: []
- rule: Linux Kernel Module Injection Detected
desc: Detect kernel module was injected (from container).
condition: spawned_process and container and proc.name=insmod and not proc.args in (white_listed_modules)
output: Linux Kernel Module injection using insmod detected (user=%user.name user_loginuid=%user.loginuid parent_process=%proc.pname module=%proc.args)
priority: WARNING
tags: [process]
# Application rules have moved to application_rules.yaml. Please look
# there if you want to enable them by adding to
# falco_rules.local.yaml.

View File

@@ -537,7 +537,7 @@
condition: >
kevt
and non_system_user
and ka.user.name in (full_admin_k8s_users)
and ka.user.name in (admin_k8s_users)
and not allowed_full_admin_users
output: K8s Operation performed by full admin user (user=%ka.user.name target=%ka.target.name/%ka.target.resource verb=%ka.verb uri=%ka.uri resp=%ka.response.code)
priority: WARNING

View File

@@ -220,7 +220,7 @@ load_kernel_module() {
rmmod "${DRIVER_NAME}" 2>/dev/null
WAIT_TIME=0
KMOD_NAME=$(echo "${DRIVER_NAME}" | tr "-" "_")
while lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
while lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1 && [ $WAIT_TIME -lt "${MAX_RMMOD_WAIT}" ]; do
if rmmod "${DRIVER_NAME}" 2>/dev/null; then
echo "* Unloading ${DRIVER_NAME} module succeeded after ${WAIT_TIME}s"
break
@@ -232,7 +232,7 @@ load_kernel_module() {
sleep 1
done
if lsmod | cut -d' ' -f1 | grep -qx "${KMOD_NAME}" > /dev/null 2>&1; then
if lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
echo "* ${DRIVER_NAME} module seems to still be loaded, hoping the best"
exit 0
fi

View File

@@ -104,12 +104,8 @@ function run_tests() {
suites+=($SCRIPTDIR/falco_tests_package.yaml)
fi
XUNIT_DIR="${OPT_BUILD_DIR}/integration-tests-xunit"
mkdir -p "${XUNIT_DIR}"
for mult in "${suites[@]}"; do
XUNIT_FILE_NAME="${XUNIT_DIR}/$(basename "${mult}").xml"
CMD="avocado run --xunit ${XUNIT_FILE_NAME} --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
CMD="avocado run --mux-yaml $mult --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
echo "Running $CMD"
BUILD_DIR=${OPT_BUILD_DIR} $CMD
RC=$?

View File

@@ -38,7 +38,8 @@ if(MINIMAL_BUILD)
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
"${PROJECT_BINARY_DIR}/userspace/engine")
"${PROJECT_BINARY_DIR}/userspace/engine"
"${PROJECT_SOURCE_DIR}/userspace/libhawk")
else()
target_include_directories(
falco_engine
@@ -51,11 +52,17 @@ else()
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
"${PROJECT_BINARY_DIR}/userspace/engine")
"${PROJECT_BINARY_DIR}/userspace/engine"
"${PROJECT_SOURCE_DIR}/userspace/libhawk")
endif()
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
if(DEFINED LIBHAWK_LIBRARIES)
message(STATUS "Using externally provided libhawk implementations: ${LIBHAWK_LIBRARIES}")
target_link_libraries(falco_engine ${LIBHAWK_LIBRARIES})
endif()
configure_file(config_falco_engine.h.in config_falco_engine.h)
if(DEFINED FALCO_COMPONENT)

View File

@@ -26,7 +26,8 @@ limitations under the License.
#include "formats.h"
extern "C" {
extern "C"
{
#include "lpeg.h"
#include "lyaml.h"
}
@@ -34,7 +35,6 @@ extern "C" {
#include "utils.h"
#include "banned.h" // This raises a compilation error when certain functions are used
string lua_on_event = "on_event";
string lua_print_stats = "print_stats";
@@ -42,24 +42,24 @@ using namespace std;
nlohmann::json::json_pointer falco_engine::k8s_audit_time = "/stageTimestamp"_json_pointer;
falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
: m_rules(NULL), m_next_ruleset_id(0),
m_min_priority(falco_common::PRIORITY_DEBUG),
m_sampling_ratio(1), m_sampling_multiplier(0),
m_replace_container_info(false)
falco_engine::falco_engine(bool seed_rng, const std::string &alternate_lua_dir):
m_rules(NULL), m_next_ruleset_id(0),
m_min_priority(falco_common::PRIORITY_DEBUG),
m_sampling_ratio(1), m_sampling_multiplier(0),
m_replace_container_info(false)
{
luaopen_lpeg(m_ls);
luaopen_yaml(m_ls);
m_alternate_lua_dir = alternate_lua_dir;
falco_common::init(m_lua_main_filename.c_str(), alternate_lua_dir.c_str());
falco_rules::init(m_ls);
m_sinsp_rules.reset(new falco_sinsp_ruleset());
m_k8s_audit_rules.reset(new falco_ruleset());
clear_filters();
if(seed_rng)
{
srandom((unsigned) getpid());
srandom((unsigned)getpid());
}
m_default_ruleset_id = find_ruleset_id(m_default_ruleset);
@@ -70,15 +70,24 @@ falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
falco_engine::~falco_engine()
{
if (m_rules)
if(m_rules)
{
delete m_rules;
}
}
falco_engine *falco_engine::clone()
{
auto engine = new falco_engine(true, m_alternate_lua_dir);
engine->set_inspector(m_inspector);
engine->set_extra(m_extra, m_replace_container_info);
engine->set_min_priority(m_min_priority);
return engine;
}
uint32_t falco_engine::engine_version()
{
return (uint32_t) FALCO_ENGINE_VERSION;
return (uint32_t)FALCO_ENGINE_VERSION;
}
#define DESCRIPTION_TEXT_START 16
@@ -144,17 +153,28 @@ void falco_engine::list_fields(bool names_only)
}
}
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
{
uint64_t dummy;
ifstream is;
return load_rules(rules_content, verbose, all_events, dummy);
is.open(rules_filename);
if(!is.is_open())
{
throw falco_exception("Could not open rules filename " +
rules_filename + " " +
"for reading");
}
string rules_content((istreambuf_iterator<char>(is)),
istreambuf_iterator<char>());
load_rules(rules_content, verbose, all_events);
}
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version)
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
{
// The engine must have been given an inspector by now.
if(! m_inspector)
if(!m_inspector)
{
throw falco_exception("No inspector provided");
}
@@ -166,45 +186,52 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
if(!m_rules)
{
m_rules = new falco_rules(m_inspector,
this,
m_ls);
// Note that falco_formats is added to the lua state used by the falco engine only.
// Within the engine, only formats.
// Formatter is used, so we can unconditionally set json_output to false.
bool json_output = false;
bool json_include_output_property = false;
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
m_rules = new falco_rules(m_inspector, this, m_ls);
}
// Note that falco_formats is added to the lua state used
// by the falco engine only. Within the engine, only
// formats.formatter is used, so we can unconditionally set
// json_output to false.
bool json_output = false;
bool json_include_output_property = false;
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version);
}
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
{
uint64_t dummy;
// m_sinsp_rules.reset(new falco_sinsp_ruleset());
// m_k8s_audit_rules.reset(new falco_ruleset());
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, dummy);
return load_rules_file(rules_filename, verbose, all_events, dummy);
m_is_ready = true;
return;
//
// auto local_rules = new falco_rules(m_inspector, this, m_ls);
// try
// {
// uint64_t dummy;
// local_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, dummy);
// // m_rules = local_rules
// // std::atomic<falco_rules *> lore(m_rules);
// // std::atomic_exchange(&lore, local_rules);
// // SCHEDULE LOCAL_RULES AS NEXT RULESET
// }
// catch(const falco_exception &e)
// {
// // todo
// printf("IGNORE BECAUSE OF ERROR LOADING RULESET!\n");
// }
}
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version)
// // todo(fntlnz): not sure we want this in falco_engine
// void falco_engine::watch_rules(bool verbose, bool all_events)
// {
// hawk_watch_rules((hawk_watch_rules_cb)rules_cb, reinterpret_cast<hawk_engine *>(this));
// }
bool falco_engine::is_ready()
{
ifstream is;
is.open(rules_filename);
if (!is.is_open())
{
throw falco_exception("Could not open rules filename " +
rules_filename + " " +
"for reading");
}
string rules_content((istreambuf_iterator<char>(is)),
istreambuf_iterator<char>());
load_rules(rules_content, verbose, all_events, required_engine_version);
return m_is_ready;
}
void falco_engine::enable_rule(const string &substring, bool enabled, const string &ruleset)
@@ -272,7 +299,7 @@ uint64_t falco_engine::num_rules_for_ruleset(const std::string &ruleset)
uint16_t ruleset_id = find_ruleset_id(ruleset);
return m_sinsp_rules->num_rules_for_ruleset(ruleset_id) +
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
}
void falco_engine::evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset)
@@ -311,15 +338,15 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
if(lua_pcall(m_ls, 1, 3, 0) != 0)
{
const char* lerr = lua_tostring(m_ls, -1);
const char *lerr = lua_tostring(m_ls, -1);
string err = "Error invoking function output: " + string(lerr);
throw falco_exception(err);
}
res->evt = ev;
const char *p = lua_tostring(m_ls, -3);
const char *p = lua_tostring(m_ls, -3);
res->rule = p;
res->source = "syscall";
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
res->priority_num = (falco_common::priority_type)lua_tonumber(m_ls, -2);
res->format = lua_tostring(m_ls, -1);
lua_pop(m_ls, 3);
}
@@ -333,6 +360,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_evt *ev)
{
// todo(leodido, fntlnz) > pass the last ruleset id
return process_sinsp_event(ev, m_default_ruleset_id);
}
@@ -344,7 +372,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json
}
// All k8s audit events have the single tag "1".
if(!m_k8s_audit_rules->run((gen_event *) ev, 1, ruleset_id))
if(!m_k8s_audit_rules->run((gen_event *)ev, 1, ruleset_id))
{
return unique_ptr<struct rule_result>();
}
@@ -359,15 +387,15 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json
if(lua_pcall(m_ls, 1, 3, 0) != 0)
{
const char* lerr = lua_tostring(m_ls, -1);
const char *lerr = lua_tostring(m_ls, -1);
string err = "Error invoking function output: " + string(lerr);
throw falco_exception(err);
}
res->evt = ev;
const char *p = lua_tostring(m_ls, -3);
const char *p = lua_tostring(m_ls, -3);
res->rule = p;
res->source = "k8s_audit";
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
res->priority_num = (falco_common::priority_type)lua_tonumber(m_ls, -2);
res->format = lua_tostring(m_ls, -1);
lua_pop(m_ls, 3);
}
@@ -393,7 +421,7 @@ bool falco_engine::parse_k8s_audit_json(nlohmann::json &j, std::list<json_event>
{
// Note we only handle a single top level array, to
// avoid excessive recursion.
if(! parse_k8s_audit_json(item, evts, false))
if(!parse_k8s_audit_json(item, evts, false))
{
return false;
}
@@ -471,7 +499,7 @@ void falco_engine::print_stats()
{
if(lua_pcall(m_ls, 0, 0, 0) != 0)
{
const char* lerr = lua_tostring(m_ls, -1);
const char *lerr = lua_tostring(m_ls, -1);
string err = "Error invoking function print_stats: " + string(lerr);
throw falco_exception(err);
}
@@ -480,21 +508,20 @@ void falco_engine::print_stats()
{
throw falco_exception("No function " + lua_print_stats + " found in lua rule loader module");
}
}
void falco_engine::add_sinsp_filter(string &rule,
set<uint32_t> &evttypes,
set<uint32_t> &syscalls,
set<string> &tags,
sinsp_filter* filter)
sinsp_filter *filter)
{
m_sinsp_rules->add(rule, evttypes, syscalls, tags, filter);
}
void falco_engine::add_k8s_audit_filter(string &rule,
set<string> &tags,
json_event_filter* filter)
json_event_filter *filter)
{
// All k8s audit events have a single tag "1".
std::set<uint32_t> event_tags = {1};
@@ -536,8 +563,8 @@ inline bool falco_engine::should_drop_evt()
return false;
}
double coin = (random() * (1.0/RAND_MAX));
return (coin >= (1.0/(m_sampling_multiplier * m_sampling_ratio)));
double coin = (random() * (1.0 / RAND_MAX));
return (coin >= (1.0 / (m_sampling_multiplier * m_sampling_ratio)));
}
sinsp_filter_factory &falco_engine::sinsp_factory()

View File

@@ -38,6 +38,11 @@ limitations under the License.
#include "config_falco_engine.h"
#include "falco_common.h"
extern "C"
{
#include "hawk.h"
}
//
// This class acts as the primary interface between a program and the
// falco rules engine. Falco outputs (writing to files/syslog/etc) are
@@ -47,9 +52,12 @@ limitations under the License.
class falco_engine : public falco_common
{
public:
falco_engine(bool seed_rng=true, const std::string& alternate_lua_dir=FALCO_ENGINE_SOURCE_LUA_DIR);
falco_engine(bool seed_rng = true, const std::string &alternate_lua_dir = FALCO_ENGINE_SOURCE_LUA_DIR);
virtual ~falco_engine();
falco_engine(const falco_engine &rhs);
falco_engine *clone();
// A given engine has a version which identifies the fields
// and rules file format it supports. This version will change
// any time the code that handles rules files, expression
@@ -57,7 +65,7 @@ public:
static uint32_t engine_version();
// Print to stdout (using printf) a description of each field supported by this engine.
void list_fields(bool names_only=false);
void list_fields(bool names_only = false);
//
// Load rules either directly or from a filename.
@@ -65,12 +73,8 @@ public:
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events);
void load_rules(const std::string &rules_content, bool verbose, bool all_events);
//
// Identical to above, but also returns the required engine version for the file/content.
// (If no required engine version is specified, returns 0).
//
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version);
void load_rules(const std::string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version);
// Watch and live-reload rules using an external ABI interface provided by libhawk
void watch_rules(bool verbose, bool all_events);
//
// Enable/Disable any rules matching the provided substring.
@@ -85,7 +89,6 @@ public:
// Wrapper that assumes the default ruleset
void enable_rule(const std::string &substring, bool enabled);
// Like enable_rule, but the rule name must be an exact match.
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset);
@@ -154,7 +157,8 @@ public:
// **Methods Related to k8s audit log events, which are
// **represented as json objects.
struct rule_result {
struct rule_result
{
gen_event *evt;
std::string rule;
std::string source;
@@ -170,7 +174,7 @@ public:
// Returns true if the json object was recognized as a k8s
// audit event(s), false otherwise.
//
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top = true);
//
// Given an event, check it against the set of rules in the
@@ -195,7 +199,7 @@ public:
//
void add_k8s_audit_filter(std::string &rule,
std::set<std::string> &tags,
json_event_filter* filter);
json_event_filter *filter);
// **Methods Related to Sinsp Events e.g system calls
//
@@ -236,13 +240,14 @@ public:
std::set<uint32_t> &evttypes,
std::set<uint32_t> &syscalls,
std::set<std::string> &tags,
sinsp_filter* filter);
sinsp_filter *filter);
sinsp_filter_factory &sinsp_factory();
json_event_filter_factory &json_factory();
private:
bool is_ready();
private:
static nlohmann::json::json_pointer k8s_audit_time;
//
@@ -262,6 +267,8 @@ private:
std::unique_ptr<falco_sinsp_ruleset> m_sinsp_rules;
std::unique_ptr<falco_ruleset> m_k8s_audit_rules;
std::string m_alternate_lua_dir;
//
// Here's how the sampling ratio and multiplier influence
// whether or not an event is dropped in
@@ -291,5 +298,6 @@ private:
std::string m_extra;
bool m_replace_container_info;
};
bool m_is_ready = false;
};

View File

@@ -26,7 +26,7 @@ bool falco_formats::s_json_output = false;
bool falco_formats::s_json_include_output_property = true;
std::unique_ptr<sinsp_evt_formatter_cache> falco_formats::s_formatters = NULL;
const static struct luaL_Reg ll_falco[] =
const static struct luaL_reg ll_falco[] =
{
{"formatter", &falco_formats::lua_formatter},
{"free_formatter", &falco_formats::lua_free_formatter},

View File

@@ -26,14 +26,15 @@ extern "C" {
#include "falco_engine.h"
#include "banned.h" // This raises a compilation error when certain functions are used
const static struct luaL_Reg ll_falco_rules[] =
{
{"clear_filters", &falco_rules::clear_filters},
{"add_filter", &falco_rules::add_filter},
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
{"enable_rule", &falco_rules::enable_rule},
{"engine_version", &falco_rules::engine_version},
{NULL, NULL}};
const static struct luaL_reg ll_falco_rules [] =
{
{"clear_filters", &falco_rules::clear_filters},
{"add_filter", &falco_rules::add_filter},
{"add_k8s_audit_filter", &falco_rules::add_k8s_audit_filter},
{"enable_rule", &falco_rules::enable_rule},
{"engine_version", &falco_rules::engine_version},
{NULL,NULL}
};
falco_rules::falco_rules(sinsp* inspector,
falco_engine *engine,

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
@@ -11,10 +11,39 @@
# specific language governing permissions and limitations under the License.
#
configure_file(config_falco.h.in config_falco.h)
configure_file("${SYSDIG_SOURCE_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
set(
FALCO_SOURCES
if(NOT MINIMAL_BUILD)
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
COMMENT "Generate gRPC API"
# Falco gRPC Version API
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
# Falco gRPC Outputs API
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(MINIMAL_BUILD)
add_executable(
falco
configuration.cpp
logger.cpp
falco_outputs.cpp
@@ -25,74 +54,84 @@ set(
event_drops.cpp
statsfilewriter.cpp
falco.cpp
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/fields_info.cpp"
)
set(
FALCO_INCLUDE_DIRECTORIES
"${PROJECT_SOURCE_DIR}/userspace/engine"
"${PROJECT_BINARY_DIR}/userspace/falco"
"${PROJECT_BINARY_DIR}/driver/src"
"${STRING_VIEW_LITE_INCLUDE}"
"${YAMLCPP_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include"
)
set(
FALCO_DEPENDENCIES
string-view-lite
libyaml
b64
luajit
lpeg
lyaml
)
set(
FALCO_LIBRARIES
falco_engine
sinsp
"${LIBYAML_LIB}"
"${YAMLCPP_LIB}"
)
if(USE_BUNDLED_DEPS)
list(APPEND FALCO_DEPENDENCIES yamlcpp)
endif()
if(NOT MINIMAL_BUILD)
list(
APPEND FALCO_SOURCES
"${SYSDIG_SOURCE_DIR}/userspace/sysdig/fields_info.cpp")
else()
add_executable(
falco
configuration.cpp
logger.cpp
falco_outputs.cpp
outputs_file.cpp
outputs_grpc.cpp
outputs_http.cpp
outputs_program.cpp
outputs_stdout.cpp
outputs_syslog.cpp
event_drops.cpp
statsfilewriter.cpp
falco.cpp
"${SYSDIG_SOURCE_DIR}/userspace/sysdig/fields_info.cpp"
webserver.cpp
grpc_context.cpp
grpc_server_impl.cpp
grpc_request_context.cpp
grpc_server.cpp
grpc_context.cpp
grpc_server_impl.cpp
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
)
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc)
list(
APPEND FALCO_INCLUDE_DIRECTORIES
"${CIVETWEB_INCLUDE_DIR}"
"${OPENSSL_INCLUDE_DIR}"
"${GRPC_INCLUDE}"
"${GRPCPP_INCLUDE}"
"${PROTOBUF_INCLUDE}"
)
add_dependencies(falco civetweb)
endif()
list(APPEND FALCO_DEPENDENCIES civetweb)
add_dependencies(falco string-view-lite)
list(
APPEND FALCO_LIBRARIES
if(USE_BUNDLED_DEPS)
add_dependencies(falco yamlcpp)
endif()
if(MINIMAL_BUILD)
target_include_directories(
falco
PUBLIC
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
"${PROJECT_SOURCE_DIR}/userspace/engine"
"${PROJECT_BINARY_DIR}/userspace/falco"
"${PROJECT_BINARY_DIR}/driver/src"
"${STRING_VIEW_LITE_INCLUDE}"
"${YAMLCPP_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include")
target_link_libraries(
falco
falco_engine
sinsp
"${LIBYAML_LIB}"
"${YAMLCPP_LIB}")
else()
target_include_directories(
falco
PUBLIC
"${SYSDIG_SOURCE_DIR}/userspace/sysdig"
"${PROJECT_SOURCE_DIR}/userspace/engine"
"${PROJECT_BINARY_DIR}/userspace/falco"
"${PROJECT_BINARY_DIR}/driver/src"
"${STRING_VIEW_LITE_INCLUDE}"
"${YAMLCPP_INCLUDE_DIR}"
"${CIVETWEB_INCLUDE_DIR}"
"${OPENSSL_INCLUDE_DIR}"
"${GRPC_INCLUDE}"
"${GRPCPP_INCLUDE}"
"${PROTOBUF_INCLUDE}"
"${CMAKE_CURRENT_BINARY_DIR}"
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include")
target_link_libraries(
falco
falco_engine
sinsp
"${GPR_LIB}"
"${GRPC_LIB}"
"${GRPCPP_LIB}"
@@ -101,66 +140,19 @@ if(NOT MINIMAL_BUILD)
"${OPENSSL_LIBRARY_CRYPTO}"
"${LIBYAML_LIB}"
"${YAMLCPP_LIB}"
"${CIVETWEB_LIB}"
)
"${CIVETWEB_LIB}")
endif()
add_executable(
falco
${FALCO_SOURCES}
)
add_dependencies(falco ${FALCO_DEPENDENCIES})
target_link_libraries(
falco
${FALCO_LIBRARIES}
)
target_include_directories(
falco
PUBLIC
${FALCO_INCLUDE_DIRECTORIES}
)
configure_file(config_falco.h.in config_falco.h)
if(NOT MINIMAL_BUILD)
add_custom_command(
TARGET falco
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields"
)
# add_custom_command(
# TARGET falco
# COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR}
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
# COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields")
else()
message(STATUS "Skipping engine fields checksum when building the minimal Falco.")
endif()
if(NOT MINIMAL_BUILD)
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
COMMENT "Generate gRPC API"
# Falco gRPC Version API
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
# Falco gRPC Outputs API
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
MESSAGE(STATUS "Skipping engine fields checksum when building the minimal Falco.")
endif()
# strip the Falco binary when releasing using musl
@@ -169,8 +161,7 @@ if(MUSL_OPTIMIZED_BUILD AND CMAKE_BUILD_TYPE STREQUAL "release")
TARGET falco
POST_BUILD
COMMAND ${CMAKE_STRIP} --strip-unneeded falco
COMMENT "Strip the Falco binary when releasing the musl build"
)
COMMENT "Strip the Falco binary when releasing the musl build")
endif()
install(TARGETS falco DESTINATION ${FALCO_BIN_DIR})

View File

@@ -68,16 +68,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_config->get_sequence<list<string>>(rules_files, string("rules_file"));
for(auto &file : rules_files)
{
// Here, we only include files that exist
struct stat buffer;
if(stat(file.c_str(), &buffer) == 0)
{
read_rules_file_directory(file, m_rules_filenames);
}
}
m_json_output = m_config->get_scalar<bool>("json_output", false);
m_json_include_output_property = m_config->get_scalar<bool>("json_include_output_property", true);
@@ -176,8 +166,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
falco_logger::set_level(m_log_level);
m_output_timeout = m_config->get_scalar<uint32_t>("output_timeout", 2000);
m_notifications_rate = m_config->get_scalar<uint32_t>("outputs", "rate", 1);
m_notifications_max_burst = m_config->get_scalar<uint32_t>("outputs", "max_burst", 1000);
@@ -244,69 +232,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
m_syscall_evt_simulate_drops = m_config->get_scalar<bool>("syscall_event_drops", "simulate_drops", false);
}
void falco_configuration::read_rules_file_directory(const string &path, list<string> &rules_filenames)
{
struct stat st;
int rc = stat(path.c_str(), &st);
if(rc != 0)
{
std::cerr << "Could not get info on rules file " << path << ": " << strerror(errno) << std::endl;
exit(-1);
}
if(st.st_mode & S_IFDIR)
{
// It's a directory. Read the contents, sort
// alphabetically, and add every path to
// rules_filenames
vector<string> dir_filenames;
DIR *dir = opendir(path.c_str());
if(!dir)
{
std::cerr << "Could not get read contents of directory " << path << ": " << strerror(errno) << std::endl;
exit(-1);
}
for(struct dirent *ent = readdir(dir); ent; ent = readdir(dir))
{
string efile = path + "/" + ent->d_name;
rc = stat(efile.c_str(), &st);
if(rc != 0)
{
std::cerr << "Could not get info on rules file " << efile << ": " << strerror(errno) << std::endl;
exit(-1);
}
if(st.st_mode & S_IFREG)
{
dir_filenames.push_back(efile);
}
}
closedir(dir);
std::sort(dir_filenames.begin(),
dir_filenames.end());
for(string &ent : dir_filenames)
{
rules_filenames.push_back(ent);
}
}
else
{
// Assume it's a file and just add to
// rules_filenames. If it can't be opened/etc that
// will be reported later..
rules_filenames.push_back(path);
}
}
static bool split(const string &str, char delim, pair<string, string> &parts)
{
@@ -348,4 +273,4 @@ void falco_configuration::set_cmdline_option(const string &opt)
{
m_config->set_scalar(keyval.first, keyval.second);
}
}
}

View File

@@ -190,9 +190,6 @@ public:
void init(std::string conf_filename, std::list<std::string>& cmdline_options);
void init(std::list<std::string>& cmdline_options);
static void read_rules_file_directory(const string& path, list<string>& rules_filenames);
std::list<std::string> m_rules_filenames;
bool m_json_output;
bool m_json_include_output_property;
std::string m_log_level;
@@ -204,7 +201,6 @@ public:
bool m_buffered_outputs;
bool m_time_format_iso_8601;
uint32_t m_output_timeout;
bool m_grpc_enabled;
uint32_t m_grpc_threadiness;

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,6 @@ limitations under the License.
#include "formats.h"
#include "logger.h"
#include "watchdog.h"
#include "outputs_file.h"
#include "outputs_program.h"
@@ -52,26 +51,18 @@ falco_outputs::~falco_outputs()
{
if(m_initialized)
{
this->stop_worker();
for(auto o : m_outputs)
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
delete o;
(*it)->cleanup();
}
}
}
void falco_outputs::init(bool json_output,
bool json_include_output_property,
uint32_t timeout,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, std::string hostname)
bool json_include_output_property,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, string hostname)
{
// Cannot be initialized more than one time.
if(m_initialized)
{
throw falco_exception("falco_outputs already initialized");
}
m_json_output = json_output;
// Note that falco_formats is already initialized by the engine,
@@ -80,29 +71,17 @@ void falco_outputs::init(bool json_output,
falco_formats::s_json_output = json_output;
falco_formats::s_json_include_output_property = json_include_output_property;
m_timeout = std::chrono::milliseconds(timeout);
m_notifications_tb.init(rate, max_burst);
m_buffered = buffered;
m_time_format_iso_8601 = time_format_iso_8601;
m_hostname = hostname;
m_worker_thread = std::thread(&falco_outputs::worker, this);
m_initialized = true;
}
// This function has to be called after init() since some configuration settings
// need to be passed to the output plugins. Then, although the worker has started,
// the worker is still on hold, waiting for a message.
// Thus it is still safe to call add_output() before any message has been enqueued.
void falco_outputs::add_output(falco::outputs::config oc)
{
if(!m_initialized)
{
throw falco_exception("cannot add output: falco_outputs not initialized yet");
}
falco::outputs::abstract_output *oo;
@@ -150,12 +129,6 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
return;
}
falco_outputs::ctrl_msg cmsg = {};
cmsg.ts = evt->get_ts();
cmsg.priority = priority;
cmsg.source = source;
cmsg.rule = rule;
string sformat;
if(source == "syscall")
{
@@ -190,38 +163,35 @@ void falco_outputs::handle_event(gen_event *evt, string &rule, string &source,
sformat += " " + format;
}
cmsg.msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
cmsg.fields = falco_formats::resolve_tokens(evt, source, sformat);
string msg;
msg = falco_formats::format_event(evt, rule, source, falco_common::priority_names[priority], sformat);
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
m_queue.push(cmsg);
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
(*it)->output_event(evt, rule, source, priority, sformat, msg);
}
}
void falco_outputs::handle_msg(uint64_t ts,
void falco_outputs::handle_msg(uint64_t now,
falco_common::priority_type priority,
std::string &msg,
std::string &rule,
std::map<std::string, std::string> &output_fields)
{
falco_outputs::ctrl_msg cmsg = {};
cmsg.ts = ts;
cmsg.priority = priority;
cmsg.source = "internal";
cmsg.rule = rule;
cmsg.fields = output_fields;
std::string full_msg;
if(m_json_output)
{
nlohmann::json jmsg;
// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
time_t evttime = ts / 1000000000;
time_t evttime = now / 1000000000;
char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
char time_ns[12]; // sizeof ".sssssssssZ"
string iso8601evttime;
strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
snprintf(time_ns, sizeof(time_ns), ".%09luZ", ts % 1000000000);
snprintf(time_ns, sizeof(time_ns), ".%09luZ", now % 1000000000);
iso8601evttime = time_sec;
iso8601evttime += time_ns;
@@ -231,15 +201,15 @@ void falco_outputs::handle_msg(uint64_t ts,
jmsg["time"] = iso8601evttime;
jmsg["output_fields"] = output_fields;
cmsg.msg = jmsg.dump();
full_msg = jmsg.dump();
}
else
{
std::string timestr;
bool first = true;
sinsp_utils::ts_to_string(ts, &timestr, false, true);
cmsg.msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
sinsp_utils::ts_to_string(now, &timestr, false, true);
full_msg = timestr + ": " + falco_common::priority_names[priority] + " " + msg + " (";
for(auto &pair : output_fields)
{
if(first)
@@ -248,95 +218,23 @@ void falco_outputs::handle_msg(uint64_t ts,
}
else
{
cmsg.msg += " ";
full_msg += " ";
}
cmsg.msg += pair.first + "=" + pair.second;
full_msg += pair.first + "=" + pair.second;
}
cmsg.msg += ")";
full_msg += ")";
}
cmsg.type = ctrl_msg_type::CTRL_MSG_OUTPUT;
m_queue.push(cmsg);
}
void falco_outputs::cleanup_outputs()
{
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_CLEANUP);
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
(*it)->output_msg(priority, full_msg);
}
}
void falco_outputs::reopen_outputs()
{
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_REOPEN);
}
void falco_outputs::stop_worker()
{
watchdog<void *> wd;
wd.start([&](void *) -> void {
falco_logger::log(LOG_NOTICE, "output channels still blocked, discarding all remaining notifications\n");
m_queue.clear();
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_STOP);
});
wd.set_timeout(m_timeout, nullptr);
this->push(falco_outputs::ctrl_msg_type::CTRL_MSG_STOP);
if(m_worker_thread.joinable())
for(auto it = m_outputs.cbegin(); it != m_outputs.cend(); ++it)
{
m_worker_thread.join();
(*it)->reopen();
}
}
inline void falco_outputs::push(ctrl_msg_type cmt)
{
falco_outputs::ctrl_msg cmsg = {};
cmsg.type = cmt;
m_queue.push(cmsg);
}
// todo(leogr,leodido): this function is not supposed to throw exceptions, and with "noexcept",
// the program is terminated if that occurs. Although that's the wanted behavior,
// we still need to improve the error reporting since some inner functions can throw exceptions.
void falco_outputs::worker() noexcept
{
watchdog<std::string> wd;
wd.start([&](std::string payload) -> void {
falco_logger::log(LOG_CRIT, "\"" + payload + "\" output timeout, all output channels are blocked\n");
});
auto timeout = m_timeout;
falco_outputs::ctrl_msg cmsg;
do
{
// Block until a message becomes available.
m_queue.pop(cmsg);
for(const auto o : m_outputs)
{
wd.set_timeout(timeout, o->get_name());
try
{
switch(cmsg.type)
{
case ctrl_msg_type::CTRL_MSG_OUTPUT:
o->output(&cmsg);
break;
case ctrl_msg_type::CTRL_MSG_CLEANUP:
case ctrl_msg_type::CTRL_MSG_STOP:
o->cleanup();
break;
case ctrl_msg_type::CTRL_MSG_REOPEN:
o->reopen();
break;
default:
falco_logger::log(LOG_DEBUG, "Outputs worker received an unknown message type\n");
}
}
catch(const exception &e)
{
falco_logger::log(LOG_ERR, o->get_name() + ": " + string(e.what()) + "\n");
}
}
wd.cancel_timeout();
} while(cmsg.type != ctrl_msg_type::CTRL_MSG_STOP);
}

View File

@@ -25,7 +25,6 @@ limitations under the License.
#include "token_bucket.h"
#include "falco_engine.h"
#include "outputs.h"
#include "tbb/concurrent_queue.h"
//
// This class acts as the primary interface between a program and the
@@ -40,25 +39,25 @@ public:
void init(bool json_output,
bool json_include_output_property,
uint32_t timeout,
uint32_t rate, uint32_t max_burst, bool buffered,
bool time_format_iso_8601, std::string hostname);
void add_output(falco::outputs::config oc);
// Format then send the event to all configured outputs (`evt` is an event that has matched some rule).
//
// evt is an event that has matched some rule. Pass the event
// to all configured outputs.
//
void handle_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format);
// Format then send a generic message to all outputs. Not necessarily associated with any event.
// Send a generic message to all outputs. Not necessarily associated with any event.
void handle_msg(uint64_t now,
falco_common::priority_type priority,
std::string &msg,
std::string &rule,
std::map<std::string, std::string> &output_fields);
void cleanup_outputs();
void reopen_outputs();
private:
@@ -72,28 +71,5 @@ private:
bool m_buffered;
bool m_json_output;
bool m_time_format_iso_8601;
std::chrono::milliseconds m_timeout;
std::string m_hostname;
enum ctrl_msg_type
{
CTRL_MSG_STOP = 0,
CTRL_MSG_OUTPUT = 1,
CTRL_MSG_CLEANUP = 2,
CTRL_MSG_REOPEN = 3,
};
struct ctrl_msg : falco::outputs::message
{
ctrl_msg_type type;
};
typedef tbb::concurrent_bounded_queue<ctrl_msg> falco_outputs_cbq;
falco_outputs_cbq m_queue;
std::thread m_worker_thread;
inline void push(ctrl_msg_type cmt);
void worker() noexcept;
void stop_worker();
};

View File

@@ -37,21 +37,6 @@ struct config
std::map<std::string, std::string> options;
};
//
// The message to be outputted. It can either refer to:
// - an event that has matched some rule,
// - or a generic message (e.g., a drop alert).
//
struct message
{
uint64_t ts;
falco_common::priority_type priority;
std::string msg;
std::string rule;
std::string source;
map<std::string, std::string> fields;
};
//
// This class acts as the primary interface for implementing
// a Falco output class.
@@ -60,8 +45,6 @@ struct message
class abstract_output
{
public:
virtual ~abstract_output() {}
void init(config oc, bool buffered, std::string hostname)
{
m_oc = oc;
@@ -69,19 +52,15 @@ public:
m_hostname = hostname;
}
// Return the output's name as per its configuration.
const std::string get_name() const
{
return m_oc.name;
}
// Output an event that has matched some rule.
virtual void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg) = 0;
// Output a message.
virtual void output(const message *msg) = 0;
// Output a generic message. Not necessarily associated with any event.
virtual void output_msg(falco_common::priority_type priority, std::string &msg) = 0;
// Possibly close the output and open it again.
virtual void reopen() {}
// Possibly flush the output.
virtual void cleanup() {}
protected:

View File

@@ -31,10 +31,16 @@ void falco::outputs::output_file::open_file()
}
}
void falco::outputs::output_file::output(const message *msg)
void falco::outputs::output_file::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_file::output_msg(falco_common::priority_type priority, std::string &msg)
{
open_file();
m_outfile << msg->msg + "\n";
m_outfile << msg + "\n";
if(m_oc.options["keep_alive"] != "true")
{

View File

@@ -27,7 +27,10 @@ namespace outputs
class output_file : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
void cleanup();

View File

@@ -21,41 +21,44 @@ limitations under the License.
#include "formats.h"
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_grpc::output(const message *msg)
void falco::outputs::output_grpc::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format,
std::string &msg)
{
falco::outputs::response grpc_res;
// time
auto timestamp = grpc_res.mutable_time();
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(msg->ts);
*timestamp = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(evt->get_ts());
// rule
auto r = grpc_res.mutable_rule();
*r = msg->rule;
*r = rule;
// source
falco::schema::source s = falco::schema::source::SYSCALL;
if(!falco::schema::source_Parse(msg->source, &s))
if(!falco::schema::source_Parse(source, &s))
{
throw falco_exception("Unknown source passed to output_grpc::output()");
throw falco_exception("Unknown source passed to output_grpc::output_event()");
}
grpc_res.set_source(s);
// priority
falco::schema::priority p = falco::schema::priority::EMERGENCY;
if(!falco::schema::priority_Parse(falco_common::priority_names[msg->priority], &p))
if(!falco::schema::priority_Parse(falco_common::priority_names[priority], &p))
{
throw falco_exception("Unknown priority passed to output_grpc::output()");
throw falco_exception("Unknown priority passed to output_grpc::output_event()");
}
grpc_res.set_priority(p);
// output
auto output = grpc_res.mutable_output();
*output = msg->msg;
*output = msg;
// output fields
auto &fields = *grpc_res.mutable_output_fields();
for(const auto &kv : msg->fields)
auto resolvedTkns = falco_formats::resolve_tokens(evt, source, format);
for(const auto &kv : resolvedTkns)
{
fields[kv.first] = kv.second;
}
@@ -65,4 +68,9 @@ void falco::outputs::output_grpc::output(const message *msg)
*host = m_hostname;
falco::grpc::queue::get().push(grpc_res);
}
void falco::outputs::output_grpc::output_msg(falco_common::priority_type priority, std::string &msg)
{
// todo(fntlnz, leodido, leogr) > gRPC does not support subscribing to dropped events yet
}

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_grpc : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
};
} // namespace outputs

View File

@@ -18,7 +18,13 @@ limitations under the License.
#include "logger.h"
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_http::output(const message *msg)
void falco::outputs::output_http::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_http::output_msg(falco_common::priority_type priority, std::string &msg)
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
@@ -31,7 +37,7 @@ void falco::outputs::output_http::output(const message *msg)
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
curl_easy_setopt(curl, CURLOPT_URL, m_oc.options["url"].c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg->msg.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L);
res = curl_easy_perform(curl);

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_http : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
};
} // namespace outputs

View File

@@ -31,11 +31,17 @@ void falco::outputs::output_program::open_pfile()
}
}
void falco::outputs::output_program::output(const message *msg)
void falco::outputs::output_program::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_program::output_msg(falco_common::priority_type priority, std::string &msg)
{
open_pfile();
fprintf(m_pfile, "%s\n", msg->msg.c_str());
fprintf(m_pfile, "%s\n", msg.c_str());
if(m_oc.options["keep_alive"] != "true")
{

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_program : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
void cleanup();

View File

@@ -18,10 +18,16 @@ limitations under the License.
#include <iostream>
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_stdout::output(const message *msg)
void falco::outputs::output_stdout::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_stdout::output_msg(falco_common::priority_type priority, std::string &msg)
{
//
// By default, the stdout stream is fully buffered or line buffered
// By default, the stdout stream is fully buffered or line buffered
// (if the stream can be determined to refer to an interactive device, e.g. in a TTY).
// Just enable automatic flushing when unbuffered output is desired.
// Note that it is set every time since other writings to the stdout can disable it.
@@ -30,7 +36,7 @@ void falco::outputs::output_stdout::output(const message *msg)
{
std::cout << std::unitbuf;
}
std::cout << msg->msg + "\n";
std::cout << msg + "\n";
}
void falco::outputs::output_stdout::cleanup()

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_stdout : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
void cleanup();
};

View File

@@ -18,8 +18,14 @@ limitations under the License.
#include <syslog.h>
#include "banned.h" // This raises a compilation error when certain functions are used
void falco::outputs::output_syslog::output(const message *msg)
void falco::outputs::output_syslog::output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg)
{
output_msg(priority, msg);
}
void falco::outputs::output_syslog::output_msg(falco_common::priority_type priority, std::string &msg)
{
// Syslog output should not have any trailing newline
::syslog(msg->priority, "%s", msg->msg.c_str());
::syslog(priority, "%s", msg.c_str());
}

View File

@@ -25,7 +25,10 @@ namespace outputs
class output_syslog : public abstract_output
{
void output(const message *msg);
void output_event(gen_event *evt, std::string &rule, std::string &source,
falco_common::priority_type priority, std::string &format, std::string &msg);
void output_msg(falco_common::priority_type priority, std::string &msg);
};
} // namespace outputs

View File

@@ -57,7 +57,4 @@ enum source {
k8s_audit = 1;
K8s_audit = 1;
K8S_audit = 1;
INTERNAL = 2;
internal = 2;
Internal = 2;
}

View File

@@ -1,96 +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 <chrono>
#include <thread>
#include <functional>
#include <atomic>
template<typename _T>
class watchdog
{
public:
watchdog():
m_timeout(nullptr),
m_is_running(false)
{
}
~watchdog()
{
stop();
}
void start(std::function<void(_T)> cb,
std::chrono::milliseconds resolution = std::chrono::milliseconds(100))
{
stop();
m_is_running.store(true, std::memory_order_release);
m_thread = std::thread([this, cb, resolution]() {
const auto no_deadline = time_point{};
timeout_data curr;
while(m_is_running.load(std::memory_order_acquire))
{
auto t = m_timeout.exchange(nullptr, std::memory_order_release);
if(t)
{
curr = *t;
delete t;
}
if(curr.deadline != no_deadline && curr.deadline < std::chrono::steady_clock::now())
{
cb(curr.payload);
curr.deadline = no_deadline;
}
std::this_thread::sleep_for(resolution);
}
});
}
void stop()
{
if(m_is_running.load(std::memory_order_acquire))
{
m_is_running.store(false, std::memory_order_release);
if(m_thread.joinable())
{
m_thread.join();
}
delete m_timeout.exchange(nullptr, std::memory_order_release);
}
}
inline void set_timeout(std::chrono::milliseconds timeout, _T payload) noexcept
{
delete m_timeout.exchange(new timeout_data{std::chrono::steady_clock::now() + timeout, payload}, std::memory_order_release);
}
inline void cancel_timeout() noexcept
{
delete m_timeout.exchange(new timeout_data, std::memory_order_release);
}
private:
typedef std::chrono::time_point<std::chrono::steady_clock> time_point;
struct timeout_data
{
time_point deadline;
_T payload;
};
std::atomic<timeout_data *> m_timeout;
std::atomic<bool> m_is_running;
std::thread m_thread;
};

10
userspace/libhawk/hawk.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef HAWK_H
#define HAWK_H
extern void hawk_init();
extern void hawk_destroy();
typedef void* hawk_engine;
typedef void (*hawk_watch_rules_cb)(char* rules_content, hawk_engine* engine);
extern void hawk_watch_rules(hawk_watch_rules_cb cb, hawk_engine* engine);
#endif //HAWK_H