blob: 3e1a97abf76641c3a1826e09de2052ebc7b51643 [file] [log] [blame]
// Copyright 2015 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.
#include "germ/launcher.h"
#include <sys/types.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/rand_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/minijail/minijail.h>
namespace germ {
// Starts with the top half of user ids.
class UidService final {
public:
UidService() { min_uid_ = 1 << ((sizeof(uid_t) * 8) >> 1); }
~UidService() {}
uid_t GetUid() {
return static_cast<uid_t>(base::RandInt(min_uid_, 2 * min_uid_));
}
private:
uid_t min_uid_;
};
Launcher::Launcher() {
uid_service_.reset(new UidService());
}
Launcher::~Launcher() {}
bool Launcher::RunInteractiveCommand(const std::string& name,
const std::vector<std::string>& argv,
int* status) {
std::vector<char*> cmdline;
for (const auto& t : argv) {
cmdline.push_back(const_cast<char*>(t.c_str()));
}
// Minijail will use the underlying char* array as 'argv',
// so null-terminate it.
cmdline.push_back(nullptr);
uid_t uid = uid_service_->GetUid();
Environment env(uid, uid);
return RunWithMinijail(env, cmdline, status);
}
bool Launcher::RunInteractiveSpec(const soma::ReadOnlyContainerSpec& spec,
int* status) {
std::vector<char*> cmdline;
// TODO(jorgelo): support running more than one executable.
for (const auto& t : spec.executables()[0]->command_line) {
cmdline.push_back(const_cast<char*>(t.c_str()));
}
// Minijail will use the underlying char* array as 'argv',
// so null-terminate it.
cmdline.push_back(nullptr);
Environment env(spec.executables()[0]->uid, spec.executables()[0]->gid);
return RunWithMinijail(env, cmdline, status);
}
void Launcher::ExecveInMinijail(const SomaExecutable& executable) {
std::vector<char*> argv;
argv.reserve(executable.command_line_size() + 1);
for (const std::string& command_line : executable.command_line()) {
argv.push_back(const_cast<char*>(command_line.c_str()));
}
// Null-terminate |argv|.
argv.push_back(nullptr);
Environment env(executable.uid(), executable.gid());
// We'll already be in a PID namespace at this point.
env.SetEnterNewPidNamespace(false);
chromeos::Minijail* minijail = chromeos::Minijail::GetInstance();
minijail->Enter(env.GetForInteractive());
// TODO(rickyz): Environment?
execve(argv[0], argv.data(), nullptr);
}
bool Launcher::RunWithMinijail(const Environment& env,
const std::vector<char*>& cmdline,
int* status) {
chromeos::Minijail* minijail = chromeos::Minijail::GetInstance();
return minijail->RunSyncAndDestroy(env.GetForInteractive(), cmdline,
status);
}
} // namespace germ