21 struct ContainerInfo {
22 ContainerFilesystem* fs_;
28 int EnterContainer(
void *
data) {
32 std::cerr <<
"Running function in container {chroot='"
34 <<
"', domainname='" <<
container->domainname_ <<
"'}"
40 while (getuid() != 0 &&
count > 0) {
45 std::cerr <<
"Child in user namespace has uid " << getuid() << std::endl;
52 <<
" " << innerdir << std::endl;
53 int rc = mount(
container->fs_->mountpt().c_str(), innerdir.c_str(),
56 std::cerr <<
"Warning: failed to bind mount " <<
container->fs_->mountpt() <<
" at "
57 << innerdir <<
", errno=" << errno << std::endl;
62 if (chdir(
container->fs_->root().c_str()) != 0) {
63 std::cerr <<
"Failed to chdir('" <<
container->fs_->root()
64 <<
"'), errno=" << errno << std::endl;
69 if (getcwd(
buffer, PATH_MAX) == NULL) {
70 std::cerr <<
"failed to retrieve cwd, errno=" << errno << std::endl;
75 std::cerr <<
"chroot('" <<
buffer <<
"') failed, errno=" << errno << std::endl;
81 if (sethostname(
container->hostname_.c_str(),
83 std::cerr <<
"Failed to sethostname('" <<
container->hostname_
84 <<
"'), errno=" << errno << std::endl;
89 if (setdomainname(
container->domainname_.c_str(),
91 std::cerr <<
"Failed to setdomainname('" <<
container->domainname_
92 <<
"'), errno=" << errno << std::endl;
106 int RunInContainer(ContainerFilesystem* fs,
const std::string& hostname,
108 const int stack_size = 1024 * 1024;
109 std::vector<byte>
stack(stack_size, 0);
110 ContainerInfo
container = {fs, hostname, domainname,
fn};
113 pid_t
child = clone(EnterContainer,
stack.data() + stack_size,
114 CLONE_VM|CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWUTS|SIGCHLD,
117 std::cerr <<
"Failed to clone(), errno=" << errno << std::endl;
122 std::stringstream mapfiless;
123 mapfiless <<
"/proc/" <<
child <<
"/uid_map";
125 int fd =
open(mapfile.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644);
127 std::cerr <<
"Failed to create '" << mapfile <<
"'" << std::endl;
130 std::stringstream contentss;
131 contentss <<
"0 " << getuid() <<
" 1" << std::endl;
134 if (rc != (
int)
content.size()) {
135 std::cerr <<
"Failed to write uid map to '" << mapfile <<
"'" << std::endl;
143 std::cerr <<
"Failed to waitpid(" <<
child <<
")" << std::endl;
147 std::cerr <<
"Child " <<
child <<
" did not exit normally" << std::endl;
153 ContainerFilesystem::ContainerFilesystem(NameContentList
files,
const std::string& mountpt) {
154 rootdir_ =
TempNam(
nullptr,
"ares-chroot");
155 mkdir(rootdir_.c_str(), 0755);
156 dirs_.push_front(rootdir_);
157 for (
const auto& nc :
files) {
159 int idx = fullpath.rfind(
'/');
162 files_.push_back(std::unique_ptr<TransientFile>(
163 new TransientFile(fullpath, nc.second)));
165 if (!mountpt.empty()) {
166 char buffer[PATH_MAX + 1];
167 if (realpath(mountpt.c_str(),
buffer)) {
175 ContainerFilesystem::~ContainerFilesystem() {
183 if (
std::find(dirs_.begin(), dirs_.end(), dir) != dirs_.end()) {
186 size_t idx = dir.rfind(
'/');
187 if (
idx != std::string::npos) {
192 mkdir(dir.c_str(), 0755);
193 dirs_.push_front(dir);