blob: 73a713f2b36a27c541d77e8c288371aaa74187e4 [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
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -07008#include <linux/loop.h>
9
Luis Hector Chavez81efb332017-09-18 14:01:29 -070010#include <string>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070011#include <vector>
Luis Hector Chavez81efb332017-09-18 14:01:29 -070012
Luis Hector Chavez644d2042017-09-19 18:56:44 -070013#include <base/callback_forward.h>
Luis Hector Chavez81efb332017-09-18 14:01:29 -070014#include <base/files/file_path.h>
Luis Hector Chaveze03926a2017-09-28 17:28:49 -070015#include <base/files/scoped_file.h>
Luis Hector Chavez835d39e2017-09-19 15:16:31 -070016#include <base/logging.h>
17#include <base/macros.h>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070018#include <libminijail.h>
19
20#include "libcontainer/config.h"
21#include "libcontainer/libcontainer.h"
Luis Hector Chavez81efb332017-09-18 14:01:29 -070022
23namespace libcontainer {
24
Luis Hector Chavez644d2042017-09-19 18:56:44 -070025// WaitablePipe provides a way for one process to wait on another. This only
26// uses the read(2) and close(2) syscalls, so it can work even in a restrictive
27// environment. Each process must call only one of Wait() and Signal() exactly
28// once.
29struct WaitablePipe {
30 WaitablePipe();
31 ~WaitablePipe();
32
33 WaitablePipe(WaitablePipe&&);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090034 WaitablePipe(const WaitablePipe&) = delete;
35 WaitablePipe& operator=(const WaitablePipe&) = delete;
Luis Hector Chavez644d2042017-09-19 18:56:44 -070036
37 // Waits for Signal() to be called.
38 void Wait();
39
40 // Notifies the process that called Wait() to continue running.
41 void Signal();
42
43 int pipe_fds[2];
Luis Hector Chavez644d2042017-09-19 18:56:44 -070044};
45
46// HookState holds two WaitablePipes so that the container can wait for its
47// parent to run prestart hooks just prior to calling execve(2).
48class HookState {
49 public:
50 HookState();
51 ~HookState();
52
53 HookState(HookState&& state);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090054 HookState(const HookState&) = delete;
55 HookState& operator=(const HookState&) = delete;
Luis Hector Chavez644d2042017-09-19 18:56:44 -070056
57 // Initializes this HookState so that WaitForHookAndRun() can be invoked and
58 // waited upon when |j| reaches |event|. Returns true on success.
59 bool InstallHook(minijail* j, minijail_hook_event_t event);
60
61 // Waits for the event specified in InstallHook() and invokes |callbacks| in
62 // the caller process. Returns true if all callbacks succeeded.
63 bool WaitForHookAndRun(const std::vector<HookCallback>& callbacks,
64 pid_t container_pid);
65
66 private:
67 // A function that can be passed to minijail_add_hook() that blocks the
68 // process in the container until the parent has finished running whatever
69 // operations are needed outside the container. This is not expected to be
70 // called directly.
71 static int WaitHook(void* payload);
72
73 bool installed_ = false;
74 WaitablePipe reached_pipe_;
75 WaitablePipe ready_pipe_;
Luis Hector Chavez644d2042017-09-19 18:56:44 -070076};
77
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -070078// Loopdev represents an active loopback device.
79struct Loopdev {
80 // The path of the loopback device. e.g. /dev/loop1
81 base::FilePath path;
82
83 // An open file descriptor for the loopback device. Has the autoclear flag,
84 // such that the kernel will automatically remove it once all references to it
85 // are closed.
86 base::ScopedFD fd;
87
88 // Information about the loop device.
89 struct loop_info64 info;
90};
91
Luis Hector Chavez81efb332017-09-18 14:01:29 -070092// Given a uid/gid map of "inside1 outside1 length1, ...", and an id inside of
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070093// the user namespace, populate |id_out|. Returns true on success.
94bool GetUsernsOutsideId(const std::string& map, int id, int* id_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070095
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070096bool MakeDir(const base::FilePath& path, int uid, int gid, int mode);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070097
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070098bool TouchFile(const base::FilePath& path, int uid, int gid, int mode);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070099
100// Find a free loop device and attach it.
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -0700101bool LoopdevSetup(const base::FilePath& source, Loopdev* loopdev_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700102
103// Detach the specified loop device.
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -0700104bool LoopdevDetach(Loopdev* loopdev);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700105
106// Create a new device mapper target for the source.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700107bool DeviceMapperSetup(const base::FilePath& source,
108 const std::string& verity_cmdline,
109 base::FilePath* dm_path_out,
110 std::string* dm_name_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700111
112// Tear down the device mapper target.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700113bool DeviceMapperDetach(const std::string& dm_name);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700114
115// Match mount_one in minijail, mount one mountpoint with
116// consideration for combination of MS_BIND/MS_RDONLY flag.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700117bool MountExternal(const std::string& src,
118 const std::string& dest,
119 const std::string& type,
120 unsigned long flags,
121 const std::string& data);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700122
Luis Hector Chaveze03926a2017-09-28 17:28:49 -0700123// Creates a pipe using pipe2(2) and returns both ends as base::ScopedFDs.
124bool Pipe2(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe, int flags);
125
126// Creates a callback that will fork(2)+execve(2) the program specified by args.
127HookCallback CreateExecveCallback(base::FilePath filename,
128 std::vector<std::string> args,
129 base::ScopedFD stdin_fd,
130 base::ScopedFD stdout_fd,
131 base::ScopedFD stderr_fd);
132
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700133// Wraps a callback to be run in a subset of the container's namespaces.
134HookCallback AdaptCallbackToRunInNamespaces(HookCallback callback,
135 std::vector<int> nstypes);
136
Luis Hector Chavez92278e82017-10-16 11:30:27 -0700137// Similar to base::CreateDirectory, but allows specifying the created
138// directories' mode and owner.
139bool CreateDirectoryOwnedBy(const base::FilePath& full_path,
140 mode_t mode,
141 uid_t uid,
142 gid_t gid);
143
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700144} // namespace libcontainer
145
146#endif // LIBCONTAINER_LIBCONTAINER_UTIL_H_