]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/storage_utils.c
log: change DEBUG, INFO, TRACE, NOTICE macro using strerror to SYS* macro
[mirror_lxc.git] / src / lxc / storage / storage_utils.c
1 /*
2 * lxc: linux Container library
3 *
4 * Copyright © 2017 Canonical Ltd.
5 *
6 * Authors:
7 * Christian Brauner <christian.brauner@ubuntu.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #define _GNU_SOURCE
25 #include <dirent.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <grp.h>
29 #include <inttypes.h>
30 #include <libgen.h>
31 #include <sched.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/mount.h>
37 #include <sys/prctl.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/wait.h>
41
42 #include "log.h"
43 #include "nbd.h"
44 #include "parse.h"
45 #include "storage.h"
46 #include "storage_utils.h"
47 #include "utils.h"
48
49 #ifndef HAVE_STRLCPY
50 #include "include/strlcpy.h"
51 #endif
52
53 #ifndef BLKGETSIZE64
54 #define BLKGETSIZE64 _IOR(0x12, 114, size_t)
55 #endif
56
57 lxc_log_define(storage_utils, lxc);
58
59 /* the bulk of this needs to become a common helper */
60 char *dir_new_path(char *src, const char *oldname, const char *name,
61 const char *oldpath, const char *lxcpath)
62 {
63 char *ret, *p, *p2;
64 int l1, l2, nlen;
65
66 nlen = strlen(src) + 1;
67 l1 = strlen(oldpath);
68 p = src;
69 /* if src starts with oldpath, look for oldname only after
70 * that path */
71 if (strncmp(src, oldpath, l1) == 0) {
72 p += l1;
73 nlen += (strlen(lxcpath) - l1);
74 }
75 l2 = strlen(oldname);
76 while ((p = strstr(p, oldname)) != NULL) {
77 p += l2;
78 nlen += strlen(name) - l2;
79 }
80
81 ret = malloc(nlen);
82 if (!ret)
83 return NULL;
84
85 p = ret;
86 if (strncmp(src, oldpath, l1) == 0) {
87 p += sprintf(p, "%s", lxcpath);
88 src += l1;
89 }
90
91 while ((p2 = strstr(src, oldname)) != NULL) {
92 size_t retlen;
93
94 /* copy text up to oldname */
95 retlen = strlcpy(p, src, p2 - src);
96 if (retlen >= p2 - src) {
97 free(ret);
98 return NULL;
99 }
100
101 /* move target pointer (p) */
102 p += p2 - src;
103 /* print new name in place of oldname */
104 p += sprintf(p, "%s", name);
105 /* move src to end of oldname */
106 src = p2 + l2;
107 }
108
109 /* copy the rest of src */
110 sprintf(p, "%s", src);
111 return ret;
112 }
113
114 /*
115 * attach_block_device returns true if all went well,
116 * meaning either a block device was attached or was not
117 * needed. It returns false if something went wrong and
118 * container startup should be stopped.
119 */
120 bool attach_block_device(struct lxc_conf *conf)
121 {
122 char *path;
123
124 if (!conf->rootfs.path)
125 return true;
126
127 path = conf->rootfs.path;
128 if (!requires_nbd(path))
129 return true;
130
131 path = strchr(path, ':');
132 if (!path)
133 return false;
134
135 path++;
136 if (!attach_nbd(path, conf))
137 return false;
138
139 return true;
140 }
141
142 /*
143 * return block size of dev->src in units of bytes
144 */
145 int blk_getsize(struct lxc_storage *bdev, uint64_t *size)
146 {
147 int fd, ret;
148 const char *src;
149
150 src = lxc_storage_get_path(bdev->src, bdev->type);
151 fd = open(src, O_RDONLY);
152 if (fd < 0)
153 return -1;
154
155 /* size of device in bytes */
156 ret = ioctl(fd, BLKGETSIZE64, size);
157 close(fd);
158 return ret;
159 }
160
161 void detach_block_device(struct lxc_conf *conf)
162 {
163 if (conf->nbd_idx != -1)
164 detach_nbd_idx(conf->nbd_idx);
165 }
166
167 /*
168 * Given a lxc_storage (presumably blockdev-based), detect the fstype
169 * by trying mounting (in a private mntns) it.
170 * @lxc_storage: bdev to investigate
171 * @type: preallocated char* in which to write the fstype
172 * @len: length of passed in char*
173 * Returns length of fstype, of -1 on error
174 */
175 int detect_fs(struct lxc_storage *bdev, char *type, int len)
176 {
177 int ret;
178 int p[2];
179 size_t linelen;
180 pid_t pid;
181 FILE *f;
182 char *sp1, *sp2, *sp3;
183 const char *l, *srcdev;
184 char devpath[MAXPATHLEN];
185 char *line = NULL;
186
187 if (!bdev || !bdev->src || !bdev->dest)
188 return -1;
189
190 srcdev = lxc_storage_get_path(bdev->src, bdev->type);
191
192 ret = pipe(p);
193 if (ret < 0)
194 return -1;
195
196 if ((pid = fork()) < 0)
197 return -1;
198
199 if (pid > 0) {
200 int status;
201 close(p[1]);
202 memset(type, 0, len);
203 ret = read(p[0], type, len - 1);
204 close(p[0]);
205 if (ret < 0) {
206 SYSERROR("error reading from pipe");
207 wait(&status);
208 return -1;
209 } else if (ret == 0) {
210 ERROR("child exited early - fstype not found");
211 wait(&status);
212 return -1;
213 }
214 wait(&status);
215 type[len - 1] = '\0';
216 INFO("detected fstype %s for %s", type, srcdev);
217 return ret;
218 }
219
220 if (unshare(CLONE_NEWNS) < 0)
221 exit(1);
222
223 if (detect_shared_rootfs()) {
224 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
225 SYSERROR("Failed to make / rslave");
226 ERROR("Continuing...");
227 }
228 }
229
230 ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
231 if (ret < 0) {
232 ERROR("failed mounting %s onto %s to detect fstype", srcdev,
233 bdev->dest);
234 exit(1);
235 }
236
237 l = linkderef(srcdev, devpath);
238 if (!l)
239 exit(1);
240 f = fopen("/proc/self/mounts", "r");
241 if (!f)
242 exit(1);
243
244 while (getline(&line, &linelen, f) != -1) {
245 sp1 = strchr(line, ' ');
246 if (!sp1)
247 exit(1);
248 *sp1 = '\0';
249 if (strcmp(line, l))
250 continue;
251 sp2 = strchr(sp1 + 1, ' ');
252 if (!sp2)
253 exit(1);
254 *sp2 = '\0';
255 sp3 = strchr(sp2 + 1, ' ');
256 if (!sp3)
257 exit(1);
258 *sp3 = '\0';
259 sp2++;
260 if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
261 exit(1);
262
263 exit(0);
264 }
265
266 exit(1);
267 }
268
269 int do_mkfs_exec_wrapper(void *args)
270 {
271 int ret;
272 char *mkfs;
273 char **data = args;
274 /* strlen("mkfs.")
275 * +
276 * strlen(data[0])
277 * +
278 * \0
279 */
280 size_t len = 5 + strlen(data[0]) + 1;
281
282 mkfs = malloc(len);
283 if (!mkfs)
284 return -1;
285
286 ret = snprintf(mkfs, len, "mkfs.%s", data[0]);
287 if (ret < 0 || (size_t)ret >= len) {
288 free(mkfs);
289 return -1;
290 }
291
292 TRACE("executing \"%s %s\"", mkfs, data[1]);
293 execlp(mkfs, mkfs, data[1], (char *)NULL);
294 SYSERROR("failed to run \"%s %s \"", mkfs, data[1]);
295 free(mkfs);
296 return -1;
297 }
298
299 /*
300 * This will return 1 for physical disks, qemu-nbd, loop, etc right now only lvm
301 * is a block device.
302 */
303 int is_blktype(struct lxc_storage *b)
304 {
305 if (strcmp(b->type, "lvm") == 0)
306 return 1;
307
308 return 0;
309 }
310
311 int mount_unknown_fs(const char *rootfs, const char *target,
312 const char *options)
313 {
314 size_t i;
315 int ret;
316 struct cbarg {
317 const char *rootfs;
318 const char *target;
319 const char *options;
320 } cbarg = {
321 .rootfs = rootfs,
322 .target = target,
323 .options = options,
324 };
325
326 /*
327 * find the filesystem type with brute force:
328 * first we check with /etc/filesystems, in case the modules
329 * are auto-loaded and fall back to the supported kernel fs
330 */
331 char *fsfile[] = {
332 "/etc/filesystems",
333 "/proc/filesystems",
334 };
335
336 for (i = 0; i < sizeof(fsfile) / sizeof(fsfile[0]); i++) {
337 if (access(fsfile[i], F_OK))
338 continue;
339
340 ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
341 if (ret < 0) {
342 ERROR("failed to parse '%s'", fsfile[i]);
343 return -1;
344 }
345
346 if (ret)
347 return 0;
348 }
349
350 ERROR("failed to determine fs type for '%s'", rootfs);
351 return -1;
352 }
353
354 /*
355 * These are copied from conf.c. However as conf.c will be moved to using
356 * the callback system, they can be pulled from there eventually, so we
357 * don't need to pollute utils.c with these low level functions
358 */
359 int find_fstype_cb(char *buffer, void *data)
360 {
361 struct cbarg {
362 const char *rootfs;
363 const char *target;
364 const char *options;
365 } *cbarg = data;
366
367 unsigned long mntflags;
368 char *mntdata;
369 char *fstype;
370
371 /* we don't try 'nodev' entries */
372 if (strstr(buffer, "nodev"))
373 return 0;
374
375 fstype = buffer;
376 fstype += lxc_char_left_gc(fstype, strlen(fstype));
377 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
378
379 DEBUG("trying to mount '%s'->'%s' with fstype '%s'", cbarg->rootfs,
380 cbarg->target, fstype);
381
382 if (parse_mntopts(cbarg->options, &mntflags, &mntdata) < 0) {
383 free(mntdata);
384 return 0;
385 }
386
387 if (mount(cbarg->rootfs, cbarg->target, fstype, mntflags, mntdata)) {
388 SYSDEBUG("mount failed with error");
389 free(mntdata);
390 return 0;
391 }
392
393 free(mntdata);
394
395 INFO("mounted '%s' on '%s', with fstype '%s'", cbarg->rootfs,
396 cbarg->target, fstype);
397
398 return 1;
399 }
400
401 const char *linkderef(const char *path, char *dest)
402 {
403 struct stat sbuf;
404 ssize_t ret;
405
406 ret = stat(path, &sbuf);
407 if (ret < 0)
408 return NULL;
409
410 if (!S_ISLNK(sbuf.st_mode))
411 return path;
412
413 ret = readlink(path, dest, MAXPATHLEN);
414 if (ret < 0) {
415 SYSERROR("error reading link %s", path);
416 return NULL;
417 } else if (ret >= MAXPATHLEN) {
418 ERROR("link in %s too long", path);
419 return NULL;
420 }
421 dest[ret] = '\0';
422
423 return dest;
424 }
425
426 /*
427 * is an unprivileged user allowed to make this kind of snapshot
428 */
429 bool unpriv_snap_allowed(struct lxc_storage *b, const char *t, bool snap,
430 bool maybesnap)
431 {
432 if (!t) {
433 /* New type will be same as original (unless snap && b->type ==
434 * dir, in which case it will be overlayfs -- which is also
435 * allowed).
436 */
437 if (strcmp(b->type, "dir") == 0 ||
438 strcmp(b->type, "overlay") == 0 ||
439 strcmp(b->type, "overlayfs") == 0 ||
440 strcmp(b->type, "btrfs") == 0 ||
441 strcmp(b->type, "loop") == 0)
442 return true;
443
444 return false;
445 }
446
447 /* Unprivileged users can copy and snapshot dir, overlayfs, and loop.
448 * In particular, not zfs, btrfs, or lvm.
449 */
450 if (strcmp(t, "dir") == 0 ||
451 strcmp(t, "overlay") == 0 ||
452 strcmp(t, "overlayfs") == 0 ||
453 strcmp(t, "btrfs") == 0 ||
454 strcmp(t, "loop") == 0)
455 return true;
456
457 return false;
458 }
459
460 bool is_valid_storage_type(const char *type)
461 {
462 if (strcmp(type, "dir") == 0 ||
463 strcmp(type, "btrfs") == 0 ||
464 strcmp(type, "loop") == 0 ||
465 strcmp(type, "lvm") == 0 ||
466 strcmp(type, "nbd") == 0 ||
467 strcmp(type, "overlay") == 0 ||
468 strcmp(type, "overlayfs") == 0 ||
469 strcmp(type, "rbd") == 0 ||
470 strcmp(type, "zfs") == 0)
471 return true;
472
473 return false;
474 }
475
476 int storage_destroy_wrapper(void *data)
477 {
478 struct lxc_conf *conf = data;
479
480 if (setgid(0) < 0) {
481 ERROR("Failed to setgid to 0");
482 return -1;
483 }
484
485 if (setgroups(0, NULL) < 0)
486 WARN("Failed to clear groups");
487
488 if (setuid(0) < 0) {
489 ERROR("Failed to setuid to 0");
490 return -1;
491 }
492
493 if (!storage_destroy(conf))
494 return -1;
495
496 return 0;
497 }