blob: 4cf0e8c5ae2501a2dd897cac7027a0a283ae2a6d [file] [log] [blame]
Luis Hector Chavez81efb332017-09-18 14:01:29 -07001// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIBCONTAINER_LIBCONTAINER_UTIL_H_
6#define LIBCONTAINER_LIBCONTAINER_UTIL_H_
7
8#include <string>
Luis Hector Chavez644d2042017-09-19 18:56:44 -07009#include <vector>
Luis Hector Chavez81efb332017-09-18 14:01:29 -070010
Luis Hector Chavez644d2042017-09-19 18:56:44 -070011#include <base/callback_forward.h>
Luis Hector Chavez81efb332017-09-18 14:01:29 -070012#include <base/files/file_path.h>
Luis Hector Chaveze03926a2017-09-28 17:28:49 -070013#include <base/files/scoped_file.h>
Luis Hector Chavez835d39e2017-09-19 15:16:31 -070014#include <base/logging.h>
15#include <base/macros.h>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070016#include <libminijail.h>
17
18#include "libcontainer/config.h"
19#include "libcontainer/libcontainer.h"
Luis Hector Chavez81efb332017-09-18 14:01:29 -070020
21namespace libcontainer {
22
Luis Hector Chavez644d2042017-09-19 18:56:44 -070023// WaitablePipe provides a way for one process to wait on another. This only
24// uses the read(2) and close(2) syscalls, so it can work even in a restrictive
25// environment. Each process must call only one of Wait() and Signal() exactly
26// once.
27struct WaitablePipe {
28 WaitablePipe();
29 ~WaitablePipe();
30
31 WaitablePipe(WaitablePipe&&);
32
33 // Waits for Signal() to be called.
34 void Wait();
35
36 // Notifies the process that called Wait() to continue running.
37 void Signal();
38
39 int pipe_fds[2];
40
41 private:
42 DISALLOW_COPY_AND_ASSIGN(WaitablePipe);
43};
44
45// HookState holds two WaitablePipes so that the container can wait for its
46// parent to run prestart hooks just prior to calling execve(2).
47class HookState {
48 public:
49 HookState();
50 ~HookState();
51
52 HookState(HookState&& state);
53
54 // Initializes this HookState so that WaitForHookAndRun() can be invoked and
55 // waited upon when |j| reaches |event|. Returns true on success.
56 bool InstallHook(minijail* j, minijail_hook_event_t event);
57
58 // Waits for the event specified in InstallHook() and invokes |callbacks| in
59 // the caller process. Returns true if all callbacks succeeded.
60 bool WaitForHookAndRun(const std::vector<HookCallback>& callbacks,
61 pid_t container_pid);
62
63 private:
64 // A function that can be passed to minijail_add_hook() that blocks the
65 // process in the container until the parent has finished running whatever
66 // operations are needed outside the container. This is not expected to be
67 // called directly.
68 static int WaitHook(void* payload);
69
70 bool installed_ = false;
71 WaitablePipe reached_pipe_;
72 WaitablePipe ready_pipe_;
73
74 DISALLOW_COPY_AND_ASSIGN(HookState);
75};
76
Luis Hector Chavez81efb332017-09-18 14:01:29 -070077// Given a uid/gid map of "inside1 outside1 length1, ...", and an id inside of
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070078// the user namespace, populate |id_out|. Returns true on success.
79bool GetUsernsOutsideId(const std::string& map, int id, int* id_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070080
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070081bool MakeDir(const base::FilePath& path, int uid, int gid, int mode);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070082
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070083bool TouchFile(const base::FilePath& path, int uid, int gid, int mode);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070084
85// Find a free loop device and attach it.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070086bool LoopdevSetup(const base::FilePath& source,
87 base::FilePath* loopdev_path_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070088
89// Detach the specified loop device.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070090bool LoopdevDetach(const base::FilePath& loopdev);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070091
92// Create a new device mapper target for the source.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070093bool DeviceMapperSetup(const base::FilePath& source,
94 const std::string& verity_cmdline,
95 base::FilePath* dm_path_out,
96 std::string* dm_name_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070097
98// Tear down the device mapper target.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070099bool DeviceMapperDetach(const std::string& dm_name);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700100
101// Match mount_one in minijail, mount one mountpoint with
102// consideration for combination of MS_BIND/MS_RDONLY flag.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700103bool MountExternal(const std::string& src,
104 const std::string& dest,
105 const std::string& type,
106 unsigned long flags,
107 const std::string& data);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700108
Luis Hector Chaveze03926a2017-09-28 17:28:49 -0700109// Creates a pipe using pipe2(2) and returns both ends as base::ScopedFDs.
110bool Pipe2(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe, int flags);
111
112// Creates a callback that will fork(2)+execve(2) the program specified by args.
113HookCallback CreateExecveCallback(base::FilePath filename,
114 std::vector<std::string> args,
115 base::ScopedFD stdin_fd,
116 base::ScopedFD stdout_fd,
117 base::ScopedFD stderr_fd);
118
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700119// Wraps a callback to be run in a subset of the container's namespaces.
120HookCallback AdaptCallbackToRunInNamespaces(HookCallback callback,
121 std::vector<int> nstypes);
122
Luis Hector Chavez92278e82017-10-16 11:30:27 -0700123// Similar to base::CreateDirectory, but allows specifying the created
124// directories' mode and owner.
125bool CreateDirectoryOwnedBy(const base::FilePath& full_path,
126 mode_t mode,
127 uid_t uid,
128 gid_t gid);
129
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700130} // namespace libcontainer
131
132#endif // LIBCONTAINER_LIBCONTAINER_UTIL_H_