]>
Commit | Line | Data |
---|---|---|
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 | |
9 | under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
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 | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
22 | #include <sys/mount.h> | |
23 | #include <errno.h> | |
24 | #include <sys/stat.h> | |
25 | #include <stdlib.h> | |
26 | #include <string.h> | |
27 | #include <libgen.h> | |
28 | #include <assert.h> | |
5c0532d1 | 29 | #include <unistd.h> |
8e274523 LP |
30 | |
31 | #include "mount-setup.h" | |
32 | #include "log.h" | |
c9af1080 LP |
33 | #include "macro.h" |
34 | #include "util.h" | |
5275d3c1 | 35 | #include "label.h" |
8e274523 | 36 | |
ca714c0e LP |
37 | typedef struct MountPoint { |
38 | const char *what; | |
39 | const char *where; | |
40 | const char *type; | |
41 | const char *options; | |
42 | unsigned long flags; | |
2076ca54 | 43 | bool fatal; |
ca714c0e LP |
44 | } MountPoint; |
45 | ||
46 | static const MountPoint mount_table[] = { | |
77d5f105 LP |
47 | { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true }, |
48 | { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true }, | |
49 | { "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID, true }, | |
50 | { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NOEXEC|MS_NODEV, true }, | |
51 | { "devpts", "/dev/pts", "devpts", NULL, MS_NOSUID|MS_NOEXEC, false }, | |
52 | { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true }, | |
53 | { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, true }, | |
8e274523 LP |
54 | }; |
55 | ||
949c6510 LP |
56 | /* These are API file systems that might be mounted by other software, |
57 | * we just list them here so that we know that we should igore them */ | |
58 | ||
59 | static const char * const ignore_paths[] = { | |
60 | "/selinux", | |
61 | "/proc/bus/usb", | |
62 | "/var/lib/nfs/rpc_pipefs", | |
63 | "/proc/fs/nfsd" | |
64 | }; | |
65 | ||
dad08730 LP |
66 | bool mount_point_is_api(const char *path) { |
67 | unsigned i; | |
68 | ||
69 | /* Checks if this mount point is considered "API", and hence | |
70 | * should be ignored */ | |
71 | ||
ca714c0e | 72 | for (i = 0; i < ELEMENTSOF(mount_table); i ++) |
449ddb2d | 73 | if (path_equal(path, mount_table[i].where)) |
dad08730 LP |
74 | return true; |
75 | ||
949c6510 | 76 | for (i = 0; i < ELEMENTSOF(ignore_paths); i++) |
449ddb2d | 77 | if (path_equal(path, ignore_paths[i])) |
949c6510 LP |
78 | return true; |
79 | ||
77d5f105 | 80 | return path_startswith(path, "/sys/fs/cgroup/"); |
dad08730 LP |
81 | } |
82 | ||
ca714c0e | 83 | static int mount_one(const MountPoint *p) { |
8e274523 LP |
84 | int r; |
85 | ||
ca714c0e | 86 | assert(p); |
8e274523 | 87 | |
8d567588 | 88 | if ((r = path_is_mount_point(p->where)) < 0) |
8e274523 LP |
89 | return r; |
90 | ||
91 | if (r > 0) | |
92 | return 0; | |
93 | ||
a04f58d6 LP |
94 | /* The access mode here doesn't really matter too much, since |
95 | * the mounted file system will take precedence anyway. */ | |
ca714c0e | 96 | mkdir_p(p->where, 0755); |
a04f58d6 | 97 | |
8e274523 | 98 | log_debug("Mounting %s to %s of type %s with options %s.", |
ca714c0e LP |
99 | p->what, |
100 | p->where, | |
101 | p->type, | |
102 | strna(p->options)); | |
103 | ||
104 | if (mount(p->what, | |
105 | p->where, | |
106 | p->type, | |
107 | p->flags, | |
108 | p->options) < 0) { | |
109 | log_error("Failed to mount %s: %s", p->where, strerror(errno)); | |
2076ca54 | 110 | return p->fatal ? -errno : 0; |
8e274523 LP |
111 | } |
112 | ||
5275d3c1 LP |
113 | label_fix(p->where); |
114 | ||
8e274523 LP |
115 | return 0; |
116 | } | |
117 | ||
2076ca54 LP |
118 | static int mount_cgroup_controllers(void) { |
119 | int r; | |
120 | FILE *f; | |
121 | char buf [256]; | |
122 | ||
670802d4 | 123 | /* Mount all available cgroup controllers that are built into the kernel. */ |
2076ca54 LP |
124 | |
125 | if (!(f = fopen("/proc/cgroups", "re"))) | |
126 | return -ENOENT; | |
127 | ||
128 | /* Ignore the header line */ | |
bab45044 | 129 | (void) fgets(buf, sizeof(buf), f); |
2076ca54 LP |
130 | |
131 | for (;;) { | |
132 | MountPoint p; | |
133 | char *controller, *where; | |
134 | ||
135 | if (fscanf(f, "%ms %*i %*i %*i", &controller) != 1) { | |
136 | ||
137 | if (feof(f)) | |
138 | break; | |
139 | ||
140 | log_error("Failed to parse /proc/cgroups."); | |
141 | r = -EIO; | |
142 | goto finish; | |
143 | } | |
144 | ||
77d5f105 | 145 | if (asprintf(&where, "/sys/fs/cgroup/%s", controller) < 0) { |
2076ca54 LP |
146 | free(controller); |
147 | r = -ENOMEM; | |
148 | goto finish; | |
149 | } | |
150 | ||
151 | zero(p); | |
152 | p.what = "cgroup"; | |
153 | p.where = where; | |
154 | p.type = "cgroup"; | |
155 | p.options = controller; | |
156 | p.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV; | |
157 | p.fatal = false; | |
158 | ||
159 | r = mount_one(&p); | |
160 | free(controller); | |
161 | free(where); | |
162 | ||
163 | if (r < 0) | |
164 | goto finish; | |
165 | } | |
166 | ||
167 | r = 0; | |
168 | ||
169 | finish: | |
170 | fclose(f); | |
171 | ||
172 | return r; | |
173 | } | |
174 | ||
5c0532d1 LP |
175 | static int symlink_and_label(const char *old_path, const char *new_path) { |
176 | int r; | |
177 | ||
178 | assert(old_path); | |
179 | assert(new_path); | |
180 | ||
181 | if ((r = label_symlinkfile_set(new_path)) < 0) | |
182 | return r; | |
183 | ||
184 | if (symlink(old_path, new_path) < 0) | |
185 | r = -errno; | |
186 | ||
187 | label_file_clear(); | |
188 | ||
189 | return r; | |
190 | } | |
191 | ||
8e274523 | 192 | int mount_setup(void) { |
5c0532d1 LP |
193 | |
194 | const char *symlinks = | |
195 | "/proc/kcore\0" "/dev/core\0" | |
196 | "/proc/self/fd\0" "/dev/fd\0" | |
197 | "/proc/self/fd/0\0" "/dev/stdin\0" | |
198 | "/proc/self/fd/1\0" "/dev/stdout\0" | |
199 | "/proc/self/fd/2\0" "/dev/stderr\0" | |
200 | "\0"; | |
201 | ||
8e274523 | 202 | int r; |
dad08730 | 203 | unsigned i; |
5c0532d1 | 204 | const char *j, *k; |
8e274523 | 205 | |
ca714c0e LP |
206 | for (i = 0; i < ELEMENTSOF(mount_table); i ++) |
207 | if ((r = mount_one(mount_table+i)) < 0) | |
8e274523 LP |
208 | return r; |
209 | ||
5c0532d1 LP |
210 | /* Create a few default symlinks, which are normally created |
211 | * bei udevd, but some scripts might need them before we start | |
212 | * udevd. */ | |
213 | ||
214 | NULSTR_FOREACH_PAIR(j, k, symlinks) | |
215 | symlink_and_label(j, k); | |
216 | ||
2076ca54 | 217 | return mount_cgroup_controllers(); |
8e274523 | 218 | } |