blob: 4f5d116bbb4816a5c09218106aed67d10298e307 [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&&);
34
35 // Waits for Signal() to be called.
36 void Wait();
37
38 // Notifies the process that called Wait() to continue running.
39 void Signal();
40
41 int pipe_fds[2];
42
43 private:
44 DISALLOW_COPY_AND_ASSIGN(WaitablePipe);
45};
46
47// HookState holds two WaitablePipes so that the container can wait for its
48// parent to run prestart hooks just prior to calling execve(2).
49class HookState {
50 public:
51 HookState();
52 ~HookState();
53
54 HookState(HookState&& state);
55
56 // Initializes this HookState so that WaitForHookAndRun() can be invoked and
57 // waited upon when |j| reaches |event|. Returns true on success.
58 bool InstallHook(minijail* j, minijail_hook_event_t event);
59
60 // Waits for the event specified in InstallHook() and invokes |callbacks| in
61 // the caller process. Returns true if all callbacks succeeded.
62 bool WaitForHookAndRun(const std::vector<HookCallback>& callbacks,
63 pid_t container_pid);
64
65 private:
66 // A function that can be passed to minijail_add_hook() that blocks the
67 // process in the container until the parent has finished running whatever
68 // operations are needed outside the container. This is not expected to be
69 // called directly.
70 static int WaitHook(void* payload);
71
72 bool installed_ = false;
73 WaitablePipe reached_pipe_;
74 WaitablePipe ready_pipe_;
75
76 DISALLOW_COPY_AND_ASSIGN(HookState);
77};
78
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -070079// Loopdev represents an active loopback device.
80struct Loopdev {
81 // The path of the loopback device. e.g. /dev/loop1
82 base::FilePath path;
83
84 // An open file descriptor for the loopback device. Has the autoclear flag,
85 // such that the kernel will automatically remove it once all references to it
86 // are closed.
87 base::ScopedFD fd;
88
89 // Information about the loop device.
90 struct loop_info64 info;
91};
92
Luis Hector Chavez81efb332017-09-18 14:01:29 -070093// Given a uid/gid map of "inside1 outside1 length1, ...", and an id inside of
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070094// the user namespace, populate |id_out|. Returns true on success.
95bool GetUsernsOutsideId(const std::string& map, int id, int* id_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070096
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070097bool MakeDir(const base::FilePath& path, int uid, int gid, int mode);
Luis Hector Chavez81efb332017-09-18 14:01:29 -070098
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -070099bool TouchFile(const base::FilePath& path, int uid, int gid, int mode);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700100
101// Find a free loop device and attach it.
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -0700102bool LoopdevSetup(const base::FilePath& source, Loopdev* loopdev_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700103
104// Detach the specified loop device.
Luis Hector Chavez5cf71ed2018-05-07 14:45:43 -0700105bool LoopdevDetach(Loopdev* loopdev);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700106
107// Create a new device mapper target for the source.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700108bool DeviceMapperSetup(const base::FilePath& source,
109 const std::string& verity_cmdline,
110 base::FilePath* dm_path_out,
111 std::string* dm_name_out);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700112
113// Tear down the device mapper target.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700114bool DeviceMapperDetach(const std::string& dm_name);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700115
116// Match mount_one in minijail, mount one mountpoint with
117// consideration for combination of MS_BIND/MS_RDONLY flag.
Luis Hector Chavez1f7e60c2017-09-27 22:03:48 -0700118bool MountExternal(const std::string& src,
119 const std::string& dest,
120 const std::string& type,
121 unsigned long flags,
122 const std::string& data);
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700123
Luis Hector Chaveze03926a2017-09-28 17:28:49 -0700124// Creates a pipe using pipe2(2) and returns both ends as base::ScopedFDs.
125bool Pipe2(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe, int flags);
126
127// Creates a callback that will fork(2)+execve(2) the program specified by args.
128HookCallback CreateExecveCallback(base::FilePath filename,
129 std::vector<std::string> args,
130 base::ScopedFD stdin_fd,
131 base::ScopedFD stdout_fd,
132 base::ScopedFD stderr_fd);
133
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700134// Wraps a callback to be run in a subset of the container's namespaces.
135HookCallback AdaptCallbackToRunInNamespaces(HookCallback callback,
136 std::vector<int> nstypes);
137
Luis Hector Chavez92278e82017-10-16 11:30:27 -0700138// Similar to base::CreateDirectory, but allows specifying the created
139// directories' mode and owner.
140bool CreateDirectoryOwnedBy(const base::FilePath& full_path,
141 mode_t mode,
142 uid_t uid,
143 gid_t gid);
144
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700145} // namespace libcontainer
146
147#endif // LIBCONTAINER_LIBCONTAINER_UTIL_H_