blob: 9b1e02427ec48910e9370109a12f27e7d998af0f [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 Chavez835d39e2017-09-19 15:16:31 -070013#include <base/logging.h>
14#include <base/macros.h>
Luis Hector Chavez644d2042017-09-19 18:56:44 -070015#include <libminijail.h>
16
17#include "libcontainer/config.h"
18#include "libcontainer/libcontainer.h"
Luis Hector Chavez81efb332017-09-18 14:01:29 -070019
20namespace libcontainer {
21
Luis Hector Chavez835d39e2017-09-19 15:16:31 -070022// Simple class that saves errno.
23class SaveErrno {
24 public:
25 SaveErrno();
26 ~SaveErrno();
27
28 private:
29 const int saved_errno_;
30
31 DISALLOW_COPY_AND_ASSIGN(SaveErrno);
32};
33
34// The comma operator will discard the SaveErrno instance, but will keep it
35// alive until after the whole expression has been evaluated.
36#define PLOG_PRESERVE(verbose_level) \
37 ::libcontainer::SaveErrno(), PLOG(verbose_level)
38
Luis Hector Chavez644d2042017-09-19 18:56:44 -070039// WaitablePipe provides a way for one process to wait on another. This only
40// uses the read(2) and close(2) syscalls, so it can work even in a restrictive
41// environment. Each process must call only one of Wait() and Signal() exactly
42// once.
43struct WaitablePipe {
44 WaitablePipe();
45 ~WaitablePipe();
46
47 WaitablePipe(WaitablePipe&&);
48
49 // Waits for Signal() to be called.
50 void Wait();
51
52 // Notifies the process that called Wait() to continue running.
53 void Signal();
54
55 int pipe_fds[2];
56
57 private:
58 DISALLOW_COPY_AND_ASSIGN(WaitablePipe);
59};
60
61// HookState holds two WaitablePipes so that the container can wait for its
62// parent to run prestart hooks just prior to calling execve(2).
63class HookState {
64 public:
65 HookState();
66 ~HookState();
67
68 HookState(HookState&& state);
69
70 // Initializes this HookState so that WaitForHookAndRun() can be invoked and
71 // waited upon when |j| reaches |event|. Returns true on success.
72 bool InstallHook(minijail* j, minijail_hook_event_t event);
73
74 // Waits for the event specified in InstallHook() and invokes |callbacks| in
75 // the caller process. Returns true if all callbacks succeeded.
76 bool WaitForHookAndRun(const std::vector<HookCallback>& callbacks,
77 pid_t container_pid);
78
79 private:
80 // A function that can be passed to minijail_add_hook() that blocks the
81 // process in the container until the parent has finished running whatever
82 // operations are needed outside the container. This is not expected to be
83 // called directly.
84 static int WaitHook(void* payload);
85
86 bool installed_ = false;
87 WaitablePipe reached_pipe_;
88 WaitablePipe ready_pipe_;
89
90 DISALLOW_COPY_AND_ASSIGN(HookState);
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
94// the user namespace, return the equivalent outside id, or return < 0 on error.
95int GetUsernsOutsideId(const std::string& map, int id);
96
97int MakeDir(const base::FilePath& path, int uid, int gid, int mode);
98
99int TouchFile(const base::FilePath& path, int uid, int gid, int mode);
100
101// Find a free loop device and attach it.
102int LoopdevSetup(const base::FilePath& source,
103 base::FilePath* loopdev_path_out);
104
105// Detach the specified loop device.
106int LoopdevDetach(const base::FilePath& loopdev);
107
108// Create a new device mapper target for the source.
109int DeviceMapperSetup(const base::FilePath& source,
110 const std::string& verity_cmdline,
111 base::FilePath* dm_path_out,
112 std::string* dm_name_out);
113
114// Tear down the device mapper target.
115int DeviceMapperDetach(const std::string& dm_name);
116
117// Match mount_one in minijail, mount one mountpoint with
118// consideration for combination of MS_BIND/MS_RDONLY flag.
119int MountExternal(const std::string& src,
120 const std::string& dest,
121 const std::string& type,
122 unsigned long flags,
123 const std::string& data);
124
Luis Hector Chavez644d2042017-09-19 18:56:44 -0700125// Wraps a callback to be run in a subset of the container's namespaces.
126HookCallback AdaptCallbackToRunInNamespaces(HookCallback callback,
127 std::vector<int> nstypes);
128
Luis Hector Chavez81efb332017-09-18 14:01:29 -0700129} // namespace libcontainer
130
131#endif // LIBCONTAINER_LIBCONTAINER_UTIL_H_