diff --git a/CMakeLists.txt b/CMakeLists.txt index 49d19e23..22c3e5ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,6 +209,7 @@ set(CPACK_RPM_PACKAGE_REQUIRES "sysdig") set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/postinstall") set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/preuninstall") set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/rpm/postuninstall") -set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/src /usr/share/man /usr/share/man/man8) +set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/src /usr/share/man /usr/share/man/man8 /etc /usr /usr/bin /usr/share /etc/rc.d /etc/rc.d/init.d ) +set(CPACK_RPM_PACKAGE_RELOCATABLE "OFF") include(CPack) diff --git a/falco.yaml b/falco.yaml index d82ed41e..b3b30b26 100644 --- a/falco.yaml +++ b/falco.yaml @@ -1,16 +1,16 @@ -rules_file: /etc/falco_rules.conf +rules_file: /etc/falco_rules.yaml json_output: false log_stderr: true log_syslog: true syslog_output: - enabled: false + enabled: true file_output: enabled: true filename: ./events.txt stdout_output: - enabled: true + enabled: false diff --git a/scripts/debian/falco b/scripts/debian/falco index 9604f2d3..0c55a02f 100755 --- a/scripts/debian/falco +++ b/scripts/debian/falco @@ -20,7 +20,7 @@ DESC="Falco" NAME=falco DAEMON=/usr/bin/$NAME PIDFILE=/var/run/$NAME.pid -DAEMON_ARGS="--daemon --falcopid=$PIDFILE" +DAEMON_ARGS="--daemon --pidfile=$PIDFILE" SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed diff --git a/scripts/rpm/falco b/scripts/rpm/falco index c0c17e84..524e167c 100755 --- a/scripts/rpm/falco +++ b/scripts/rpm/falco @@ -34,7 +34,7 @@ start() { [ -x $exec ] || exit 5 # [ -f $config ] || exit 6 echo -n $"Starting $prog: " - daemon $exec --daemon --falcopid=$pidfile + daemon $exec --daemon --pidfile=$pidfile retval=$? echo [ $retval -eq 0 ] && touch $lockfile diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index b1c5a6cb..74e5775e 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -19,7 +19,7 @@ void falco_configuration::init(string conf_filename) string m_config_file = conf_filename; m_config = new yaml_configuration(m_config_file); - m_rules_filename = m_config->get_scalar("rules_file", "/etc/falco_rules.conf"); + m_rules_filename = m_config->get_scalar("rules_file", "/etc/falco_rules.yaml"); m_json_output = m_config->get_scalar("json_output", false); output_config file_output; diff --git a/userspace/falco/falco.cpp b/userspace/falco/falco.cpp index 8b3cb59e..9dce811c 100644 --- a/userspace/falco/falco.cpp +++ b/userspace/falco/falco.cpp @@ -39,11 +39,13 @@ static void usage() printf( "Usage: falco [options] rules_filename\n\n" "Options:\n" - " -h, --help Print this page\n" - " -c Configuration file (default " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ")\n" - " -o Output type (options are 'stdout', 'syslog', default is 'stdout')\n" - " -e Read the events from (in .scap format) instead of tapping into live.\n" - " -r Rules file (defaults to value set in configuration file, or /etc/falco_rules.conf).\n" + " -h, --help Print this page\n" + " -c Configuration file (default " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ")\n" + " -o Output type (options are 'stdout', 'syslog', default is 'stdout')\n" + " -d, --daemon Run as a daemon\n" + " -p, --pidfile When run as a daemon, write pid to specified file\n" + " -e Read the events from (in .scap format) instead of tapping into live.\n" + " -r Rules file (defaults to value set in configuration file, or /etc/falco_rules.conf).\n" "\n" ); } @@ -192,16 +194,20 @@ int falco_init(int argc, char **argv) sinsp_evt::param_fmt event_buffer_format; int long_index = 0; string lua_main_filename; - string output_name = "stdout"; + string output_name = "syslog"; string scap_filename; string conf_filename; string rules_filename; string lua_dir = FALCO_LUA_DIR; lua_State* ls = NULL; + bool daemon = false; + string pidfilename = "/var/run/falco.pid"; static struct option long_options[] = { {"help", no_argument, 0, 'h' }, + {"daemon", no_argument, 0, 'd' }, + {"pidfile", required_argument, 0, 'd' }, {0, 0, 0, 0} }; @@ -214,7 +220,7 @@ int falco_init(int argc, char **argv) // Parse the args // while((op = getopt_long(argc, argv, - "c:ho:e:r:", + "c:ho:e:r:dp:", long_options, &long_index)) != -1) { switch(op) @@ -239,6 +245,12 @@ int falco_init(int argc, char **argv) case 'r': rules_filename = optarg; break; + case 'd': + daemon = true; + break; + case 'p': + pidfilename = optarg; + break; case '?': result = EXIT_FAILURE; goto exit; @@ -248,6 +260,18 @@ int falco_init(int argc, char **argv) } + // Some combinations of arguments are not allowed. + if (daemon && pidfilename == "") { + falco_logger::log(LOG_ERR, "If -d is provided, a pid file must also be provided. Exiting.\n"); + result = EXIT_FAILURE; + goto exit; + } + + if (daemon && output_name == "stdout") { + falco_logger::log(LOG_ERR, "If -d is provided, can not output to stdout. Exiting.\n"); + result = EXIT_FAILURE; + goto exit; + } ifstream* conf_stream; if (conf_filename.size()) @@ -255,7 +279,7 @@ int falco_init(int argc, char **argv) conf_stream = new ifstream(conf_filename); if (!conf_stream->good()) { - falco_logger::log(LOG_ERR, "Could not find configuration file at " + conf_filename + ". Exiting \n"); + falco_logger::log(LOG_ERR, "Could not find configuration file at " + conf_filename + ". Exiting.\n"); result = EXIT_FAILURE; goto exit; } @@ -308,7 +332,7 @@ int falco_init(int argc, char **argv) { falco_logger::log(LOG_ERR, "Could not find Falco Lua libraries (tried " + string(FALCO_LUA_DIR FALCO_LUA_MAIN) + ", " + - lua_main_filename + "). Exiting \n"); + lua_main_filename + "). Exiting.\n"); result = EXIT_FAILURE; goto exit; } @@ -365,11 +389,64 @@ int falco_init(int argc, char **argv) { if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null")) { - falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting\n"); + falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting.\n"); } inspector->open(); } } + + // If daemonizing, do it here so any init errors will + // be returned in the foreground process. + if (daemon) { + pid_t pid, sid; + + pid = fork(); + if (pid < 0) { + // error + falco_logger::log(LOG_ERR, "Could not fork. Exiting.\n"); + result = EXIT_FAILURE; + goto exit; + } else if (pid > 0) { + // parent. Write child pid to pidfile and exit + std::ofstream pidfile; + pidfile.open(pidfilename); + + if (!pidfile.good()) + { + falco_logger::log(LOG_ERR, "Could not write pid to pid file " + pidfilename + ". Exiting.\n"); + result = EXIT_FAILURE; + goto exit; + } + pidfile << pid; + pidfile.close(); + goto exit; + } + // if here, child. + + // Become own process group. + sid = setsid(); + if (sid < 0) { + falco_logger::log(LOG_ERR, "Could not set session id. Exiting.\n"); + result = EXIT_FAILURE; + goto exit; + } + + // Set umask so no files are world anything or group writable. + umask(027); + + // Change working directory to '/' + if ((chdir("/")) < 0) { + falco_logger::log(LOG_ERR, "Could not change working directory to '/'. Exiting.\n"); + result = EXIT_FAILURE; + goto exit; + } + + // Close stdin, stdout, stderr. + close(0); + close(1); + close(2); + } + do_inspect(inspector, rules, ls); @@ -378,7 +455,7 @@ int falco_init(int argc, char **argv) } catch(sinsp_exception& e) { - falco_logger::log(LOG_ERR, "Runtime error: " + string(e.what()) + ". Exiting\n"); + falco_logger::log(LOG_ERR, "Runtime error: " + string(e.what()) + ". Exiting.\n"); result = EXIT_FAILURE; } diff --git a/userspace/falco/logger.cpp b/userspace/falco/logger.cpp index 9f104265..7c4bdc5b 100644 --- a/userspace/falco/logger.cpp +++ b/userspace/falco/logger.cpp @@ -30,8 +30,8 @@ int falco_logger::syslog(lua_State *ls) { return 0; } -bool falco_logger::log_stderr; -bool falco_logger::log_syslog; +bool falco_logger::log_stderr = true; +bool falco_logger::log_syslog = true; void falco_logger::log(int priority, const string msg) { if (falco_logger::log_syslog) {