]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/mount-setup.c
util-lib: move web-related calls into web-util.[ch]
[thirdparty/systemd.git] / src / core / mount-setup.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8e274523
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
8e274523
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
8e274523 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
8e274523
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <sys/mount.h>
23#include <errno.h>
8e274523 24#include <stdlib.h>
5c0532d1 25#include <unistd.h>
1829dc9d 26#include <ftw.h>
8e274523 27
64824462 28#include "bus-util.h"
4349cd7c
LP
29#include "cgroup-util.h"
30#include "dev-setup.h"
31#include "efivars.h"
32#include "label.h"
8e274523 33#include "log.h"
c9af1080 34#include "macro.h"
4349cd7c 35#include "missing.h"
49e942b2 36#include "mkdir.h"
4349cd7c
LP
37#include "mount-setup.h"
38#include "mount-util.h"
9eb977db 39#include "path-util.h"
4349cd7c 40#include "set.h"
8552b176 41#include "smack-util.h"
4349cd7c
LP
42#include "strv.h"
43#include "util.h"
44#include "virt.h"
bef2733f 45
6aa220e0
KS
46typedef enum MountMode {
47 MNT_NONE = 0,
48 MNT_FATAL = 1 << 0,
49 MNT_IN_CONTAINER = 1 << 1,
50} MountMode;
51
ca714c0e
LP
52typedef struct MountPoint {
53 const char *what;
54 const char *where;
55 const char *type;
56 const char *options;
57 unsigned long flags;
6aa220e0
KS
58 bool (*condition_fn)(void);
59 MountMode mode;
ca714c0e
LP
60} MountPoint;
61
4ef31082 62/* The first three entries we might need before SELinux is up. The
160481f6 63 * fourth (securityfs) is needed by IMA to load a custom policy. The
7c96ab1d
LP
64 * other ones we can delay until SELinux and IMA are loaded. When
65 * SMACK is enabled we need smackfs, too, so it's a fifth one. */
66#ifdef HAVE_SMACK
ffbd2c4d 67#define N_EARLY_MOUNT 5
7c96ab1d
LP
68#else
69#define N_EARLY_MOUNT 4
70#endif
4ef31082 71
ca714c0e 72static const MountPoint mount_table[] = {
68d4c452
LP
73 { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
74 NULL, MNT_FATAL|MNT_IN_CONTAINER },
75 { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
76 NULL, MNT_FATAL|MNT_IN_CONTAINER },
77 { "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME,
78 NULL, MNT_FATAL|MNT_IN_CONTAINER },
79 { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
80 NULL, MNT_NONE },
d407c940 81#ifdef HAVE_SMACK
68d4c452
LP
82 { "smackfs", "/sys/fs/smackfs", "smackfs", "smackfsdef=*", MS_NOSUID|MS_NOEXEC|MS_NODEV,
83 mac_smack_use, MNT_FATAL },
84 { "tmpfs", "/dev/shm", "tmpfs", "mode=1777,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
85 mac_smack_use, MNT_FATAL },
d407c940 86#endif
68d4c452
LP
87 { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
88 NULL, MNT_FATAL|MNT_IN_CONTAINER },
89 { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC,
90 NULL, MNT_IN_CONTAINER },
d407c940 91#ifdef HAVE_SMACK
68d4c452
LP
92 { "tmpfs", "/run", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
93 mac_smack_use, MNT_FATAL },
d407c940 94#endif
68d4c452
LP
95 { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
96 NULL, MNT_FATAL|MNT_IN_CONTAINER },
efdb0237
LP
97 { "cgroup", "/sys/fs/cgroup", "cgroup", "__DEVEL__sane_behavior", MS_NOSUID|MS_NOEXEC|MS_NODEV,
98 cg_is_unified_wanted, MNT_FATAL|MNT_IN_CONTAINER },
68d4c452 99 { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
efdb0237 100 cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
68d4c452 101 { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV,
efdb0237 102 cg_is_legacy_wanted, MNT_IN_CONTAINER },
68d4c452 103 { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV,
efdb0237 104 cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
68d4c452
LP
105 { "pstore", "/sys/fs/pstore", "pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
106 NULL, MNT_NONE },
c06bf414 107#ifdef ENABLE_EFI
68d4c452
LP
108 { "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
109 is_efi_boot, MNT_NONE },
c06bf414 110#endif
63cc4c31 111 { "kdbusfs", "/sys/fs/kdbus", "kdbusfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
1f49dffc 112 is_kdbus_wanted, MNT_IN_CONTAINER },
63cc4c31
DM
113};
114
949c6510 115/* These are API file systems that might be mounted by other software,
46ff0ed7 116 * we just list them here so that we know that we should ignore them */
949c6510 117
eaeb18db
LP
118static const char ignore_paths[] =
119 /* SELinux file systems */
120 "/sys/fs/selinux\0"
eaeb18db
LP
121 /* Container bind mounts */
122 "/proc/sys\0"
123 "/dev/console\0"
c481f78b 124 "/proc/kmsg\0";
949c6510 125
dad08730
LP
126bool mount_point_is_api(const char *path) {
127 unsigned i;
128
129 /* Checks if this mount point is considered "API", and hence
130 * should be ignored */
131
ca714c0e 132 for (i = 0; i < ELEMENTSOF(mount_table); i ++)
449ddb2d 133 if (path_equal(path, mount_table[i].where))
dad08730
LP
134 return true;
135
57f2a956
KS
136 return path_startswith(path, "/sys/fs/cgroup/");
137}
138
139bool mount_point_ignore(const char *path) {
eaeb18db 140 const char *i;
57f2a956 141
eaeb18db
LP
142 NULSTR_FOREACH(i, ignore_paths)
143 if (path_equal(path, i))
949c6510
LP
144 return true;
145
57f2a956 146 return false;
dad08730
LP
147}
148
4ef31082 149static int mount_one(const MountPoint *p, bool relabel) {
8e274523
LP
150 int r;
151
ca714c0e 152 assert(p);
8e274523 153
6aa220e0
KS
154 if (p->condition_fn && !p->condition_fn())
155 return 0;
156
51b4af2c 157 /* Relabel first, just in case */
4ef31082 158 if (relabel)
c9bc0764 159 label_fix(p->where, true, true);
51b4af2c 160
e26d6ce5 161 r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
64f75d7a 162 if (r < 0 && r != -ENOENT)
8e274523 163 return r;
8e274523 164 if (r > 0)
51b4af2c 165 return 0;
8e274523 166
c481f78b 167 /* Skip securityfs in a container */
75f86906 168 if (!(p->mode & MNT_IN_CONTAINER) && detect_container() > 0)
c481f78b
LP
169 return 0;
170
a04f58d6
LP
171 /* The access mode here doesn't really matter too much, since
172 * the mounted file system will take precedence anyway. */
c4bfd169
LP
173 if (relabel)
174 mkdir_p_label(p->where, 0755);
175 else
176 mkdir_p(p->where, 0755);
a04f58d6 177
8e274523 178 log_debug("Mounting %s to %s of type %s with options %s.",
ca714c0e
LP
179 p->what,
180 p->where,
181 p->type,
182 strna(p->options));
183
184 if (mount(p->what,
185 p->where,
186 p->type,
187 p->flags,
188 p->options) < 0) {
99a17ada 189 log_full((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, "Failed to mount %s at %s: %m", p->type, p->where);
6aa220e0 190 return (p->mode & MNT_FATAL) ? -errno : 0;
8e274523
LP
191 }
192
51b4af2c 193 /* Relabel again, since we now mounted something fresh here */
4ef31082 194 if (relabel)
c9bc0764 195 label_fix(p->where, false, false);
5275d3c1 196
0c85a4f3 197 return 1;
8e274523
LP
198}
199
4ef31082
LP
200int mount_setup_early(void) {
201 unsigned i;
202 int r = 0;
203
204 assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table));
205
206 /* Do a minimal mount of /proc and friends to enable the most
207 * basic stuff, such as SELinux */
208 for (i = 0; i < N_EARLY_MOUNT; i ++) {
209 int j;
210
211 j = mount_one(mount_table + i, false);
7ff307bc 212 if (j != 0 && r >= 0)
4ef31082
LP
213 r = j;
214 }
215
216 return r;
217}
218
0c85a4f3 219int mount_cgroup_controllers(char ***join_controllers) {
a6b26d90 220 _cleanup_set_free_free_ Set *controllers = NULL;
a641dcd9 221 int r;
2076ca54 222
efdb0237
LP
223 if (!cg_is_legacy_wanted())
224 return 0;
225
670802d4 226 /* Mount all available cgroup controllers that are built into the kernel. */
2076ca54 227
d5099efc 228 controllers = set_new(&string_hash_ops);
a6b26d90
ZJS
229 if (!controllers)
230 return log_oom();
0c85a4f3 231
b12afc8c
LP
232 r = cg_kernel_controllers(controllers);
233 if (r < 0)
234 return log_error_errno(r, "Failed to enumerate cgroup controllers: %m");
0c85a4f3
LP
235
236 for (;;) {
a641dcd9 237 _cleanup_free_ char *options = NULL, *controller = NULL, *where = NULL;
a6b26d90
ZJS
238 MountPoint p = {
239 .what = "cgroup",
240 .type = "cgroup",
241 .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV,
242 .mode = MNT_IN_CONTAINER,
243 };
0c85a4f3
LP
244 char ***k = NULL;
245
246 controller = set_steal_first(controllers);
247 if (!controller)
248 break;
249
250 if (join_controllers)
251 for (k = join_controllers; *k; k++)
252 if (strv_find(*k, controller))
253 break;
254
255 if (k && *k) {
256 char **i, **j;
257
258 for (i = *k, j = *k; *i; i++) {
259
260 if (!streq(*i, controller)) {
a641dcd9 261 _cleanup_free_ char *t;
0c85a4f3
LP
262
263 t = set_remove(controllers, *i);
264 if (!t) {
265 free(*i);
266 continue;
267 }
0c85a4f3
LP
268 }
269
270 *(j++) = *i;
271 }
272
273 *j = NULL;
274
275 options = strv_join(*k, ",");
a6b26d90
ZJS
276 if (!options)
277 return log_oom();
0c85a4f3
LP
278 } else {
279 options = controller;
280 controller = NULL;
281 }
282
a641dcd9
LP
283 where = strappend("/sys/fs/cgroup/", options);
284 if (!where)
285 return log_oom();
286
287 p.where = where;
0c85a4f3 288 p.options = options;
2076ca54 289
4ef31082 290 r = mount_one(&p, true);
a6b26d90
ZJS
291 if (r < 0)
292 return r;
0c85a4f3
LP
293
294 if (r > 0 && k && *k) {
295 char **i;
296
297 for (i = *k; *i; i++) {
a641dcd9
LP
298 _cleanup_free_ char *t = NULL;
299
300 t = strappend("/sys/fs/cgroup/", *i);
301 if (!t)
302 return log_oom();
0c85a4f3
LP
303
304 r = symlink(options, t);
4a62c710
MS
305 if (r < 0 && errno != EEXIST)
306 return log_error_errno(errno, "Failed to create symlink %s: %m", t);
f8c1a81c
SW
307#ifdef SMACK_RUN_LABEL
308 r = mac_smack_copy(t, options);
309 if (r < 0 && r != -EOPNOTSUPP)
310 return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", options, t);
311#endif
0c85a4f3
LP
312 }
313 }
2076ca54
LP
314 }
315
679142ce
LP
316 /* Now that we mounted everything, let's make the tmpfs the
317 * cgroup file systems are mounted into read-only. */
b12afc8c 318 (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");
679142ce 319
a6b26d90 320 return 0;
2076ca54
LP
321}
322
0fff82e5 323#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
1829dc9d
LP
324static int nftw_cb(
325 const char *fpath,
326 const struct stat *sb,
327 int tflag,
328 struct FTW *ftwbuf) {
329
9fe117ea 330 /* No need to label /dev twice in a row... */
edb49778
LP
331 if (_unlikely_(ftwbuf->level == 0))
332 return FTW_CONTINUE;
333
c9bc0764 334 label_fix(fpath, false, false);
af65c248 335
edb49778 336 /* /run/initramfs is static data and big, no need to
af65c248 337 * dynamically relabel its contents at boot... */
edb49778
LP
338 if (_unlikely_(ftwbuf->level == 1 &&
339 tflag == FTW_D &&
340 streq(fpath, "/run/initramfs")))
341 return FTW_SKIP_SUBTREE;
9fe117ea 342
edb49778 343 return FTW_CONTINUE;
1829dc9d 344};
0fff82e5 345#endif
1829dc9d 346
0b3325e7 347int mount_setup(bool loaded_policy) {
dad08730 348 unsigned i;
68d4c452 349 int r = 0;
8e274523 350
4ef31082 351 for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
68d4c452 352 int j;
4ef31082 353
68d4c452 354 j = mount_one(mount_table + i, loaded_policy);
7ff307bc 355 if (j != 0 && r >= 0)
68d4c452 356 r = j;
4ef31082 357 }
8e274523 358
68d4c452
LP
359 if (r < 0)
360 return r;
361
0fff82e5 362#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
f1d19aa4
LP
363 /* Nodes in devtmpfs and /run need to be manually updated for
364 * the appropriate labels, after mounting. The other virtual
365 * API file systems like /sys and /proc do not need that, they
366 * use the same label for all their files. */
0b3325e7
LP
367 if (loaded_policy) {
368 usec_t before_relabel, after_relabel;
369 char timespan[FORMAT_TIMESPAN_MAX];
370
371 before_relabel = now(CLOCK_MONOTONIC);
372
edb49778
LP
373 nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
374 nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
0b3325e7
LP
375
376 after_relabel = now(CLOCK_MONOTONIC);
377
378 log_info("Relabelled /dev and /run in %s.",
2fa4092c 379 format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0));
3bbecb2f 380 }
0fff82e5 381#endif
1829dc9d 382
5c0532d1 383 /* Create a few default symlinks, which are normally created
f1d19aa4 384 * by udevd, but some scripts might need them before we start
5c0532d1 385 * udevd. */
03cfe0d5 386 dev_setup(NULL, UID_INVALID, GID_INVALID);
5c0532d1 387
b3ac5f8c
LP
388 /* Mark the root directory as shared in regards to mount
389 * propagation. The kernel defaults to "private", but we think
390 * it makes more sense to have a default of "shared" so that
391 * nspawn and the container tools work out of the box. If
392 * specific setups need other settings they can reset the
393 * propagation mode to private if needed. */
75f86906 394 if (detect_container() <= 0)
c481f78b 395 if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
56f64d95 396 log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");
b3ac5f8c 397
66e41181
LP
398 /* Create a few directories we always want around, Note that
399 * sd_booted() checks for /run/systemd/system, so this mkdir
400 * really needs to stay for good, otherwise software that
401 * copied sd-daemon.c into their sources will misdetect
402 * systemd. */
d2e54fae
KS
403 mkdir_label("/run/systemd", 0755);
404 mkdir_label("/run/systemd/system", 0755);
c17ec25e 405 mkdir_label("/run/systemd/inaccessible", 0000);
b925e726 406
0c85a4f3 407 return 0;
8e274523 408}