blob: a20b8022efbff401b8c0a570e8b35cde16eb5a27 [file] [log] [blame]
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PATCHPANEL_MINIJAILED_PROCESS_RUNNER_H_
#define PATCHPANEL_MINIJAILED_PROCESS_RUNNER_H_
#include <sys/types.h>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include <base/time/time.h>
#include <brillo/minijail/minijail.h>
#include "patchpanel/iptables.h"
#include "patchpanel/system.h"
namespace patchpanel {
// Runs the current process with minimal privileges. This function is expected
// to be used by child processes that need only CAP_NET_RAW and to run as the
// patchpaneld user.
void EnterChildProcessJail();
// Enforces the expected processes are run with the correct privileges.
class MinijailedProcessRunner {
public:
// Ownership of |mj| is not assumed and must be managed by the caller.
// If |mj| is null, the default instance will be used.
explicit MinijailedProcessRunner(brillo::Minijail* mj = nullptr);
// Provided for testing only.
MinijailedProcessRunner(brillo::Minijail* mj, std::unique_ptr<System> system);
MinijailedProcessRunner(const MinijailedProcessRunner&) = delete;
MinijailedProcessRunner& operator=(const MinijailedProcessRunner&) = delete;
virtual ~MinijailedProcessRunner() = default;
// Runs ip. If |as_patchpanel_user|, runs as user 'patchpaneld' and under the
// group 'patchpaneld', as well as inherits supplemntary groups (i.e. group
// 'tun') of user 'patchpaneld'. If not, runs as 'nobody'.
virtual int ip(const std::string& obj,
const std::string& cmd,
const std::vector<std::string>& args,
bool as_patchpanel_user = false,
bool log_failures = true);
virtual int ip6(const std::string& obj,
const std::string& cmd,
const std::vector<std::string>& args,
bool as_patchpanel_user = false,
bool log_failures = true);
// Runs iptables.
// - If |timeout| is not nullopt, the command will be killed if the process
// runs longer than |timeout|.
// - If |output| is not nullptr, it will be filled with the result from stdout
// of iptables command.
virtual int iptables(Iptables::Table table,
Iptables::Command command,
std::string_view chain,
const std::vector<std::string>& argv,
bool log_failures = true,
std::optional<base::TimeDelta> timeout = std::nullopt,
std::string* output = nullptr);
virtual int ip6tables(Iptables::Table table,
Iptables::Command command,
std::string_view chain,
const std::vector<std::string>& argv,
bool log_failures = true,
std::optional<base::TimeDelta> timeout = std::nullopt,
std::string* output = nullptr);
// Installs all |modules| via modprobe.
virtual int modprobe_all(const std::vector<std::string>& modules,
bool log_failures = true);
// Creates a new named network namespace with name |netns_name|.
virtual int ip_netns_add(const std::string& netns_name,
bool log_failures = true);
// Attaches a name to the network namespace of the given pid
// TODO(hugobenichi) How can patchpanel create a |netns_name| file in
// /run/netns without running ip as root ?
virtual int ip_netns_attach(const std::string& netns_name,
pid_t netns_pid,
bool log_failures = true);
virtual int ip_netns_delete(const std::string& netns_name,
bool log_failures = true);
// Run conntrack command with given command option and |argv|.
virtual int conntrack(std::string_view command,
const std::vector<std::string>& argv,
bool log_failures = true);
protected:
// Used by ip() and ip6().
// Runs a process (argv[0]) with optional arguments (argv[1]...)
// in a minijail as user |patchpaneld| and user the group |patchpaneld| with
// CAP_NET_ADMIN and CAP_NET_RAW capabilities. Inherits supplementary groups
// of |patchpaneld|.
virtual int RunIp(const std::vector<std::string>& argv,
bool as_patchpanel_user,
bool log_failures = true);
virtual int RunIptables(std::string_view iptables_path,
Iptables::Table table,
Iptables::Command command,
std::string_view chain,
const std::vector<std::string>& argv,
bool log_failures,
std::optional<base::TimeDelta> timeout,
std::string* output);
virtual int RunIpNetns(const std::vector<std::string>& argv,
bool log_failures);
private:
int RunSyncDestroy(const std::vector<std::string>& argv,
brillo::Minijail* mj,
minijail* jail,
bool log_failures,
std::string* output) {
return RunSyncDestroyWithTimeout(argv, mj, jail, log_failures,
/*timeout=*/std::nullopt, output);
}
int RunSyncDestroyWithTimeout(const std::vector<std::string>& argv,
brillo::Minijail* mj,
minijail* jail,
bool log_failures,
std::optional<base::TimeDelta> timeout,
std::string* output);
brillo::Minijail* mj_;
std::unique_ptr<System> system_;
};
} // namespace patchpanel
#endif // PATCHPANEL_MINIJAILED_PROCESS_RUNNER_H_