]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/overlay.c
coverity: #1426028
[mirror_lxc.git] / src / lxc / storage / overlay.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library 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 library 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 library; 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 <errno.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "conf.h"
31 #include "confile.h"
32 #include "log.h"
33 #include "lxccontainer.h"
34 #include "overlay.h"
35 #include "rsync.h"
36 #include "storage.h"
37 #include "storage_utils.h"
38 #include "utils.h"
39
40 lxc_log_define(overlay, lxc);
41
42 static char *ovl_name;
43 static char *ovl_version[] = {"overlay", "overlayfs"};
44
45 static char *ovl_detect_name(void);
46 static int ovl_do_rsync(const char *src, const char *dest,
47 struct lxc_conf *conf);
48 static int ovl_remount_on_enodev(const char *lower, const char *target,
49 const char *name, unsigned long mountflags,
50 const void *options);
51
52 int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldname,
53 const char *cname, const char *oldpath, const char *lxcpath,
54 int snap, uint64_t newsize, struct lxc_conf *conf)
55 {
56 int ret;
57 const char *src;
58
59 if (!snap) {
60 ERROR("The overlay storage driver can only be used for "
61 "snapshots");
62 return -22;
63 }
64
65 if (!orig->src || !orig->dest)
66 return -1;
67
68 new->dest = must_make_path(lxcpath, cname, "rootfs", NULL);
69
70 ret = mkdir_p(new->dest, 0755);
71 if (ret < 0 && errno != EEXIST) {
72 SYSERROR("Failed to create directory \"%s\"", new->dest);
73 return -1;
74 }
75
76 if (am_unpriv()) {
77 ret = chown_mapped_root(new->dest, conf);
78 if (ret < 0)
79 WARN("Failed to update ownership of %s", new->dest);
80 }
81
82 if (strcmp(orig->type, "dir") == 0) {
83 char *delta, *lastslash;
84 char *work;
85 int ret, len, lastslashidx;
86
87 /* If we have "/var/lib/lxc/c2/rootfs" then delta will be
88 * "/var/lib/lxc/c2/delta0".
89 */
90 lastslash = strrchr(new->dest, '/');
91 if (!lastslash) {
92 ERROR("Failed to detect \"/\" in string \"%s\"",
93 new->dest);
94 return -22;
95 }
96
97 if (strlen(lastslash) < (sizeof("/rootfs") - 1)) {
98 ERROR("Failed to detect \"/rootfs\" in string \"%s\"",
99 new->dest);
100 return -22;
101 }
102
103 lastslash++;
104 lastslashidx = lastslash - new->dest;
105
106 delta = malloc(lastslashidx + 7);
107 if (!delta) {
108 ERROR("Failed to allocate memory");
109 return -1;
110 }
111
112 memcpy(delta, new->dest, lastslashidx + 1);
113 memcpy(delta + lastslashidx, "delta0", sizeof("delta0") - 1);
114 delta[lastslashidx + sizeof("delta0") - 1] = '\0';
115
116 ret = mkdir(delta, 0755);
117 if (ret < 0 && errno != EEXIST) {
118 SYSERROR("Failed to create directory \"%s\"", delta);
119 free(delta);
120 return -1;
121 }
122
123 if (am_unpriv()) {
124 ret = chown_mapped_root(delta, conf);
125 if (ret < 0)
126 WARN("Failed to update ownership of %s", delta);
127 }
128
129 /* Make workdir for overlayfs.v22 or higher:
130 * The workdir will be
131 * /var/lib/lxc/c2/olwork
132 * and is used to prepare files before they are atomically
133 * switched to the overlay destination. Workdirs need to be on
134 * the same filesystem as the upperdir so it's OK for it to be
135 * empty.
136 */
137 work = malloc(lastslashidx + 7);
138 if (!work) {
139 ERROR("Failed to allocate memory");
140 free(delta);
141 return -1;
142 }
143
144 memcpy(work, new->dest, lastslashidx + 1);
145 memcpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
146 work[lastslashidx + sizeof("olwork") - 1] = '\0';
147
148 ret = mkdir(work, 0755);
149 if (ret < 0) {
150 SYSERROR("Failed to create directory \"%s\"", work);
151 free(delta);
152 free(work);
153 return -1;
154 }
155
156 if (am_unpriv()) {
157 ret = chown_mapped_root(work, conf);
158 if (ret < 0)
159 WARN("Failed to update ownership of %s", work);
160 }
161 free(work);
162
163 /* strlen("overlay:") = 8
164 * +
165 * strlen(delta)
166 * +
167 * :
168 * +
169 * strlen(src)
170 * +
171 * \0
172 */
173 src = lxc_storage_get_path(orig->src, orig->type);
174 len = 8 + strlen(delta) + 1 + strlen(src) + 1;
175 new->src = malloc(len);
176 if (!new->src) {
177 ERROR("Failed to allocate memory");
178 free(delta);
179 return -ENOMEM;
180 }
181
182 ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
183 free(delta);
184 if (ret < 0 || (size_t)ret >= len) {
185 ERROR("Failed to create string");
186 return -1;
187 }
188 } else if (!strcmp(orig->type, "overlayfs") ||
189 !strcmp(orig->type, "overlay")) {
190 char *clean_old_path, *clean_new_path;
191 char *lastslash, *ndelta, *nsrc, *odelta, *osrc, *s1, *s2, *s3,
192 *work;
193 int ret, lastslashidx;
194 size_t len, name_len;
195
196 osrc = strdup(orig->src);
197 if (!osrc) {
198 ERROR("Failed to duplicate string \"%s\"", orig->src);
199 return -22;
200 }
201
202 nsrc = osrc;
203 if (strncmp(osrc, "overlay:", 8) == 0)
204 nsrc += 8;
205 else if (strncmp(osrc, "overlayfs:", 10) == 0)
206 nsrc += 10;
207
208 odelta = strchr(nsrc, ':');
209 if (!odelta) {
210 ERROR("Failed to find \":\" in \"%s\"", nsrc);
211 free(osrc);
212 return -22;
213 }
214
215 *odelta = '\0';
216 odelta++;
217 ndelta = must_make_path(lxcpath, cname, "delta0", NULL);
218
219 ret = mkdir(ndelta, 0755);
220 if (ret < 0 && errno != EEXIST) {
221 SYSERROR("Failed to create directory \"%s\"", ndelta);
222 free(osrc);
223 free(ndelta);
224 return -1;
225 }
226
227 if (am_unpriv()) {
228 ret = chown_mapped_root(ndelta, conf);
229 if (ret < 0)
230 WARN("Failed to update ownership of %s",
231 ndelta);
232 }
233
234 /* Make workdir for overlayfs.v22 or higher (See the comment
235 * further up.).
236 */
237 lastslash = strrchr(ndelta, '/');
238 if (!lastslash) {
239 ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
240 free(osrc);
241 free(ndelta);
242 return -1;
243 }
244 lastslash++;
245 lastslashidx = lastslash - ndelta;
246
247 work = malloc(lastslashidx + 7);
248 if (!work) {
249 free(osrc);
250 free(ndelta);
251 ERROR("Failed to allocate memory");
252 return -1;
253 }
254
255 memcpy(work, ndelta, lastslashidx + 1);
256 memcpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
257 work[lastslashidx + sizeof("olwork") - 1] = '\0';
258
259 ret = mkdir(work, 0755);
260 if (ret < 0 && errno != EEXIST) {
261 SYSERROR("Failed to create directory \"%s\"", ndelta);
262 free(osrc);
263 free(ndelta);
264 free(work);
265 return -1;
266 }
267
268 if (am_unpriv()) {
269 ret = chown_mapped_root(work, conf);
270 if (ret < 0)
271 WARN("Failed to update ownership of %s", work);
272 }
273 free(work);
274
275 /* strlen("overlay:") = 8
276 * +
277 * strlen(delta)
278 * +
279 * :
280 * +
281 * strlen(src)
282 * +
283 * \0
284 */
285 len = 8 + strlen(ndelta) + 1 + strlen(nsrc) + 1;
286 new->src = malloc(len);
287 if (!new->src) {
288 free(osrc);
289 free(ndelta);
290 ERROR("Failed to allocate memory");
291 return -ENOMEM;
292 }
293 ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
294 if (ret < 0 || (size_t)ret >= len) {
295 ERROR("Failed to create string");
296 free(osrc);
297 free(ndelta);
298 return -1;
299 }
300
301 ret = ovl_do_rsync(odelta, ndelta, conf);
302 free(osrc);
303 free(ndelta);
304 if (ret < 0)
305 return -1;
306
307 /* When we create an overlay snapshot of an overlay container in
308 * the snapshot directory under "<lxcpath>/<name>/snaps/" we
309 * don't need to record a dependency. If we would restore would
310 * also fail.
311 */
312 clean_old_path = lxc_deslashify(oldpath);
313 if (!clean_old_path)
314 return -1;
315
316 clean_new_path = lxc_deslashify(lxcpath);
317 if (!clean_new_path) {
318 free(clean_old_path);
319 return -1;
320 }
321
322 s1 = strrchr(clean_old_path, '/');
323 if (!s1) {
324 ERROR("Failed to detect \"/\" in string \"%s\"", clean_old_path);
325 free(clean_old_path);
326 free(clean_new_path);
327 return -1;
328 }
329
330 s2 = strrchr(clean_new_path, '/');
331 if (!s2) {
332 ERROR("Failed to detect \"/\" in string \"%s\"", clean_new_path);
333 free(clean_old_path);
334 free(clean_new_path);
335 return -1;
336 }
337
338 if (!strncmp(s1, "/snaps", sizeof("/snaps") - 1)) {
339 s1 = clean_new_path;
340 s2 = clean_old_path;
341 s3 = (char *)cname;
342 } else if (!strncmp(s2, "/snaps", sizeof("/snaps") - 1)) {
343 s1 = clean_old_path;
344 s2 = clean_new_path;
345 s3 = (char *)oldname;
346 } else {
347 free(clean_old_path);
348 free(clean_new_path);
349 return 0;
350 }
351
352 len = strlen(s1);
353 if (!strncmp(s1, s2, len)) {
354 char *tmp;
355
356 tmp = (char *)(s2 + len + 1);
357 if (*tmp == '\0') {
358 free(clean_old_path);
359 free(clean_new_path);
360 return 0;
361 }
362
363 name_len = strlen(s3);
364 if (strncmp(s3, tmp, name_len)) {
365 free(clean_old_path);
366 free(clean_new_path);
367 return 0;
368 }
369
370 free(clean_old_path);
371 free(clean_new_path);
372 return LXC_CLONE_SNAPSHOT;
373 }
374
375 free(clean_old_path);
376 free(clean_new_path);
377 return 0;
378 } else {
379 ERROR("overlay clone of %s container is not yet supported",
380 orig->type);
381 /* Note, supporting this will require ovl_mount supporting
382 * mounting of the underlay. No big deal, just needs to be done.
383 */
384 return -1;
385 }
386
387 return 0;
388 }
389
390 /* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
391 * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
392 * after starting the container are written to "<lxcpath>/<lxcname>/delta0".
393 */
394 int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
395 struct bdev_specs *specs)
396 {
397 char *delta;
398 int ret;
399 size_t len, newlen;
400
401 len = strlen(dest);
402 if (len < 8 || strcmp(dest + len - 7, "/rootfs")) {
403 ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest);
404 return -1;
405 }
406
407 bdev->dest = strdup(dest);
408 if (!bdev->dest) {
409 ERROR("Failed to duplicate string \"%s\"", dest);
410 return -1;
411 }
412
413 delta = malloc(len + 1);
414 if (!delta) {
415 ERROR("Failed to allocate memory");
416 return -1;
417 }
418
419 memcpy(delta, dest, len);
420 memcpy(delta + len - 6, "delta0", sizeof("delta0") - 1);
421 delta[len + sizeof("delta0")] = '\0';
422
423 ret = mkdir_p(delta, 0755);
424 if (ret < 0) {
425 SYSERROR("Failed to create directory \"%s\"", delta);
426 free(delta);
427 return -1;
428 }
429
430 /* overlay:lower:upper */
431 newlen = (2 * len) + strlen("overlay:") + 2;
432 bdev->src = malloc(newlen);
433 if (!bdev->src) {
434 ERROR("Failed to allocate memory");
435 free(delta);
436 return -1;
437 }
438
439 ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
440 if (ret < 0 || (size_t)ret >= newlen) {
441 ERROR("Failed to create string");
442 free(delta);
443 return -1;
444 }
445
446 ret = mkdir_p(bdev->dest, 0755);
447 if (ret < 0) {
448 SYSERROR("Failed to create directory \"%s\"", bdev->dest);
449 free(delta);
450 return -1;
451 }
452
453 free(delta);
454 return 0;
455 }
456
457 int ovl_destroy(struct lxc_storage *orig)
458 {
459 char *upper = orig->src;
460
461 /* For an overlay container the rootfs is considered immutable
462 * and cannot be removed when restoring from a snapshot.
463 */
464 if (orig->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)
465 return 0;
466
467 if (strncmp(upper, "overlay:", 8) == 0)
468 upper += 8;
469 else if (strncmp(upper, "overlayfs:", 10) == 0)
470 upper += 10;
471
472 upper = strchr(upper, ':');
473 if (!upper)
474 return -22;
475 upper++;
476
477 return lxc_rmdir_onedev(upper, NULL);
478 }
479
480 bool ovl_detect(const char *path)
481 {
482 if (!strncmp(path, "overlay:", 8))
483 return true;
484
485 if (!strncmp(path, "overlayfs:", 10))
486 return true;
487
488 return false;
489 }
490
491 int ovl_mount(struct lxc_storage *bdev)
492 {
493 char *tmp, *options, *dup, *lower, *upper;
494 char *options_work, *work, *lastslash;
495 int lastslashidx;
496 size_t len, len2;
497 unsigned long mntflags;
498 char *mntdata;
499 int ret, ret2;
500
501 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
502 return -22;
503
504 if (!bdev->src || !bdev->dest)
505 return -22;
506
507 if (!ovl_name)
508 ovl_name = ovl_detect_name();
509
510 /* Separately mount it first:
511 * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
512 */
513 dup = strdup(bdev->src);
514 if (!dup) {
515 ERROR("Failed to allocate memory");
516 return -1;
517 }
518 upper = dup;
519 lower = dup;
520
521 if (strncmp(dup, "overlay:", 8) == 0)
522 lower += 8;
523 else if (strncmp(dup, "overlayfs:", 10) == 0)
524 lower += 10;
525 if (upper != lower)
526 upper = lower;
527
528 /* support multiple lower layers */
529 while ((tmp = strstr(upper, ":/"))) {
530 tmp++;
531 upper = tmp;
532 }
533
534 upper--;
535 if (upper == lower) {
536 free(dup);
537 return -22;
538 }
539 *upper = '\0';
540 upper++;
541
542 /* if delta doesn't yet exist, create it */
543 ret = mkdir_p(upper, 0755);
544 if (ret < 0 && errno != EEXIST) {
545 SYSERROR("Failed to create directory \"%s\"", upper);
546 free(dup);
547 return -22;
548 }
549
550 /* overlayfs.v22 or higher needs workdir option:
551 * if upper is
552 * /var/lib/lxc/c2/delta0
553 * then workdir is
554 * /var/lib/lxc/c2/olwork
555 */
556 lastslash = strrchr(upper, '/');
557 if (!lastslash) {
558 ERROR("Failed to detect \"/\" in string \"%s\"", upper);
559 free(dup);
560 return -22;
561 }
562
563 lastslash++;
564 lastslashidx = lastslash - upper;
565
566 work = malloc(lastslashidx + 7);
567 if (!work) {
568 ERROR("Failed to allocate memory");
569 free(dup);
570 return -22;
571 }
572
573 memcpy(work, upper, lastslashidx + 1);
574 memcpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
575 work[lastslashidx + sizeof("olwork") - 1] = '\0';
576
577 ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
578 if (ret < 0) {
579 ERROR("Failed to parse mount options");
580 free(mntdata);
581 free(dup);
582 free(work);
583 return -22;
584 }
585
586 ret = mkdir_p(work, 0755);
587 if (ret < 0 && errno != EEXIST) {
588 SYSERROR("Failed to create directory \"%s\"", work);
589 free(mntdata);
590 free(dup);
591 free(work);
592 return -22;
593 }
594
595 /*
596 * TODO:
597 * We should check whether bdev->src is a blockdev but for now only
598 * support overlays of a basic directory
599 */
600
601 if (mntdata) {
602 len = strlen(lower) + strlen(upper) +
603 strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
604 options = alloca(len);
605 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s",
606 upper, lower, mntdata);
607
608 len2 = strlen(lower) + strlen(upper) + strlen(work) +
609 strlen("upperdir=,lowerdir=,workdir=") +
610 strlen(mntdata) + 1;
611 options_work = alloca(len2);
612 ret2 = snprintf(options, len2,
613 "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper,
614 lower, work, mntdata);
615 } else {
616 len = strlen(lower) + strlen(upper) +
617 strlen("upperdir=,lowerdir=") + 1;
618 options = alloca(len);
619 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper,
620 lower);
621
622 len2 = strlen(lower) + strlen(upper) + strlen(work) +
623 strlen("upperdir=,lowerdir=,workdir=") + 1;
624 options_work = alloca(len2);
625 ret2 = snprintf(options_work, len2,
626 "upperdir=%s,lowerdir=%s,workdir=%s", upper,
627 lower, work);
628 }
629
630 if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) {
631 ERROR("Failed to create string");
632 free(mntdata);
633 free(dup);
634 free(work);
635 return -1;
636 }
637
638 /* Assume we need a workdir as we are on a overlay version >= v22. */
639 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
640 MS_MGC_VAL | mntflags, options_work);
641 if (ret < 0) {
642 INFO("Failed to mount \"%s\" on \"%s\" with options \"%s\". "
643 "Retrying without workdir: %s",
644 lower, bdev->dest, options_work, strerror(errno));
645
646 /* Assume we cannot use a workdir as we are on a version <= v21.
647 */
648 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
649 MS_MGC_VAL | mntflags, options);
650 if (ret < 0)
651 SYSERROR("Failed to mount \"%s\" on \"%s\" with "
652 "options \"%s\": %s",
653 lower, bdev->dest, options, strerror(errno));
654 else
655 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"",
656 lower, bdev->dest, options);
657 } else {
658 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"", lower,
659 bdev->dest, options_work);
660 }
661
662 free(dup);
663 free(work);
664 return ret;
665 }
666
667 int ovl_umount(struct lxc_storage *bdev)
668 {
669 int ret;
670
671 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
672 return -22;
673
674 if (!bdev->src || !bdev->dest)
675 return -22;
676
677 ret = umount(bdev->dest);
678 if (ret < 0)
679 SYSERROR("Failed to unmount \"%s\"", bdev->dest);
680 else
681 TRACE("Unmounted \"%s\"", bdev->dest);
682
683 return ret;
684 }
685
686 const char *ovl_get_lower(const char *rootfs_path)
687 {
688 const char *s1 = rootfs_path;
689
690 if (strncmp(rootfs_path, "overlay:", 8) == 0)
691 s1 += 8;
692 else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
693 s1 += 10;
694
695 s1 = strstr(s1, ":/");
696 if (!s1)
697 return NULL;
698 s1++;
699
700 return s1;
701 }
702
703 char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
704 {
705 char *rootfsdir = NULL;
706 char *s1 = NULL;
707 char *s2 = NULL;
708 char *s3 = NULL;
709
710 if (!rootfs_path || !rootfslen)
711 return NULL;
712
713 s1 = strdup(rootfs_path);
714 if (!s1)
715 return NULL;
716
717 s2 = s1;
718 if (strncmp(rootfs_path, "overlay:", 8) == 0)
719 s2 += 8;
720 else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
721 s2 += 10;
722
723 s3 = strstr(s2, ":/");
724 if (s3)
725 *s3 = '\0';
726
727 rootfsdir = strdup(s2);
728 free(s1);
729 if (!rootfsdir)
730 return NULL;
731
732 *rootfslen = strlen(rootfsdir);
733
734 return rootfsdir;
735 }
736
737 int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
738 const char *lxc_name, const char *lxc_path)
739 {
740 char lxcpath[MAXPATHLEN];
741 char **opts;
742 int ret;
743 size_t arrlen, i, len, rootfslen;
744 int fret = -1;
745 size_t dirlen = 0;
746 char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL,
747 *workdir = NULL;
748
749 /* When rootfs == NULL we have a container without a rootfs. */
750 if (rootfs && rootfs->path)
751 rootfs_path = rootfs->path;
752
753 opts = lxc_string_split(mntent->mnt_opts, ',');
754 if (opts)
755 arrlen = lxc_array_len((void **)opts);
756 else
757 goto err;
758
759 for (i = 0; i < arrlen; i++) {
760 if (strstr(opts[i], "upperdir=") &&
761 (strlen(opts[i]) > (len = strlen("upperdir="))))
762 upperdir = opts[i] + len;
763 else if (strstr(opts[i], "workdir=") &&
764 (strlen(opts[i]) > (len = strlen("workdir="))))
765 workdir = opts[i] + len;
766 }
767
768 if (rootfs_path) {
769 ret = snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name);
770 if (ret < 0 || ret >= MAXPATHLEN)
771 goto err;
772
773 rootfs_dir = ovl_get_rootfs(rootfs_path, &rootfslen);
774 if (!rootfs_dir)
775 goto err;
776
777 dirlen = strlen(lxcpath);
778 }
779
780 /*
781 * We neither allow users to create upperdirs and workdirs outside the
782 * containerdir nor inside the rootfs. The latter might be debatable.
783 * When we have a container without a rootfs we skip the checks.
784 */
785 ret = 0;
786 if (upperdir) {
787 if (!rootfs_path)
788 ret = mkdir_p(upperdir, 0755);
789 else if (!strncmp(upperdir, lxcpath, dirlen) &&
790 strncmp(upperdir, rootfs_dir, rootfslen))
791 ret = mkdir_p(upperdir, 0755);
792 if (ret < 0)
793 WARN("Failed to create directory \"%s\": %s", upperdir,
794 strerror(errno));
795 }
796
797 ret = 0;
798 if (workdir) {
799 if (!rootfs_path)
800 ret = mkdir_p(workdir, 0755);
801 else if (!strncmp(workdir, lxcpath, dirlen) &&
802 strncmp(workdir, rootfs_dir, rootfslen))
803 ret = mkdir_p(workdir, 0755);
804 if (ret < 0)
805 WARN("Failed to create directory \"%s\": %s", workdir,
806 strerror(errno));
807 }
808
809 fret = 0;
810
811 err:
812 free(rootfs_dir);
813 lxc_free_array((void **)opts, free);
814 return fret;
815 }
816
817 /* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
818 * with overlay lxc.mount.entry entries we need to update absolute paths for
819 * upper- and workdir. This update is done in two locations:
820 * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
821 * independent of each other since lxc_conf->mountlist may contain more mount
822 * entries (e.g. from other included files) than lxc_conf->unexpanded_config.
823 */
824 int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
825 const char *lxc_name, const char *newpath,
826 const char *newname)
827 {
828 char new_upper[MAXPATHLEN], new_work[MAXPATHLEN], old_upper[MAXPATHLEN],
829 old_work[MAXPATHLEN];
830 size_t i;
831 struct lxc_list *iterator;
832 char *cleanpath = NULL;
833 int fret = -1;
834 int ret = 0;
835 const char *ovl_dirs[] = {"br", "upperdir", "workdir"};
836
837 cleanpath = strdup(newpath);
838 if (!cleanpath)
839 goto err;
840
841 remove_trailing_slashes(cleanpath);
842
843 /*
844 * We have to update lxc_conf->unexpanded_config separately from
845 * lxc_conf->mount_list.
846 */
847 for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) {
848 if (!clone_update_unexp_ovl_paths(lxc_conf, lxc_path, newpath,
849 lxc_name, newname,
850 ovl_dirs[i]))
851 goto err;
852 }
853
854 ret =
855 snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path, lxc_name);
856 if (ret < 0 || ret >= MAXPATHLEN)
857 goto err;
858
859 ret =
860 snprintf(new_work, MAXPATHLEN, "workdir=%s/%s", cleanpath, newname);
861 if (ret < 0 || ret >= MAXPATHLEN)
862 goto err;
863
864 lxc_list_for_each(iterator, &lxc_conf->mount_list) {
865 char *mnt_entry = NULL, *new_mnt_entry = NULL, *tmp = NULL,
866 *tmp_mnt_entry = NULL;
867
868 mnt_entry = iterator->elem;
869
870 if (strstr(mnt_entry, "overlay"))
871 tmp = "upperdir";
872 else if (strstr(mnt_entry, "aufs"))
873 tmp = "br";
874
875 if (!tmp)
876 continue;
877
878 ret = snprintf(old_upper, MAXPATHLEN, "%s=%s/%s", tmp, lxc_path,
879 lxc_name);
880 if (ret < 0 || ret >= MAXPATHLEN)
881 goto err;
882
883 ret = snprintf(new_upper, MAXPATHLEN, "%s=%s/%s", tmp,
884 cleanpath, newname);
885 if (ret < 0 || ret >= MAXPATHLEN)
886 goto err;
887
888 if (strstr(mnt_entry, old_upper)) {
889 tmp_mnt_entry =
890 lxc_string_replace(old_upper, new_upper, mnt_entry);
891 }
892
893 if (strstr(mnt_entry, old_work)) {
894 if (tmp_mnt_entry)
895 new_mnt_entry = lxc_string_replace(
896 old_work, new_work, tmp_mnt_entry);
897 else
898 new_mnt_entry = lxc_string_replace(
899 old_work, new_work, mnt_entry);
900 }
901
902 if (new_mnt_entry) {
903 free(iterator->elem);
904 iterator->elem = strdup(new_mnt_entry);
905 } else if (tmp_mnt_entry) {
906 free(iterator->elem);
907 iterator->elem = strdup(tmp_mnt_entry);
908 }
909
910 free(new_mnt_entry);
911 free(tmp_mnt_entry);
912 }
913
914 fret = 0;
915 err:
916 free(cleanpath);
917 return fret;
918 }
919
920 static int ovl_remount_on_enodev(const char *lower, const char *target,
921 const char *name, unsigned long mountflags,
922 const void *options)
923 {
924 int ret;
925 ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
926 if (ret < 0 && errno == ENODEV) /* Try other module name. */
927 ret = mount(lower, target,
928 ovl_name == ovl_version[0] ? ovl_version[1]
929 : ovl_version[0],
930 MS_MGC_VAL | mountflags, options);
931 return ret;
932 }
933
934 static char *ovl_detect_name(void)
935 {
936 FILE *f;
937 char *v = ovl_version[0];
938 char *line = NULL;
939 size_t len = 0;
940
941 f = fopen("/proc/filesystems", "r");
942 if (!f)
943 return v;
944
945 while (getline(&line, &len, f) != -1) {
946 if (strcmp(line, "nodev\toverlayfs\n") == 0) {
947 v = ovl_version[1];
948 break;
949 }
950 }
951
952 fclose(f);
953 free(line);
954 return v;
955 }
956
957 static int ovl_do_rsync(const char *src, const char *dest,
958 struct lxc_conf *conf)
959 {
960 int ret = -1;
961 struct rsync_data_char rdata = {0};
962 char cmd_output[MAXPATHLEN] = {0};
963
964 rdata.src = (char *)src;
965 rdata.dest = (char *)dest;
966 if (am_unpriv())
967 ret = userns_exec_full(conf, lxc_rsync_exec_wrapper, &rdata,
968 "lxc_rsync_exec_wrapper");
969 else
970 ret = run_command(cmd_output, sizeof(cmd_output),
971 lxc_rsync_exec_wrapper, (void *)&rdata);
972 if (ret < 0)
973 ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", src, dest,
974 cmd_output[0] != '\0' ? ": " : "",
975 cmd_output[0] != '\0' ? cmd_output : "");
976
977 return ret;
978 }