| // Copyright 2016 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef AUTHPOLICY_PROCESS_EXECUTOR_H_ |
| #define AUTHPOLICY_PROCESS_EXECUTOR_H_ |
| |
| #include <map> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/macros.h> |
| |
| struct minijail; |
| |
| namespace authpolicy { |
| |
| class Anonymizer; |
| |
| // Helper class to execute commands and piping data. Uses minijail. |
| class ProcessExecutor { |
| public: |
| explicit ProcessExecutor(std::vector<std::string> args); |
| |
| // Gets the arguments passed into the constructor. |
| const std::vector<std::string>& GetArgs() const { return args_; } |
| |
| // Adds a single argument to the end of the argument list. |
| void PushArg(std::string arg) { args_.push_back(std::move(arg)); } |
| |
| // Set a file descriptor that gets piped into stdin during execution. |
| // The file descriptor must stay valid until |Execute| is called. |
| void SetInputFile(int fd); |
| |
| // Set a string that gets written to stdin during execution. If a file |
| // descriptor is set as well, this string is appended to its data. |
| void SetInputString(const std::string& input_str); |
| |
| // Set an environment variable '|key|=|value|, which is passed into the |
| // process to be executed. Any number of variables can be set. |
| void SetEnv(const std::string& key, const std::string& value); |
| |
| // Sets a seccomp filter by parsing the given file. |
| void SetSeccompFilter(const std::string& policy_file); |
| |
| // Toggles logging of syscalls blocked by seccomp filters. |
| void LogSeccompFilterFailures(bool enabled); |
| |
| // Toggles a flag that prevents execve from gaining new privileges. |
| void SetNoNewPrivs(bool enabled); |
| |
| // Toggles a flag that prevents that supplementary groups are wiped. |
| void KeepSupplementaryGroups(bool enabled); |
| |
| // Toggles logging of command line and the exit code. |
| void LogCommand(bool enabled); |
| |
| // Toggles logging of the command output. |
| void LogOutput(bool enabled); |
| |
| // Toggles logging of the command output if the command failed. |
| void LogOutputOnError(bool enabled); |
| |
| // Sets the anonymizer to be applied to command logs. |
| void SetAnonymizer(Anonymizer* anonymizer); |
| |
| // Execute the command. Returns true if the command executed and returned with |
| // exit code 0. Also returns true if no args were passed to the constructor. |
| // Returns false otherwise. |
| // Calling |Execute| multiple times is possible. Note, however, that you might |
| // have to call |SetInputFile| again if the input pipe was fully read. |
| // Getters should only be called after execution. |
| bool Execute(); |
| |
| // On first call, if any type of logging is enabled, logs stdout and stderr |
| // from the last call to Execute(). Subsequent calls do nothing. Called |
| // automatically by Execute() if certain logging conditions are met. Call this |
| // function if logging-on-error is enabled, the return code was 0, but you |
| // want to log anyway, e.g. since the data was bad or unexpected. |
| void LogOutputOnce(); |
| |
| // When set to true, will perform IO on the child process' stdin, stdout and |
| // stderr only after the child process has exited. Intended to allow testing |
| // of the handling of error conditions. |
| void SetPerformPipeIoAfterProcessExitForTesting( |
| bool perform_pipe_io_after_process_exit_for_testing); |
| |
| // Populated after execute call. |
| const std::string& GetStdout() const { return out_data_; } |
| const std::string& GetStderr() const { return err_data_; } |
| int GetExitCode() const { return exit_code_; } |
| |
| // GetExitCode() returns this if some internal error in Execute() occurred, |
| // e.g. failed to copy stdin pipes. Not an actual return code from execve. |
| static const int kExitCodeInternalError = 127; |
| |
| private: |
| // Resets the output variables that are populated by |Execute|. |
| void ResetOutput(); |
| |
| // Logs stderr and stdout from the last command, if output logs are enabled. |
| void MaybeLogOutput(); |
| |
| std::vector<std::string> args_; |
| std::map<std::string, std::string> env_map_; |
| int input_fd_ = -1; |
| std::string input_str_; |
| std::string out_data_; |
| std::string err_data_; |
| int exit_code_ = 0; |
| std::string seccomp_policy_file_; |
| bool log_seccomp_failures_ = false; |
| bool no_new_privs_ = false; |
| bool keep_supplementary_flags_ = false; |
| bool log_command_ = false; |
| bool log_output_ = false; |
| bool log_output_on_error_ = false; |
| Anonymizer* anonymizer_ = nullptr; |
| bool output_logged_ = false; |
| bool perform_pipe_io_after_process_exit_for_testing_ = false; |
| |
| // We better not copy/assign because of |input_fd_|. |
| DISALLOW_COPY_AND_ASSIGN(ProcessExecutor); |
| }; |
| |
| } // namespace authpolicy |
| |
| #endif // AUTHPOLICY_PROCESS_EXECUTOR_H_ |