diff --git a/userspace/falco/CMakeLists.txt b/userspace/falco/CMakeLists.txt index 9ece1ba7..6a9070c2 100644 --- a/userspace/falco/CMakeLists.txt +++ b/userspace/falco/CMakeLists.txt @@ -21,6 +21,7 @@ set( app_runnable_action.cpp app_actions/create_signal_handlers.cpp app_actions/init_action.cpp + app_actions/run_action.cpp app_actions/init_falco_engine.cpp app_actions/init_inspector.cpp app_actions/init_outputs.cpp @@ -36,6 +37,7 @@ set( app_actions/start_grpc_server.cpp app_actions/start_webserver.cpp app_actions/validate_rules_files.cpp + app_actions/daemonize.cpp app_action_manager.cpp configuration.cpp logger.cpp diff --git a/userspace/falco/app_actions/daemonize.cpp b/userspace/falco/app_actions/daemonize.cpp new file mode 100644 index 00000000..b027d3a0 --- /dev/null +++ b/userspace/falco/app_actions/daemonize.cpp @@ -0,0 +1,115 @@ +/* +Copyright (C) 2022 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 +#include +#include + +#include "daemonize.h" + +namespace falco { +namespace app { + +act_daemonize::act_daemonize(application &app) + : run_action(app), m_name("daemonize"), m_daemonized(false) +{ +} + +act_daemonize::~act_daemonize() +{ +} + +const std::string &act_daemonize::name() +{ + return m_name; +} + +const std::list &act_daemonize::prerequsites() +{ + return m_prerequsites; +} + +runnable_action::run_result act_daemonize::run() +{ + run_result ret = {true, "", true}; + + // If daemonizing, do it here so any init errors will + // be returned in the foreground process. + if (app().options().daemon && !m_daemonized) { + pid_t pid, sid; + + pid = fork(); + if (pid < 0) { + // error + ret.success = false; + ret.errstr = "Could not fork."; + ret.proceed = false; + return ret; + } else if (pid > 0) { + // parent. Write child pid to pidfile and exit + std::ofstream pidfile; + pidfile.open(app().options().pidfilename); + + if (!pidfile.good()) + { + ret.success = false; + ret.errstr = string("Could not write pid to pid file ") + app().options().pidfilename + "."; + ret.proceed = false; + return ret; + } + pidfile << pid; + pidfile.close(); + return ret; + } + // if here, child. + + // Become own process group. + sid = setsid(); + if (sid < 0) { + ret.success = false; + ret.errstr = string("Could not set session id."); + ret.proceed = false; + return ret; + } + + // Set umask so no files are world anything or group writable. + umask(027); + + // Change working directory to '/' + if ((chdir("/")) < 0) { + ret.success = false; + ret.errstr = string("Could not change working directory to '/'."); + ret.proceed = false; + return ret; + } + + // Close stdin, stdout, stderr and reopen to /dev/null + close(0); + close(1); + close(2); + open("/dev/null", O_RDONLY); + open("/dev/null", O_RDWR); + open("/dev/null", O_RDWR); + + m_daemonized = true; + } + + return ret; +} + +}; // namespace application +}; // namespace falco + diff --git a/userspace/falco/app_actions/daemonize.h b/userspace/falco/app_actions/daemonize.h new file mode 100644 index 00000000..cea84ebb --- /dev/null +++ b/userspace/falco/app_actions/daemonize.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 2022 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 + +#include "run_action.h" + +namespace falco { +namespace app { + +class act_daemonize : public run_action { +public: + act_daemonize(application &app); + virtual ~act_daemonize(); + + const std::string &name() override; + + const std::list &prerequsites() override; + + run_result run() override; + +private: + std::string m_name; + std::list m_prerequsites; + bool m_daemonized; +}; + +}; // namespace application +}; // namespace falco + diff --git a/userspace/falco/app_actions/run_action.cpp b/userspace/falco/app_actions/run_action.cpp new file mode 100644 index 00000000..40be179a --- /dev/null +++ b/userspace/falco/app_actions/run_action.cpp @@ -0,0 +1,40 @@ +/* +Copyright (C) 2022 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 "run_action.h" + +namespace falco { +namespace app { + +static std::string run_group = "run"; + +run_action::run_action(application &app) + : action(app) +{ +} + +run_action::~run_action() +{ +} + +const std::string &run_action::group() +{ + return run_group; +} + +}; // namespace application +}; // namespace falco + diff --git a/userspace/falco/app_actions/run_action.h b/userspace/falco/app_actions/run_action.h new file mode 100644 index 00000000..33eb8db7 --- /dev/null +++ b/userspace/falco/app_actions/run_action.h @@ -0,0 +1,37 @@ +/* +Copyright (C) 2022 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 "app_action.h" + +namespace falco { +namespace app { + +// All actions in the "run" group derive from this class + +class run_action : public action { +public: + run_action(application &app); + virtual ~run_action(); + + const std::string &group() override; +}; + +}; // namespace application +}; // namespace falco + diff --git a/userspace/falco/defined_app_actions.h b/userspace/falco/defined_app_actions.h index d4e47e03..b8ebad2b 100644 --- a/userspace/falco/defined_app_actions.h +++ b/userspace/falco/defined_app_actions.h @@ -31,4 +31,6 @@ limitations under the License. #include "app_actions/start_webserver.h" #include "app_actions/validate_rules_files.h" +#include "app_actions/daemonize.h" +