]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/conf.c
cgroup: improve support for multiple lxcpaths (v3)
[mirror_lxc.git] / src / lxc / conf.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #undef _GNU_SOURCE
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <dirent.h>
31 #include <unistd.h>
32 #include <sys/wait.h>
33 #include <sys/syscall.h>
34
35 #if HAVE_PTY_H
36 #include <pty.h>
37 #else
38 #include <../include/openpty.h>
39 #endif
40
41 #include <linux/loop.h>
42
43 #include <sys/types.h>
44 #include <sys/utsname.h>
45 #include <sys/param.h>
46 #include <sys/stat.h>
47 #include <sys/socket.h>
48 #include <sys/mount.h>
49 #include <sys/mman.h>
50 #include <sys/prctl.h>
51
52 #include <arpa/inet.h>
53 #include <fcntl.h>
54 #include <netinet/in.h>
55 #include <net/if.h>
56 #include <libgen.h>
57
58 #include "network.h"
59 #include "error.h"
60 #include "parse.h"
61 #include "config.h"
62 #include "utils.h"
63 #include "conf.h"
64 #include "log.h"
65 #include "lxc.h" /* for lxc_cgroup_set() */
66 #include "caps.h" /* for lxc_caps_last_cap() */
67
68 #if HAVE_APPARMOR
69 #include <apparmor.h>
70 #endif
71
72 #if HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
74 #endif
75
76 #if HAVE_SYS_PERSONALITY_H
77 #include <sys/personality.h>
78 #endif
79
80 #if IS_BIONIC
81 #include <../include/lxcmntent.h>
82 #else
83 #include <mntent.h>
84 #endif
85
86 #include "lxcseccomp.h"
87
88 lxc_log_define(lxc_conf, lxc);
89
90 #define MAXHWLEN 18
91 #define MAXINDEXLEN 20
92 #define MAXMTULEN 16
93 #define MAXLINELEN 128
94
95 #ifndef MS_DIRSYNC
96 #define MS_DIRSYNC 128
97 #endif
98
99 #ifndef MS_REC
100 #define MS_REC 16384
101 #endif
102
103 #ifndef MNT_DETACH
104 #define MNT_DETACH 2
105 #endif
106
107 #ifndef MS_SLAVE
108 #define MS_SLAVE (1<<19)
109 #endif
110
111 #ifndef MS_RELATIME
112 #define MS_RELATIME (1 << 21)
113 #endif
114
115 #ifndef MS_STRICTATIME
116 #define MS_STRICTATIME (1 << 24)
117 #endif
118
119 #if HAVE_SYS_CAPABILITY_H
120 #ifndef CAP_SETFCAP
121 #define CAP_SETFCAP 31
122 #endif
123
124 #ifndef CAP_MAC_OVERRIDE
125 #define CAP_MAC_OVERRIDE 32
126 #endif
127
128 #ifndef CAP_MAC_ADMIN
129 #define CAP_MAC_ADMIN 33
130 #endif
131 #endif
132
133 #ifndef PR_CAPBSET_DROP
134 #define PR_CAPBSET_DROP 24
135 #endif
136
137 #ifndef LO_FLAGS_AUTOCLEAR
138 #define LO_FLAGS_AUTOCLEAR 4
139 #endif
140
141 /* Define pivot_root() if missing from the C library */
142 #ifndef HAVE_PIVOT_ROOT
143 static int pivot_root(const char * new_root, const char * put_old)
144 {
145 #ifdef __NR_pivot_root
146 return syscall(__NR_pivot_root, new_root, put_old);
147 #else
148 errno = ENOSYS;
149 return -1;
150 #endif
151 }
152 #else
153 extern int pivot_root(const char * new_root, const char * put_old);
154 #endif
155
156 /* Define sethostname() if missing from the C library */
157 #ifndef HAVE_SETHOSTNAME
158 static int sethostname(const char * name, size_t len)
159 {
160 #ifdef __NR_sethostname
161 return syscall(__NR_sethostname, name, len);
162 #else
163 errno = ENOSYS;
164 return -1;
165 #endif
166 }
167 #endif
168
169 /* Define __S_ISTYPE if missing from the C library */
170 #ifndef __S_ISTYPE
171 #define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask))
172 #endif
173
174 char *lxchook_names[NUM_LXC_HOOKS] = {
175 "pre-start", "pre-mount", "mount", "autodev", "start", "post-stop" };
176
177 typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
178
179 struct mount_opt {
180 char *name;
181 int clear;
182 int flag;
183 };
184
185 struct caps_opt {
186 char *name;
187 int value;
188 };
189
190 static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
191 static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
192 static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
193 static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
194 static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
195
196 static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
197 [LXC_NET_VETH] = instanciate_veth,
198 [LXC_NET_MACVLAN] = instanciate_macvlan,
199 [LXC_NET_VLAN] = instanciate_vlan,
200 [LXC_NET_PHYS] = instanciate_phys,
201 [LXC_NET_EMPTY] = instanciate_empty,
202 };
203
204 static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *);
205 static int shutdown_macvlan(struct lxc_handler *, struct lxc_netdev *);
206 static int shutdown_vlan(struct lxc_handler *, struct lxc_netdev *);
207 static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *);
208 static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *);
209
210 static instanciate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
211 [LXC_NET_VETH] = shutdown_veth,
212 [LXC_NET_MACVLAN] = shutdown_macvlan,
213 [LXC_NET_VLAN] = shutdown_vlan,
214 [LXC_NET_PHYS] = shutdown_phys,
215 [LXC_NET_EMPTY] = shutdown_empty,
216 };
217
218 static struct mount_opt mount_opt[] = {
219 { "defaults", 0, 0 },
220 { "ro", 0, MS_RDONLY },
221 { "rw", 1, MS_RDONLY },
222 { "suid", 1, MS_NOSUID },
223 { "nosuid", 0, MS_NOSUID },
224 { "dev", 1, MS_NODEV },
225 { "nodev", 0, MS_NODEV },
226 { "exec", 1, MS_NOEXEC },
227 { "noexec", 0, MS_NOEXEC },
228 { "sync", 0, MS_SYNCHRONOUS },
229 { "async", 1, MS_SYNCHRONOUS },
230 { "dirsync", 0, MS_DIRSYNC },
231 { "remount", 0, MS_REMOUNT },
232 { "mand", 0, MS_MANDLOCK },
233 { "nomand", 1, MS_MANDLOCK },
234 { "atime", 1, MS_NOATIME },
235 { "noatime", 0, MS_NOATIME },
236 { "diratime", 1, MS_NODIRATIME },
237 { "nodiratime", 0, MS_NODIRATIME },
238 { "bind", 0, MS_BIND },
239 { "rbind", 0, MS_BIND|MS_REC },
240 { "relatime", 0, MS_RELATIME },
241 { "norelatime", 1, MS_RELATIME },
242 { "strictatime", 0, MS_STRICTATIME },
243 { "nostrictatime", 1, MS_STRICTATIME },
244 { NULL, 0, 0 },
245 };
246
247 #if HAVE_SYS_CAPABILITY_H
248 static struct caps_opt caps_opt[] = {
249 { "chown", CAP_CHOWN },
250 { "dac_override", CAP_DAC_OVERRIDE },
251 { "dac_read_search", CAP_DAC_READ_SEARCH },
252 { "fowner", CAP_FOWNER },
253 { "fsetid", CAP_FSETID },
254 { "kill", CAP_KILL },
255 { "setgid", CAP_SETGID },
256 { "setuid", CAP_SETUID },
257 { "setpcap", CAP_SETPCAP },
258 { "linux_immutable", CAP_LINUX_IMMUTABLE },
259 { "net_bind_service", CAP_NET_BIND_SERVICE },
260 { "net_broadcast", CAP_NET_BROADCAST },
261 { "net_admin", CAP_NET_ADMIN },
262 { "net_raw", CAP_NET_RAW },
263 { "ipc_lock", CAP_IPC_LOCK },
264 { "ipc_owner", CAP_IPC_OWNER },
265 { "sys_module", CAP_SYS_MODULE },
266 { "sys_rawio", CAP_SYS_RAWIO },
267 { "sys_chroot", CAP_SYS_CHROOT },
268 { "sys_ptrace", CAP_SYS_PTRACE },
269 { "sys_pacct", CAP_SYS_PACCT },
270 { "sys_admin", CAP_SYS_ADMIN },
271 { "sys_boot", CAP_SYS_BOOT },
272 { "sys_nice", CAP_SYS_NICE },
273 { "sys_resource", CAP_SYS_RESOURCE },
274 { "sys_time", CAP_SYS_TIME },
275 { "sys_tty_config", CAP_SYS_TTY_CONFIG },
276 { "mknod", CAP_MKNOD },
277 { "lease", CAP_LEASE },
278 #ifdef CAP_AUDIT_WRITE
279 { "audit_write", CAP_AUDIT_WRITE },
280 #endif
281 #ifdef CAP_AUDIT_CONTROL
282 { "audit_control", CAP_AUDIT_CONTROL },
283 #endif
284 { "setfcap", CAP_SETFCAP },
285 { "mac_override", CAP_MAC_OVERRIDE },
286 { "mac_admin", CAP_MAC_ADMIN },
287 #ifdef CAP_SYSLOG
288 { "syslog", CAP_SYSLOG },
289 #endif
290 #ifdef CAP_WAKE_ALARM
291 { "wake_alarm", CAP_WAKE_ALARM },
292 #endif
293 };
294 #else
295 static struct caps_opt caps_opt[] = {};
296 #endif
297
298 static int run_buffer(char *buffer)
299 {
300 FILE *f;
301 char *output;
302
303 f = popen(buffer, "r");
304 if (!f) {
305 SYSERROR("popen failed");
306 return -1;
307 }
308
309 output = malloc(LXC_LOG_BUFFER_SIZE);
310 if (!output) {
311 ERROR("failed to allocate memory for script output");
312 return -1;
313 }
314
315 while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
316 DEBUG("script output: %s", output);
317
318 free(output);
319
320 if (pclose(f) == -1) {
321 SYSERROR("Script exited on error");
322 return -1;
323 }
324
325 return 0;
326 }
327
328 static int run_script(const char *name, const char *section,
329 const char *script, ...)
330 {
331 int ret;
332 char *buffer, *p;
333 size_t size = 0;
334 va_list ap;
335
336 INFO("Executing script '%s' for container '%s', config section '%s'",
337 script, name, section);
338
339 va_start(ap, script);
340 while ((p = va_arg(ap, char *)))
341 size += strlen(p) + 1;
342 va_end(ap);
343
344 size += strlen(script);
345 size += strlen(name);
346 size += strlen(section);
347 size += 3;
348
349 if (size > INT_MAX)
350 return -1;
351
352 buffer = alloca(size);
353 if (!buffer) {
354 ERROR("failed to allocate memory");
355 return -1;
356 }
357
358 ret = snprintf(buffer, size, "%s %s %s", script, name, section);
359 if (ret < 0 || ret >= size) {
360 ERROR("Script name too long");
361 free(buffer);
362 return -1;
363 }
364
365 va_start(ap, script);
366 while ((p = va_arg(ap, char *))) {
367 int len = size-ret;
368 int rc;
369 rc = snprintf(buffer + ret, len, " %s", p);
370 if (rc < 0 || rc >= len) {
371 free(buffer);
372 ERROR("Script args too long");
373 return -1;
374 }
375 ret += rc;
376 }
377 va_end(ap);
378
379 return run_buffer(buffer);
380 }
381
382 static int find_fstype_cb(char* buffer, void *data)
383 {
384 struct cbarg {
385 const char *rootfs;
386 const char *target;
387 int mntopt;
388 } *cbarg = data;
389
390 char *fstype;
391
392 /* we don't try 'nodev' entries */
393 if (strstr(buffer, "nodev"))
394 return 0;
395
396 fstype = buffer;
397 fstype += lxc_char_left_gc(fstype, strlen(fstype));
398 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
399
400 DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
401 cbarg->rootfs, cbarg->target, fstype);
402
403 if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
404 DEBUG("mount failed with error: %s", strerror(errno));
405 return 0;
406 }
407
408 INFO("mounted '%s' on '%s', with fstype '%s'",
409 cbarg->rootfs, cbarg->target, fstype);
410
411 return 1;
412 }
413
414 static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
415 {
416 int i;
417
418 struct cbarg {
419 const char *rootfs;
420 const char *target;
421 int mntopt;
422 } cbarg = {
423 .rootfs = rootfs,
424 .target = target,
425 .mntopt = mntopt,
426 };
427
428 /*
429 * find the filesystem type with brute force:
430 * first we check with /etc/filesystems, in case the modules
431 * are auto-loaded and fall back to the supported kernel fs
432 */
433 char *fsfile[] = {
434 "/etc/filesystems",
435 "/proc/filesystems",
436 };
437
438 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
439
440 int ret;
441
442 if (access(fsfile[i], F_OK))
443 continue;
444
445 ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
446 if (ret < 0) {
447 ERROR("failed to parse '%s'", fsfile[i]);
448 return -1;
449 }
450
451 if (ret)
452 return 0;
453 }
454
455 ERROR("failed to determine fs type for '%s'", rootfs);
456 return -1;
457 }
458
459 static int mount_rootfs_dir(const char *rootfs, const char *target)
460 {
461 return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
462 }
463
464 static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
465 {
466 int rfd;
467 int ret = -1;
468
469 rfd = open(rootfs, O_RDWR);
470 if (rfd < 0) {
471 SYSERROR("failed to open '%s'", rootfs);
472 return -1;
473 }
474
475 memset(loinfo, 0, sizeof(*loinfo));
476
477 loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
478
479 if (ioctl(fd, LOOP_SET_FD, rfd)) {
480 SYSERROR("failed to LOOP_SET_FD");
481 goto out;
482 }
483
484 if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
485 SYSERROR("failed to LOOP_SET_STATUS64");
486 goto out;
487 }
488
489 ret = 0;
490 out:
491 close(rfd);
492
493 return ret;
494 }
495
496 static int mount_rootfs_file(const char *rootfs, const char *target)
497 {
498 struct dirent dirent, *direntp;
499 struct loop_info64 loinfo;
500 int ret = -1, fd = -1, rc;
501 DIR *dir;
502 char path[MAXPATHLEN];
503
504 dir = opendir("/dev");
505 if (!dir) {
506 SYSERROR("failed to open '/dev'");
507 return -1;
508 }
509
510 while (!readdir_r(dir, &dirent, &direntp)) {
511
512 if (!direntp)
513 break;
514
515 if (!strcmp(direntp->d_name, "."))
516 continue;
517
518 if (!strcmp(direntp->d_name, ".."))
519 continue;
520
521 if (strncmp(direntp->d_name, "loop", 4))
522 continue;
523
524 rc = snprintf(path, MAXPATHLEN, "/dev/%s", direntp->d_name);
525 if (rc < 0 || rc >= MAXPATHLEN)
526 continue;
527
528 fd = open(path, O_RDWR);
529 if (fd < 0)
530 continue;
531
532 if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
533 close(fd);
534 continue;
535 }
536
537 if (errno != ENXIO) {
538 WARN("unexpected error for ioctl on '%s': %m",
539 direntp->d_name);
540 continue;
541 }
542
543 DEBUG("found '%s' free lodev", path);
544
545 ret = setup_lodev(rootfs, fd, &loinfo);
546 if (!ret)
547 ret = mount_unknow_fs(path, target, 0);
548 close(fd);
549
550 break;
551 }
552
553 if (closedir(dir))
554 WARN("failed to close directory");
555
556 return ret;
557 }
558
559 static int mount_rootfs_block(const char *rootfs, const char *target)
560 {
561 return mount_unknow_fs(rootfs, target, 0);
562 }
563
564 /*
565 * pin_rootfs
566 * if rootfs is a directory, then open ${rootfs}.hold for writing for the
567 * duration of the container run, to prevent the container from marking the
568 * underlying fs readonly on shutdown.
569 * return -1 on error.
570 * return -2 if nothing needed to be pinned.
571 * return an open fd (>=0) if we pinned it.
572 */
573 int pin_rootfs(const char *rootfs)
574 {
575 char absrootfs[MAXPATHLEN];
576 char absrootfspin[MAXPATHLEN];
577 struct stat s;
578 int ret, fd;
579
580 if (rootfs == NULL || strlen(rootfs) == 0)
581 return 0;
582
583 if (!realpath(rootfs, absrootfs)) {
584 SYSERROR("failed to get real path for '%s'", rootfs);
585 return -1;
586 }
587
588 if (access(absrootfs, F_OK)) {
589 SYSERROR("'%s' is not accessible", absrootfs);
590 return -1;
591 }
592
593 if (stat(absrootfs, &s)) {
594 SYSERROR("failed to stat '%s'", absrootfs);
595 return -1;
596 }
597
598 if (!S_ISDIR(s.st_mode))
599 return -2;
600
601 ret = snprintf(absrootfspin, MAXPATHLEN, "%s%s", absrootfs, ".hold");
602 if (ret >= MAXPATHLEN) {
603 SYSERROR("pathname too long for rootfs hold file");
604 return -1;
605 }
606
607 fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR);
608 INFO("opened %s as fd %d\n", absrootfspin, fd);
609 return fd;
610 }
611
612 static int mount_rootfs(const char *rootfs, const char *target)
613 {
614 char absrootfs[MAXPATHLEN];
615 struct stat s;
616 int i;
617
618 typedef int (*rootfs_cb)(const char *, const char *);
619
620 struct rootfs_type {
621 int type;
622 rootfs_cb cb;
623 } rtfs_type[] = {
624 { S_IFDIR, mount_rootfs_dir },
625 { S_IFBLK, mount_rootfs_block },
626 { S_IFREG, mount_rootfs_file },
627 };
628
629 if (!realpath(rootfs, absrootfs)) {
630 SYSERROR("failed to get real path for '%s'", rootfs);
631 return -1;
632 }
633
634 if (access(absrootfs, F_OK)) {
635 SYSERROR("'%s' is not accessible", absrootfs);
636 return -1;
637 }
638
639 if (stat(absrootfs, &s)) {
640 SYSERROR("failed to stat '%s'", absrootfs);
641 return -1;
642 }
643
644 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
645
646 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
647 continue;
648
649 return rtfs_type[i].cb(absrootfs, target);
650 }
651
652 ERROR("unsupported rootfs type for '%s'", absrootfs);
653 return -1;
654 }
655
656 static int setup_utsname(struct utsname *utsname)
657 {
658 if (!utsname)
659 return 0;
660
661 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
662 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
663 return -1;
664 }
665
666 INFO("'%s' hostname has been setup", utsname->nodename);
667
668 return 0;
669 }
670
671 static int setup_tty(const struct lxc_rootfs *rootfs,
672 const struct lxc_tty_info *tty_info, char *ttydir)
673 {
674 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
675 int i, ret;
676
677 if (!rootfs->path)
678 return 0;
679
680 for (i = 0; i < tty_info->nbtty; i++) {
681
682 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
683
684 ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
685 rootfs->mount, i + 1);
686 if (ret >= sizeof(path)) {
687 ERROR("pathname too long for ttys");
688 return -1;
689 }
690 if (ttydir) {
691 /* create dev/lxc/tty%d" */
692 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
693 rootfs->mount, ttydir, i + 1);
694 if (ret >= sizeof(lxcpath)) {
695 ERROR("pathname too long for ttys");
696 return -1;
697 }
698 ret = creat(lxcpath, 0660);
699 if (ret==-1 && errno != EEXIST) {
700 SYSERROR("error creating %s\n", lxcpath);
701 return -1;
702 }
703 close(ret);
704 ret = unlink(path);
705 if (ret && errno != ENOENT) {
706 SYSERROR("error unlinking %s\n", path);
707 return -1;
708 }
709
710 if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) {
711 WARN("failed to mount '%s'->'%s'",
712 pty_info->name, path);
713 continue;
714 }
715
716 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
717 if (ret >= sizeof(lxcpath)) {
718 ERROR("tty pathname too long");
719 return -1;
720 }
721 ret = symlink(lxcpath, path);
722 if (ret) {
723 SYSERROR("failed to create symlink for tty %d\n", i+1);
724 return -1;
725 }
726 } else {
727 /* If we populated /dev, then we need to create /dev/ttyN */
728 if (access(path, F_OK)) {
729 ret = creat(path, 0660);
730 if (ret==-1) {
731 SYSERROR("error creating %s\n", path);
732 /* this isn't fatal, continue */
733 } else
734 close(ret);
735 }
736 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
737 WARN("failed to mount '%s'->'%s'",
738 pty_info->name, path);
739 continue;
740 }
741 }
742 }
743
744 INFO("%d tty(s) has been setup", tty_info->nbtty);
745
746 return 0;
747 }
748
749 static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
750 {
751 struct lxc_list *mountlist, *listentry, *iterator;
752 char *pivotdir, *mountpoint, *mountentry;
753 int found;
754 void **cbparm;
755
756 mountentry = buffer;
757 cbparm = (void **)data;
758
759 mountlist = cbparm[0];
760 pivotdir = cbparm[1];
761
762 /* parse entry, first field is mountname, ignore */
763 mountpoint = strtok(mountentry, " ");
764 if (!mountpoint)
765 return -1;
766
767 /* second field is mountpoint */
768 mountpoint = strtok(NULL, " ");
769 if (!mountpoint)
770 return -1;
771
772 /* only consider mountpoints below old root fs */
773 if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
774 return 0;
775
776 /* filter duplicate mountpoints */
777 found = 0;
778 lxc_list_for_each(iterator, mountlist) {
779 if (!strcmp(iterator->elem, mountpoint)) {
780 found = 1;
781 break;
782 }
783 }
784 if (found)
785 return 0;
786
787 /* add entry to list */
788 listentry = malloc(sizeof(*listentry));
789 if (!listentry) {
790 SYSERROR("malloc for mountpoint listentry failed");
791 return -1;
792 }
793
794 listentry->elem = strdup(mountpoint);
795 if (!listentry->elem) {
796 SYSERROR("strdup failed");
797 return -1;
798 }
799 lxc_list_add_tail(mountlist, listentry);
800
801 return 0;
802 }
803
804 static int umount_oldrootfs(const char *oldrootfs)
805 {
806 char path[MAXPATHLEN];
807 void *cbparm[2];
808 struct lxc_list mountlist, *iterator, *next;
809 int ok, still_mounted, last_still_mounted;
810 int rc;
811
812 /* read and parse /proc/mounts in old root fs */
813 lxc_list_init(&mountlist);
814
815 /* oldrootfs is on the top tree directory now */
816 rc = snprintf(path, sizeof(path), "/%s", oldrootfs);
817 if (rc >= sizeof(path)) {
818 ERROR("rootfs name too long");
819 return -1;
820 }
821 cbparm[0] = &mountlist;
822
823 cbparm[1] = strdup(path);
824 if (!cbparm[1]) {
825 SYSERROR("strdup failed");
826 return -1;
827 }
828
829 rc = snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
830 if (rc >= sizeof(path)) {
831 ERROR("container proc/mounts name too long");
832 return -1;
833 }
834
835 ok = lxc_file_for_each_line(path,
836 setup_rootfs_pivot_root_cb, &cbparm);
837 if (ok < 0) {
838 SYSERROR("failed to read or parse mount list '%s'", path);
839 return -1;
840 }
841
842 /* umount filesystems until none left or list no longer shrinks */
843 still_mounted = 0;
844 do {
845 last_still_mounted = still_mounted;
846 still_mounted = 0;
847
848 lxc_list_for_each_safe(iterator, &mountlist, next) {
849
850 /* umount normally */
851 if (!umount(iterator->elem)) {
852 DEBUG("umounted '%s'", (char *)iterator->elem);
853 lxc_list_del(iterator);
854 continue;
855 }
856
857 still_mounted++;
858 }
859
860 } while (still_mounted > 0 && still_mounted != last_still_mounted);
861
862
863 lxc_list_for_each(iterator, &mountlist) {
864
865 /* let's try a lazy umount */
866 if (!umount2(iterator->elem, MNT_DETACH)) {
867 INFO("lazy unmount of '%s'", (char *)iterator->elem);
868 continue;
869 }
870
871 /* be more brutal (nfs) */
872 if (!umount2(iterator->elem, MNT_FORCE)) {
873 INFO("forced unmount of '%s'", (char *)iterator->elem);
874 continue;
875 }
876
877 WARN("failed to unmount '%s'", (char *)iterator->elem);
878 }
879
880 return 0;
881 }
882
883 static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
884 {
885 char path[MAXPATHLEN];
886 int remove_pivotdir = 0;
887 int rc;
888
889 /* change into new root fs */
890 if (chdir(rootfs)) {
891 SYSERROR("can't chdir to new rootfs '%s'", rootfs);
892 return -1;
893 }
894
895 if (!pivotdir)
896 pivotdir = "lxc_putold";
897
898 /* compute the full path to pivotdir under rootfs */
899 rc = snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
900 if (rc >= sizeof(path)) {
901 ERROR("pivot dir name too long");
902 return -1;
903 }
904
905 if (access(path, F_OK)) {
906
907 if (mkdir_p(path, 0755)) {
908 SYSERROR("failed to create pivotdir '%s'", path);
909 return -1;
910 }
911
912 remove_pivotdir = 1;
913 DEBUG("created '%s' directory", path);
914 }
915
916 DEBUG("mountpoint for old rootfs is '%s'", path);
917
918 /* pivot_root into our new root fs */
919 if (pivot_root(".", path)) {
920 SYSERROR("pivot_root syscall failed");
921 return -1;
922 }
923
924 if (chdir("/")) {
925 SYSERROR("can't chdir to / after pivot_root");
926 return -1;
927 }
928
929 DEBUG("pivot_root syscall to '%s' successful", rootfs);
930
931 /* we switch from absolute path to relative path */
932 if (umount_oldrootfs(pivotdir))
933 return -1;
934
935 /* remove temporary mount point, we don't consider the removing
936 * as fatal */
937 if (remove_pivotdir && rmdir(pivotdir))
938 WARN("can't remove mountpoint '%s': %m", pivotdir);
939
940 return 0;
941 }
942
943 /*
944 * Do we want to add options for max size of /dev and a file to
945 * specify which devices to create?
946 */
947 static int mount_autodev(char *root)
948 {
949 int ret;
950 char path[MAXPATHLEN];
951
952 INFO("Mounting /dev under %s\n", root);
953 ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
954 if (ret < 0 || ret > MAXPATHLEN)
955 return -1;
956 ret = mount("none", path, "tmpfs", 0, "size=100000");
957 if (ret) {
958 SYSERROR("Failed to mount /dev at %s\n", root);
959 return -1;
960 }
961 ret = snprintf(path, MAXPATHLEN, "%s/dev/pts", root);
962 if (ret < 0 || ret >= MAXPATHLEN)
963 return -1;
964 ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
965 if (ret) {
966 SYSERROR("Failed to create /dev/pts in container");
967 return -1;
968 }
969
970 INFO("Mounted /dev under %s\n", root);
971 return 0;
972 }
973
974 struct lxc_devs {
975 char *name;
976 mode_t mode;
977 int maj;
978 int min;
979 };
980
981 struct lxc_devs lxc_devs[] = {
982 { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
983 { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
984 { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 },
985 { "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 },
986 { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 },
987 { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 },
988 { "console", S_IFCHR | S_IRUSR | S_IWUSR, 5, 1 },
989 };
990
991 static int setup_autodev(char *root)
992 {
993 int ret;
994 struct lxc_devs *d;
995 char path[MAXPATHLEN];
996 int i;
997 mode_t cmask;
998
999 INFO("Creating initial consoles under %s/dev\n", root);
1000
1001 ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
1002 if (ret < 0 || ret >= MAXPATHLEN) {
1003 ERROR("Error calculating container /dev location");
1004 return -1;
1005 }
1006
1007 INFO("Populating /dev under %s\n", root);
1008 cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
1009 for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
1010 d = &lxc_devs[i];
1011 ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name);
1012 if (ret < 0 || ret >= MAXPATHLEN)
1013 return -1;
1014 ret = mknod(path, d->mode, makedev(d->maj, d->min));
1015 if (ret && errno != EEXIST) {
1016 SYSERROR("Error creating %s\n", d->name);
1017 return -1;
1018 }
1019 }
1020 umask(cmask);
1021
1022 INFO("Populated /dev under %s\n", root);
1023 return 0;
1024 }
1025
1026 /*
1027 * Detect whether / is mounted MS_SHARED. The only way I know of to
1028 * check that is through /proc/self/mountinfo.
1029 * I'm only checking for /. If the container rootfs or mount location
1030 * is MS_SHARED, but not '/', then you're out of luck - figuring that
1031 * out would be too much work to be worth it.
1032 */
1033 #define LINELEN 4096
1034 int detect_shared_rootfs(void)
1035 {
1036 char buf[LINELEN], *p;
1037 FILE *f;
1038 int i;
1039 char *p2;
1040
1041 f = fopen("/proc/self/mountinfo", "r");
1042 if (!f)
1043 return 0;
1044 while ((p = fgets(buf, LINELEN, f))) {
1045 INFO("looking at .%s.", p);
1046 for (p = buf, i=0; p && i < 4; i++)
1047 p = index(p+1, ' ');
1048 if (!p)
1049 continue;
1050 p2 = index(p+1, ' ');
1051 if (!p2)
1052 continue;
1053 *p2 = '\0';
1054 INFO("now p is .%s.", p);
1055 if (strcmp(p+1, "/") == 0) {
1056 // this is '/'. is it shared?
1057 p = index(p2+1, ' ');
1058 if (strstr(p, "shared:"))
1059 return 1;
1060 }
1061 }
1062 fclose(f);
1063 return 0;
1064 }
1065
1066 /*
1067 * I'll forgive you for asking whether all of this is needed :) The
1068 * answer is yes.
1069 * pivot_root will fail if the new root, the put_old dir, or the parent
1070 * of current->fs->root are MS_SHARED. (parent of current->fs_root may
1071 * or may not be current->fs_root - if we assumed it always was, we could
1072 * just mount --make-rslave /). So,
1073 * 1. mount a tiny tmpfs to be parent of current->fs->root.
1074 * 2. make that MS_SLAVE
1075 * 3. make a 'root' directory under that
1076 * 4. mount --rbind / under the $tinyroot/root.
1077 * 5. make that rslave
1078 * 6. chdir and chroot into $tinyroot/root
1079 * 7. $tinyroot will be unmounted by our parent in start.c
1080 */
1081 static int chroot_into_slave(struct lxc_conf *conf)
1082 {
1083 char path[MAXPATHLEN];
1084 const char *destpath = conf->rootfs.mount;
1085 int ret;
1086
1087 if (mount(destpath, destpath, NULL, MS_BIND, 0)) {
1088 SYSERROR("failed to mount %s bind", destpath);
1089 return -1;
1090 }
1091 if (mount("", destpath, NULL, MS_SLAVE, 0)) {
1092 SYSERROR("failed to make %s slave", destpath);
1093 return -1;
1094 }
1095 if (mount("none", destpath, "tmpfs", 0, "size=10000")) {
1096 SYSERROR("Failed to mount tmpfs / at %s", destpath);
1097 return -1;
1098 }
1099 ret = snprintf(path, MAXPATHLEN, "%s/root", destpath);
1100 if (ret < 0 || ret >= MAXPATHLEN) {
1101 ERROR("out of memory making root path");
1102 return -1;
1103 }
1104 if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1105 SYSERROR("Failed to create /dev/pts in container");
1106 return -1;
1107 }
1108 if (mount("/", path, NULL, MS_BIND|MS_REC, 0)) {
1109 SYSERROR("Failed to rbind mount / to %s", path);
1110 return -1;
1111 }
1112 if (mount("", destpath, NULL, MS_SLAVE|MS_REC, 0)) {
1113 SYSERROR("Failed to make tmp-/ at %s rslave", path);
1114 return -1;
1115 }
1116 if (chdir(path)) {
1117 SYSERROR("Failed to chdir into tmp-/");
1118 return -1;
1119 }
1120 if (chroot(path)) {
1121 SYSERROR("Failed to chroot into tmp-/");
1122 return -1;
1123 }
1124 INFO("Chrooted into tmp-/ at %s\n", path);
1125 return 0;
1126 }
1127
1128 static int setup_rootfs(struct lxc_conf *conf)
1129 {
1130 const struct lxc_rootfs *rootfs = &conf->rootfs;
1131
1132 if (!rootfs->path)
1133 return 0;
1134
1135 if (access(rootfs->mount, F_OK)) {
1136 SYSERROR("failed to access to '%s', check it is present",
1137 rootfs->mount);
1138 return -1;
1139 }
1140
1141 if (detect_shared_rootfs()) {
1142 if (chroot_into_slave(conf)) {
1143 ERROR("Failed to chroot into slave /");
1144 return -1;
1145 }
1146 }
1147
1148 if (mount_rootfs(rootfs->path, rootfs->mount)) {
1149 ERROR("failed to mount rootfs");
1150 return -1;
1151 }
1152
1153 DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
1154
1155 return 0;
1156 }
1157
1158 int setup_pivot_root(const struct lxc_rootfs *rootfs)
1159 {
1160 if (!rootfs->path)
1161 return 0;
1162
1163 if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
1164 ERROR("failed to setup pivot root");
1165 return -1;
1166 }
1167
1168 return 0;
1169 }
1170
1171 static int setup_pts(int pts)
1172 {
1173 char target[PATH_MAX];
1174
1175 if (!pts)
1176 return 0;
1177
1178 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
1179 SYSERROR("failed to umount 'dev/pts'");
1180 return -1;
1181 }
1182
1183 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
1184 "newinstance,ptmxmode=0666")) {
1185 SYSERROR("failed to mount a new instance of '/dev/pts'");
1186 return -1;
1187 }
1188
1189 if (access("/dev/ptmx", F_OK)) {
1190 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
1191 goto out;
1192 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
1193 return -1;
1194 }
1195
1196 if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
1197 goto out;
1198
1199 /* fallback here, /dev/pts/ptmx exists just mount bind */
1200 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
1201 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
1202 return -1;
1203 }
1204
1205 INFO("created new pts instance");
1206
1207 out:
1208 return 0;
1209 }
1210
1211 static int setup_personality(int persona)
1212 {
1213 #if HAVE_SYS_PERSONALITY_H
1214 if (persona == -1)
1215 return 0;
1216
1217 if (personality(persona) < 0) {
1218 SYSERROR("failed to set personality to '0x%x'", persona);
1219 return -1;
1220 }
1221
1222 INFO("set personality to '0x%x'", persona);
1223 #endif
1224
1225 return 0;
1226 }
1227
1228 static int setup_dev_console(const struct lxc_rootfs *rootfs,
1229 const struct lxc_console *console)
1230 {
1231 char path[MAXPATHLEN];
1232 struct stat s;
1233 int ret;
1234
1235 ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1236 if (ret >= sizeof(path)) {
1237 ERROR("console path too long\n");
1238 return -1;
1239 }
1240
1241 if (access(path, F_OK)) {
1242 WARN("rootfs specified but no console found at '%s'", path);
1243 return 0;
1244 }
1245
1246 if (console->peer == -1) {
1247 INFO("no console output required");
1248 return 0;
1249 }
1250
1251 if (stat(path, &s)) {
1252 SYSERROR("failed to stat '%s'", path);
1253 return -1;
1254 }
1255
1256 if (chmod(console->name, s.st_mode)) {
1257 SYSERROR("failed to set mode '0%o' to '%s'",
1258 s.st_mode, console->name);
1259 return -1;
1260 }
1261
1262 if (mount(console->name, path, "none", MS_BIND, 0)) {
1263 ERROR("failed to mount '%s' on '%s'", console->name, path);
1264 return -1;
1265 }
1266
1267 INFO("console has been setup");
1268 return 0;
1269 }
1270
1271 static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
1272 const struct lxc_console *console,
1273 char *ttydir)
1274 {
1275 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
1276 int ret;
1277
1278 /* create rootfs/dev/<ttydir> directory */
1279 ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
1280 ttydir);
1281 if (ret >= sizeof(path))
1282 return -1;
1283 ret = mkdir(path, 0755);
1284 if (ret && errno != EEXIST) {
1285 SYSERROR("failed with errno %d to create %s\n", errno, path);
1286 return -1;
1287 }
1288 INFO("created %s\n", path);
1289
1290 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
1291 rootfs->mount, ttydir);
1292 if (ret >= sizeof(lxcpath)) {
1293 ERROR("console path too long\n");
1294 return -1;
1295 }
1296
1297 snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1298 ret = unlink(path);
1299 if (ret && errno != ENOENT) {
1300 SYSERROR("error unlinking %s\n", path);
1301 return -1;
1302 }
1303
1304 ret = creat(lxcpath, 0660);
1305 if (ret==-1 && errno != EEXIST) {
1306 SYSERROR("error %d creating %s\n", errno, lxcpath);
1307 return -1;
1308 }
1309 close(ret);
1310
1311 if (console->peer == -1) {
1312 INFO("no console output required");
1313 return 0;
1314 }
1315
1316 if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
1317 ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
1318 return -1;
1319 }
1320
1321 /* create symlink from rootfs/dev/console to 'lxc/console' */
1322 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
1323 if (ret >= sizeof(lxcpath)) {
1324 ERROR("lxc/console path too long");
1325 return -1;
1326 }
1327 ret = symlink(lxcpath, path);
1328 if (ret) {
1329 SYSERROR("failed to create symlink for console");
1330 return -1;
1331 }
1332
1333 INFO("console has been setup on %s", lxcpath);
1334
1335 return 0;
1336 }
1337
1338 static int setup_console(const struct lxc_rootfs *rootfs,
1339 const struct lxc_console *console,
1340 char *ttydir)
1341 {
1342 /* We don't have a rootfs, /dev/console will be shared */
1343 if (!rootfs->path)
1344 return 0;
1345 if (!ttydir)
1346 return setup_dev_console(rootfs, console);
1347
1348 return setup_ttydir_console(rootfs, console, ttydir);
1349 }
1350
1351 static int setup_kmsg(const struct lxc_rootfs *rootfs,
1352 const struct lxc_console *console)
1353 {
1354 char kpath[MAXPATHLEN];
1355 int ret;
1356
1357 if (!rootfs->path)
1358 return 0;
1359 ret = snprintf(kpath, sizeof(kpath), "%s/dev/kmsg", rootfs->mount);
1360 if (ret < 0 || ret >= sizeof(kpath))
1361 return -1;
1362
1363 ret = unlink(kpath);
1364 if (ret && errno != ENOENT) {
1365 SYSERROR("error unlinking %s\n", kpath);
1366 return -1;
1367 }
1368
1369 ret = symlink("console", kpath);
1370 if (ret) {
1371 SYSERROR("failed to create symlink for kmsg");
1372 return -1;
1373 }
1374
1375 return 0;
1376 }
1377
1378 int setup_cgroup(const char *cgpath, struct lxc_list *cgroups)
1379 {
1380 struct lxc_list *iterator;
1381 struct lxc_cgroup *cg;
1382 int ret = -1;
1383
1384 if (lxc_list_empty(cgroups))
1385 return 0;
1386
1387 lxc_list_for_each(iterator, cgroups) {
1388
1389 cg = iterator->elem;
1390
1391 if (lxc_cgroup_set_bypath(cgpath, cg->subsystem, cg->value)) {
1392 ERROR("Error setting %s to %s for %s\n", cg->subsystem,
1393 cg->value, cgpath);
1394 goto out;
1395 }
1396
1397 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
1398 }
1399
1400 ret = 0;
1401 INFO("cgroup has been setup");
1402 out:
1403 return ret;
1404 }
1405
1406 static void parse_mntopt(char *opt, unsigned long *flags, char **data)
1407 {
1408 struct mount_opt *mo;
1409
1410 /* If opt is found in mount_opt, set or clear flags.
1411 * Otherwise append it to data. */
1412
1413 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
1414 if (!strncmp(opt, mo->name, strlen(mo->name))) {
1415 if (mo->clear)
1416 *flags &= ~mo->flag;
1417 else
1418 *flags |= mo->flag;
1419 return;
1420 }
1421 }
1422
1423 if (strlen(*data))
1424 strcat(*data, ",");
1425 strcat(*data, opt);
1426 }
1427
1428 static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
1429 char **mntdata)
1430 {
1431 char *s, *data;
1432 char *p, *saveptr = NULL;
1433
1434 *mntdata = NULL;
1435 *mntflags = 0L;
1436
1437 if (!mntopts)
1438 return 0;
1439
1440 s = strdup(mntopts);
1441 if (!s) {
1442 SYSERROR("failed to allocate memory");
1443 return -1;
1444 }
1445
1446 data = malloc(strlen(s) + 1);
1447 if (!data) {
1448 SYSERROR("failed to allocate memory");
1449 free(s);
1450 return -1;
1451 }
1452 *data = 0;
1453
1454 for (p = strtok_r(s, ",", &saveptr); p != NULL;
1455 p = strtok_r(NULL, ",", &saveptr))
1456 parse_mntopt(p, mntflags, &data);
1457
1458 if (*data)
1459 *mntdata = data;
1460 else
1461 free(data);
1462 free(s);
1463
1464 return 0;
1465 }
1466
1467 static int mount_entry(const char *fsname, const char *target,
1468 const char *fstype, unsigned long mountflags,
1469 const char *data)
1470 {
1471 if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
1472 SYSERROR("failed to mount '%s' on '%s'", fsname, target);
1473 return -1;
1474 }
1475
1476 if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
1477
1478 DEBUG("remounting %s on %s to respect bind or remount options",
1479 fsname, target);
1480
1481 if (mount(fsname, target, fstype,
1482 mountflags | MS_REMOUNT, data)) {
1483 SYSERROR("failed to mount '%s' on '%s'",
1484 fsname, target);
1485 return -1;
1486 }
1487 }
1488
1489 DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
1490
1491 return 0;
1492 }
1493
1494 static inline int mount_entry_on_systemfs(struct mntent *mntent)
1495 {
1496 unsigned long mntflags;
1497 char *mntdata;
1498 int ret;
1499
1500 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1501 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1502 return -1;
1503 }
1504
1505 ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
1506 mntent->mnt_type, mntflags, mntdata);
1507
1508 if (hasmntopt(mntent, "optional") != NULL)
1509 ret = 0;
1510
1511 free(mntdata);
1512
1513 return ret;
1514 }
1515
1516 static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
1517 const struct lxc_rootfs *rootfs,
1518 const char *lxc_name)
1519 {
1520 char *aux;
1521 char path[MAXPATHLEN];
1522 unsigned long mntflags;
1523 char *mntdata;
1524 int r, ret = 0, offset;
1525 const char *lxcpath;
1526
1527 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1528 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1529 return -1;
1530 }
1531
1532 lxcpath = default_lxc_path();
1533 if (!lxcpath) {
1534 ERROR("Out of memory");
1535 return -1;
1536 }
1537
1538 /* if rootfs->path is a blockdev path, allow container fstab to
1539 * use $lxcpath/CN/rootfs as the target prefix */
1540 r = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name);
1541 if (r < 0 || r >= MAXPATHLEN)
1542 goto skipvarlib;
1543
1544 aux = strstr(mntent->mnt_dir, path);
1545 if (aux) {
1546 offset = strlen(path);
1547 goto skipabs;
1548 }
1549
1550 skipvarlib:
1551 aux = strstr(mntent->mnt_dir, rootfs->path);
1552 if (!aux) {
1553 WARN("ignoring mount point '%s'", mntent->mnt_dir);
1554 goto out;
1555 }
1556 offset = strlen(rootfs->path);
1557
1558 skipabs:
1559
1560 r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
1561 aux + offset);
1562 if (r < 0 || r >= MAXPATHLEN) {
1563 WARN("pathnme too long for '%s'", mntent->mnt_dir);
1564 ret = -1;
1565 goto out;
1566 }
1567
1568
1569 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1570 mntflags, mntdata);
1571
1572 if (hasmntopt(mntent, "optional") != NULL)
1573 ret = 0;
1574
1575 out:
1576 free(mntdata);
1577 return ret;
1578 }
1579
1580 static int mount_entry_on_relative_rootfs(struct mntent *mntent,
1581 const char *rootfs)
1582 {
1583 char path[MAXPATHLEN];
1584 unsigned long mntflags;
1585 char *mntdata;
1586 int ret;
1587
1588 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1589 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1590 return -1;
1591 }
1592
1593 /* relative to root mount point */
1594 ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
1595 if (ret >= sizeof(path)) {
1596 ERROR("path name too long");
1597 return -1;
1598 }
1599
1600 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1601 mntflags, mntdata);
1602
1603 if (hasmntopt(mntent, "optional") != NULL)
1604 ret = 0;
1605
1606 free(mntdata);
1607
1608 return ret;
1609 }
1610
1611 static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
1612 const char *lxc_name)
1613 {
1614 struct mntent *mntent;
1615 int ret = -1;
1616
1617 while ((mntent = getmntent(file))) {
1618
1619 if (!rootfs->path) {
1620 if (mount_entry_on_systemfs(mntent))
1621 goto out;
1622 continue;
1623 }
1624
1625 /* We have a separate root, mounts are relative to it */
1626 if (mntent->mnt_dir[0] != '/') {
1627 if (mount_entry_on_relative_rootfs(mntent,
1628 rootfs->mount))
1629 goto out;
1630 continue;
1631 }
1632
1633 if (mount_entry_on_absolute_rootfs(mntent, rootfs, lxc_name))
1634 goto out;
1635 }
1636
1637 ret = 0;
1638
1639 INFO("mount points have been setup");
1640 out:
1641 return ret;
1642 }
1643
1644 static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
1645 const char *lxc_name)
1646 {
1647 FILE *file;
1648 int ret;
1649
1650 if (!fstab)
1651 return 0;
1652
1653 file = setmntent(fstab, "r");
1654 if (!file) {
1655 SYSERROR("failed to use '%s'", fstab);
1656 return -1;
1657 }
1658
1659 ret = mount_file_entries(rootfs, file, lxc_name);
1660
1661 endmntent(file);
1662 return ret;
1663 }
1664
1665 static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
1666 const char *lxc_name)
1667 {
1668 FILE *file;
1669 struct lxc_list *iterator;
1670 char *mount_entry;
1671 int ret;
1672
1673 file = tmpfile();
1674 if (!file) {
1675 ERROR("tmpfile error: %m");
1676 return -1;
1677 }
1678
1679 lxc_list_for_each(iterator, mount) {
1680 mount_entry = iterator->elem;
1681 fprintf(file, "%s\n", mount_entry);
1682 }
1683
1684 rewind(file);
1685
1686 ret = mount_file_entries(rootfs, file, lxc_name);
1687
1688 fclose(file);
1689 return ret;
1690 }
1691
1692 static int setup_caps(struct lxc_list *caps)
1693 {
1694 struct lxc_list *iterator;
1695 char *drop_entry;
1696 char *ptr;
1697 int i, capid;
1698
1699 lxc_list_for_each(iterator, caps) {
1700
1701 drop_entry = iterator->elem;
1702
1703 capid = -1;
1704
1705 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
1706
1707 if (strcmp(drop_entry, caps_opt[i].name))
1708 continue;
1709
1710 capid = caps_opt[i].value;
1711 break;
1712 }
1713
1714 if (capid < 0) {
1715 /* try to see if it's numeric, so the user may specify
1716 * capabilities that the running kernel knows about but
1717 * we don't */
1718 capid = strtol(drop_entry, &ptr, 10);
1719 if (!ptr || *ptr != '\0' ||
1720 capid == LONG_MIN || capid == LONG_MAX)
1721 /* not a valid number */
1722 capid = -1;
1723 else if (capid > lxc_caps_last_cap())
1724 /* we have a number but it's not a valid
1725 * capability */
1726 capid = -1;
1727 }
1728
1729 if (capid < 0) {
1730 ERROR("unknown capability %s", drop_entry);
1731 return -1;
1732 }
1733
1734 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
1735
1736 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
1737 SYSERROR("failed to remove %s capability", drop_entry);
1738 return -1;
1739 }
1740
1741 }
1742
1743 DEBUG("capabilities has been setup");
1744
1745 return 0;
1746 }
1747
1748 static int setup_hw_addr(char *hwaddr, const char *ifname)
1749 {
1750 struct sockaddr sockaddr;
1751 struct ifreq ifr;
1752 int ret, fd;
1753
1754 ret = lxc_convert_mac(hwaddr, &sockaddr);
1755 if (ret) {
1756 ERROR("mac address '%s' conversion failed : %s",
1757 hwaddr, strerror(-ret));
1758 return -1;
1759 }
1760
1761 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1762 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1763
1764 fd = socket(AF_INET, SOCK_DGRAM, 0);
1765 if (fd < 0) {
1766 ERROR("socket failure : %s", strerror(errno));
1767 return -1;
1768 }
1769
1770 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1771 close(fd);
1772 if (ret)
1773 ERROR("ioctl failure : %s", strerror(errno));
1774
1775 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1776
1777 return ret;
1778 }
1779
1780 static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
1781 {
1782 struct lxc_list *iterator;
1783 struct lxc_inetdev *inetdev;
1784 int err;
1785
1786 lxc_list_for_each(iterator, ip) {
1787
1788 inetdev = iterator->elem;
1789
1790 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
1791 &inetdev->bcast, inetdev->prefix);
1792 if (err) {
1793 ERROR("failed to setup_ipv4_addr ifindex %d : %s",
1794 ifindex, strerror(-err));
1795 return -1;
1796 }
1797 }
1798
1799 return 0;
1800 }
1801
1802 static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
1803 {
1804 struct lxc_list *iterator;
1805 struct lxc_inet6dev *inet6dev;
1806 int err;
1807
1808 lxc_list_for_each(iterator, ip) {
1809
1810 inet6dev = iterator->elem;
1811
1812 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
1813 &inet6dev->mcast, &inet6dev->acast,
1814 inet6dev->prefix);
1815 if (err) {
1816 ERROR("failed to setup_ipv6_addr ifindex %d : %s",
1817 ifindex, strerror(-err));
1818 return -1;
1819 }
1820 }
1821
1822 return 0;
1823 }
1824
1825 static int setup_netdev(struct lxc_netdev *netdev)
1826 {
1827 char ifname[IFNAMSIZ];
1828 char *current_ifname = ifname;
1829 int err;
1830
1831 /* empty network namespace */
1832 if (!netdev->ifindex) {
1833 if (netdev->flags & IFF_UP) {
1834 err = lxc_netdev_up("lo");
1835 if (err) {
1836 ERROR("failed to set the loopback up : %s",
1837 strerror(-err));
1838 return -1;
1839 }
1840 }
1841 return 0;
1842 }
1843
1844 /* retrieve the name of the interface */
1845 if (!if_indextoname(netdev->ifindex, current_ifname)) {
1846 ERROR("no interface corresponding to index '%d'",
1847 netdev->ifindex);
1848 return -1;
1849 }
1850
1851 /* default: let the system to choose one interface name */
1852 if (!netdev->name)
1853 netdev->name = netdev->type == LXC_NET_PHYS ?
1854 netdev->link : "eth%d";
1855
1856 /* rename the interface name */
1857 err = lxc_netdev_rename_by_name(ifname, netdev->name);
1858 if (err) {
1859 ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
1860 strerror(-err));
1861 return -1;
1862 }
1863
1864 /* Re-read the name of the interface because its name has changed
1865 * and would be automatically allocated by the system
1866 */
1867 if (!if_indextoname(netdev->ifindex, current_ifname)) {
1868 ERROR("no interface corresponding to index '%d'",
1869 netdev->ifindex);
1870 return -1;
1871 }
1872
1873 /* set a mac address */
1874 if (netdev->hwaddr) {
1875 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
1876 ERROR("failed to setup hw address for '%s'",
1877 current_ifname);
1878 return -1;
1879 }
1880 }
1881
1882 /* setup ipv4 addresses on the interface */
1883 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
1884 ERROR("failed to setup ip addresses for '%s'",
1885 ifname);
1886 return -1;
1887 }
1888
1889 /* setup ipv6 addresses on the interface */
1890 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
1891 ERROR("failed to setup ipv6 addresses for '%s'",
1892 ifname);
1893 return -1;
1894 }
1895
1896 /* set the network device up */
1897 if (netdev->flags & IFF_UP) {
1898 int err;
1899
1900 err = lxc_netdev_up(current_ifname);
1901 if (err) {
1902 ERROR("failed to set '%s' up : %s", current_ifname,
1903 strerror(-err));
1904 return -1;
1905 }
1906
1907 /* the network is up, make the loopback up too */
1908 err = lxc_netdev_up("lo");
1909 if (err) {
1910 ERROR("failed to set the loopback up : %s",
1911 strerror(-err));
1912 return -1;
1913 }
1914 }
1915
1916 /* We can only set up the default routes after bringing
1917 * up the interface, sine bringing up the interface adds
1918 * the link-local routes and we can't add a default
1919 * route if the gateway is not reachable. */
1920
1921 /* setup ipv4 gateway on the interface */
1922 if (netdev->ipv4_gateway) {
1923 if (!(netdev->flags & IFF_UP)) {
1924 ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname);
1925 return -1;
1926 }
1927
1928 if (lxc_list_empty(&netdev->ipv4)) {
1929 ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname);
1930 return -1;
1931 }
1932
1933 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
1934 if (err) {
1935 ERROR("failed to setup ipv4 gateway for '%s': %s",
1936 ifname, strerror(-err));
1937 if (netdev->ipv4_gateway_auto) {
1938 char buf[INET_ADDRSTRLEN];
1939 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
1940 ERROR("tried to set autodetected ipv4 gateway '%s'", buf);
1941 }
1942 return -1;
1943 }
1944 }
1945
1946 /* setup ipv6 gateway on the interface */
1947 if (netdev->ipv6_gateway) {
1948 if (!(netdev->flags & IFF_UP)) {
1949 ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname);
1950 return -1;
1951 }
1952
1953 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
1954 ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname);
1955 return -1;
1956 }
1957
1958 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
1959 if (err) {
1960 ERROR("failed to setup ipv6 gateway for '%s': %s",
1961 ifname, strerror(-err));
1962 if (netdev->ipv6_gateway_auto) {
1963 char buf[INET6_ADDRSTRLEN];
1964 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
1965 ERROR("tried to set autodetected ipv6 gateway '%s'", buf);
1966 }
1967 return -1;
1968 }
1969 }
1970
1971 DEBUG("'%s' has been setup", current_ifname);
1972
1973 return 0;
1974 }
1975
1976 static int setup_network(struct lxc_list *network)
1977 {
1978 struct lxc_list *iterator;
1979 struct lxc_netdev *netdev;
1980
1981 lxc_list_for_each(iterator, network) {
1982
1983 netdev = iterator->elem;
1984
1985 if (setup_netdev(netdev)) {
1986 ERROR("failed to setup netdev");
1987 return -1;
1988 }
1989 }
1990
1991 if (!lxc_list_empty(network))
1992 INFO("network has been setup");
1993
1994 return 0;
1995 }
1996
1997 void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf)
1998 {
1999 int i;
2000
2001 INFO("running to reset %d nic names", conf->num_savednics);
2002 for (i=0; i<conf->num_savednics; i++) {
2003 struct saved_nic *s = &conf->saved_nics[i];
2004 INFO("resetting nic %d to %s\n", s->ifindex, s->orig_name);
2005 lxc_netdev_rename_by_index(s->ifindex, s->orig_name);
2006 free(s->orig_name);
2007 }
2008 conf->num_savednics = 0;
2009 free(conf->saved_nics);
2010 }
2011
2012 static int setup_private_host_hw_addr(char *veth1)
2013 {
2014 struct ifreq ifr;
2015 int err;
2016 int sockfd;
2017
2018 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2019 if (sockfd < 0)
2020 return -errno;
2021
2022 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
2023 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
2024 if (err < 0) {
2025 close(sockfd);
2026 return -errno;
2027 }
2028
2029 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
2030 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
2031 close(sockfd);
2032 if (err < 0)
2033 return -errno;
2034
2035 DEBUG("mac address of host interface '%s' changed to private "
2036 "%02x:%02x:%02x:%02x:%02x:%02x", veth1,
2037 ifr.ifr_hwaddr.sa_data[0] & 0xff,
2038 ifr.ifr_hwaddr.sa_data[1] & 0xff,
2039 ifr.ifr_hwaddr.sa_data[2] & 0xff,
2040 ifr.ifr_hwaddr.sa_data[3] & 0xff,
2041 ifr.ifr_hwaddr.sa_data[4] & 0xff,
2042 ifr.ifr_hwaddr.sa_data[5] & 0xff);
2043
2044 return 0;
2045 }
2046
2047 static char *default_rootfs_mount = LXCROOTFSMOUNT;
2048
2049 struct lxc_conf *lxc_conf_init(void)
2050 {
2051 struct lxc_conf *new;
2052 int i;
2053
2054 new = malloc(sizeof(*new));
2055 if (!new) {
2056 ERROR("lxc_conf_init : %m");
2057 return NULL;
2058 }
2059 memset(new, 0, sizeof(*new));
2060
2061 new->personality = -1;
2062 new->console.log_path = NULL;
2063 new->console.log_fd = -1;
2064 new->console.path = NULL;
2065 new->console.peer = -1;
2066 new->console.master = -1;
2067 new->console.slave = -1;
2068 new->console.name[0] = '\0';
2069 new->maincmd_fd = -1;
2070 new->rootfs.mount = default_rootfs_mount;
2071 lxc_list_init(&new->cgroup);
2072 lxc_list_init(&new->network);
2073 lxc_list_init(&new->mount_list);
2074 lxc_list_init(&new->caps);
2075 lxc_list_init(&new->id_map);
2076 for (i=0; i<NUM_LXC_HOOKS; i++)
2077 lxc_list_init(&new->hooks[i]);
2078 #if HAVE_APPARMOR
2079 new->aa_profile = NULL;
2080 #endif
2081 #if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2082 new->lsm_umount_proc = 0;
2083 #endif
2084
2085 return new;
2086 }
2087
2088 static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
2089 {
2090 char veth1buf[IFNAMSIZ], *veth1;
2091 char veth2buf[IFNAMSIZ], *veth2;
2092 int err;
2093
2094 if (netdev->priv.veth_attr.pair)
2095 veth1 = netdev->priv.veth_attr.pair;
2096 else {
2097 err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
2098 if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
2099 ERROR("veth1 name too long");
2100 return -1;
2101 }
2102 veth1 = mktemp(veth1buf);
2103 /* store away for deconf */
2104 memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
2105 }
2106
2107 snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
2108 veth2 = mktemp(veth2buf);
2109
2110 if (!strlen(veth1) || !strlen(veth2)) {
2111 ERROR("failed to allocate a temporary name");
2112 return -1;
2113 }
2114
2115 err = lxc_veth_create(veth1, veth2);
2116 if (err) {
2117 ERROR("failed to create %s-%s : %s", veth1, veth2,
2118 strerror(-err));
2119 return -1;
2120 }
2121
2122 /* changing the high byte of the mac address to 0xfe, the bridge interface
2123 * will always keep the host's mac address and not take the mac address
2124 * of a container */
2125 err = setup_private_host_hw_addr(veth1);
2126 if (err) {
2127 ERROR("failed to change mac address of host interface '%s' : %s",
2128 veth1, strerror(-err));
2129 goto out_delete;
2130 }
2131
2132 if (netdev->mtu) {
2133 err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
2134 if (!err)
2135 err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
2136 if (err) {
2137 ERROR("failed to set mtu '%s' for %s-%s : %s",
2138 netdev->mtu, veth1, veth2, strerror(-err));
2139 goto out_delete;
2140 }
2141 }
2142
2143 if (netdev->link) {
2144 err = lxc_bridge_attach(netdev->link, veth1);
2145 if (err) {
2146 ERROR("failed to attach '%s' to the bridge '%s' : %s",
2147 veth1, netdev->link, strerror(-err));
2148 goto out_delete;
2149 }
2150 }
2151
2152 netdev->ifindex = if_nametoindex(veth2);
2153 if (!netdev->ifindex) {
2154 ERROR("failed to retrieve the index for %s", veth2);
2155 goto out_delete;
2156 }
2157
2158 err = lxc_netdev_up(veth1);
2159 if (err) {
2160 ERROR("failed to set %s up : %s", veth1, strerror(-err));
2161 goto out_delete;
2162 }
2163
2164 if (netdev->upscript) {
2165 err = run_script(handler->name, "net", netdev->upscript, "up",
2166 "veth", veth1, (char*) NULL);
2167 if (err)
2168 goto out_delete;
2169 }
2170
2171 DEBUG("instanciated veth '%s/%s', index is '%d'",
2172 veth1, veth2, netdev->ifindex);
2173
2174 return 0;
2175
2176 out_delete:
2177 lxc_netdev_delete_by_name(veth1);
2178 return -1;
2179 }
2180
2181 static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
2182 {
2183 char *veth1;
2184 int err;
2185
2186 if (netdev->priv.veth_attr.pair)
2187 veth1 = netdev->priv.veth_attr.pair;
2188 else
2189 veth1 = netdev->priv.veth_attr.veth1;
2190
2191 if (netdev->downscript) {
2192 err = run_script(handler->name, "net", netdev->downscript,
2193 "down", "veth", veth1, (char*) NULL);
2194 if (err)
2195 return -1;
2196 }
2197 return 0;
2198 }
2199
2200 static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2201 {
2202 char peerbuf[IFNAMSIZ], *peer;
2203 int err;
2204
2205 if (!netdev->link) {
2206 ERROR("no link specified for macvlan netdev");
2207 return -1;
2208 }
2209
2210 err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
2211 if (err >= sizeof(peerbuf))
2212 return -1;
2213
2214 peer = mktemp(peerbuf);
2215 if (!strlen(peer)) {
2216 ERROR("failed to make a temporary name");
2217 return -1;
2218 }
2219
2220 err = lxc_macvlan_create(netdev->link, peer,
2221 netdev->priv.macvlan_attr.mode);
2222 if (err) {
2223 ERROR("failed to create macvlan interface '%s' on '%s' : %s",
2224 peer, netdev->link, strerror(-err));
2225 return -1;
2226 }
2227
2228 netdev->ifindex = if_nametoindex(peer);
2229 if (!netdev->ifindex) {
2230 ERROR("failed to retrieve the index for %s", peer);
2231 lxc_netdev_delete_by_name(peer);
2232 return -1;
2233 }
2234
2235 if (netdev->upscript) {
2236 err = run_script(handler->name, "net", netdev->upscript, "up",
2237 "macvlan", netdev->link, (char*) NULL);
2238 if (err)
2239 return -1;
2240 }
2241
2242 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
2243 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
2244
2245 return 0;
2246 }
2247
2248 static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2249 {
2250 int err;
2251
2252 if (netdev->downscript) {
2253 err = run_script(handler->name, "net", netdev->downscript,
2254 "down", "macvlan", netdev->link,
2255 (char*) NULL);
2256 if (err)
2257 return -1;
2258 }
2259 return 0;
2260 }
2261
2262 /* XXX: merge with instanciate_macvlan */
2263 static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2264 {
2265 char peer[IFNAMSIZ];
2266 int err;
2267
2268 if (!netdev->link) {
2269 ERROR("no link specified for vlan netdev");
2270 return -1;
2271 }
2272
2273 err = snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
2274 if (err >= sizeof(peer)) {
2275 ERROR("peer name too long");
2276 return -1;
2277 }
2278
2279 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
2280 if (err) {
2281 ERROR("failed to create vlan interface '%s' on '%s' : %s",
2282 peer, netdev->link, strerror(-err));
2283 return -1;
2284 }
2285
2286 netdev->ifindex = if_nametoindex(peer);
2287 if (!netdev->ifindex) {
2288 ERROR("failed to retrieve the ifindex for %s", peer);
2289 lxc_netdev_delete_by_name(peer);
2290 return -1;
2291 }
2292
2293 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
2294 netdev->ifindex);
2295
2296 return 0;
2297 }
2298
2299 static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2300 {
2301 return 0;
2302 }
2303
2304 static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
2305 {
2306 if (!netdev->link) {
2307 ERROR("no link specified for the physical interface");
2308 return -1;
2309 }
2310
2311 netdev->ifindex = if_nametoindex(netdev->link);
2312 if (!netdev->ifindex) {
2313 ERROR("failed to retrieve the index for %s", netdev->link);
2314 return -1;
2315 }
2316
2317 if (netdev->upscript) {
2318 int err;
2319 err = run_script(handler->name, "net", netdev->upscript,
2320 "up", "phys", netdev->link, (char*) NULL);
2321 if (err)
2322 return -1;
2323 }
2324
2325 return 0;
2326 }
2327
2328 static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
2329 {
2330 int err;
2331
2332 if (netdev->downscript) {
2333 err = run_script(handler->name, "net", netdev->downscript,
2334 "down", "phys", netdev->link, (char*) NULL);
2335 if (err)
2336 return -1;
2337 }
2338 return 0;
2339 }
2340
2341 static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
2342 {
2343 netdev->ifindex = 0;
2344 if (netdev->upscript) {
2345 int err;
2346 err = run_script(handler->name, "net", netdev->upscript,
2347 "up", "empty", (char*) NULL);
2348 if (err)
2349 return -1;
2350 }
2351 return 0;
2352 }
2353
2354 static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
2355 {
2356 int err;
2357
2358 if (netdev->downscript) {
2359 err = run_script(handler->name, "net", netdev->downscript,
2360 "down", "empty", (char*) NULL);
2361 if (err)
2362 return -1;
2363 }
2364 return 0;
2365 }
2366
2367 int lxc_create_network(struct lxc_handler *handler)
2368 {
2369 struct lxc_list *network = &handler->conf->network;
2370 struct lxc_list *iterator;
2371 struct lxc_netdev *netdev;
2372
2373 lxc_list_for_each(iterator, network) {
2374
2375 netdev = iterator->elem;
2376
2377 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
2378 ERROR("invalid network configuration type '%d'",
2379 netdev->type);
2380 return -1;
2381 }
2382
2383 if (netdev_conf[netdev->type](handler, netdev)) {
2384 ERROR("failed to create netdev");
2385 return -1;
2386 }
2387
2388 }
2389
2390 return 0;
2391 }
2392
2393 void lxc_delete_network(struct lxc_handler *handler)
2394 {
2395 struct lxc_list *network = &handler->conf->network;
2396 struct lxc_list *iterator;
2397 struct lxc_netdev *netdev;
2398
2399 lxc_list_for_each(iterator, network) {
2400 netdev = iterator->elem;
2401
2402 if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
2403 if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
2404 WARN("failed to rename to the initial name the " \
2405 "netdev '%s'", netdev->link);
2406 continue;
2407 }
2408
2409 if (netdev_deconf[netdev->type](handler, netdev)) {
2410 WARN("failed to destroy netdev");
2411 }
2412
2413 /* Recent kernel remove the virtual interfaces when the network
2414 * namespace is destroyed but in case we did not moved the
2415 * interface to the network namespace, we have to destroy it
2416 */
2417 if (netdev->ifindex != 0 &&
2418 lxc_netdev_delete_by_index(netdev->ifindex))
2419 WARN("failed to remove interface '%s'", netdev->name);
2420 }
2421 }
2422
2423 int lxc_assign_network(struct lxc_list *network, pid_t pid)
2424 {
2425 struct lxc_list *iterator;
2426 struct lxc_netdev *netdev;
2427 int err;
2428
2429 lxc_list_for_each(iterator, network) {
2430
2431 netdev = iterator->elem;
2432
2433 /* empty network namespace, nothing to move */
2434 if (!netdev->ifindex)
2435 continue;
2436
2437 err = lxc_netdev_move_by_index(netdev->ifindex, pid);
2438 if (err) {
2439 ERROR("failed to move '%s' to the container : %s",
2440 netdev->link, strerror(-err));
2441 return -1;
2442 }
2443
2444 DEBUG("move '%s' to '%d'", netdev->name, pid);
2445 }
2446
2447 return 0;
2448 }
2449
2450 int add_id_mapping(enum idtype idtype, pid_t pid, uid_t host_start, uid_t ns_start, int range)
2451 {
2452 char path[PATH_MAX];
2453 int ret, closeret;
2454 FILE *f;
2455
2456 ret = snprintf(path, PATH_MAX, "/proc/%d/%cid_map", pid, idtype == ID_TYPE_UID ? 'u' : 'g');
2457 if (ret < 0 || ret >= PATH_MAX) {
2458 fprintf(stderr, "%s: path name too long", __func__);
2459 return -E2BIG;
2460 }
2461 f = fopen(path, "w");
2462 if (!f) {
2463 perror("open");
2464 return -EINVAL;
2465 }
2466 ret = fprintf(f, "%d %d %d", ns_start, host_start, range);
2467 if (ret < 0)
2468 SYSERROR("writing id mapping");
2469 closeret = fclose(f);
2470 if (closeret)
2471 SYSERROR("writing id mapping");
2472 return ret < 0 ? ret : closeret;
2473 }
2474
2475 int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
2476 {
2477 struct lxc_list *iterator;
2478 struct id_map *map;
2479 int ret = 0;
2480
2481 lxc_list_for_each(iterator, idmap) {
2482 map = iterator->elem;
2483 ret = add_id_mapping(map->idtype, pid, map->hostid, map->nsid, map->range);
2484 if (ret)
2485 break;
2486 }
2487 return ret;
2488 }
2489
2490 int lxc_find_gateway_addresses(struct lxc_handler *handler)
2491 {
2492 struct lxc_list *network = &handler->conf->network;
2493 struct lxc_list *iterator;
2494 struct lxc_netdev *netdev;
2495 int link_index;
2496
2497 lxc_list_for_each(iterator, network) {
2498 netdev = iterator->elem;
2499
2500 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
2501 continue;
2502
2503 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
2504 ERROR("gateway = auto only supported for "
2505 "veth and macvlan");
2506 return -1;
2507 }
2508
2509 if (!netdev->link) {
2510 ERROR("gateway = auto needs a link interface");
2511 return -1;
2512 }
2513
2514 link_index = if_nametoindex(netdev->link);
2515 if (!link_index)
2516 return -EINVAL;
2517
2518 if (netdev->ipv4_gateway_auto) {
2519 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
2520 ERROR("failed to automatically find ipv4 gateway "
2521 "address from link interface '%s'", netdev->link);
2522 return -1;
2523 }
2524 }
2525
2526 if (netdev->ipv6_gateway_auto) {
2527 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
2528 ERROR("failed to automatically find ipv6 gateway "
2529 "address from link interface '%s'", netdev->link);
2530 return -1;
2531 }
2532 }
2533 }
2534
2535 return 0;
2536 }
2537
2538 int lxc_create_tty(const char *name, struct lxc_conf *conf)
2539 {
2540 struct lxc_tty_info *tty_info = &conf->tty_info;
2541 int i;
2542
2543 /* no tty in the configuration */
2544 if (!conf->tty)
2545 return 0;
2546
2547 tty_info->pty_info =
2548 malloc(sizeof(*tty_info->pty_info)*conf->tty);
2549 if (!tty_info->pty_info) {
2550 SYSERROR("failed to allocate pty_info");
2551 return -1;
2552 }
2553
2554 for (i = 0; i < conf->tty; i++) {
2555
2556 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2557
2558 if (openpty(&pty_info->master, &pty_info->slave,
2559 pty_info->name, NULL, NULL)) {
2560 SYSERROR("failed to create pty #%d", i);
2561 tty_info->nbtty = i;
2562 lxc_delete_tty(tty_info);
2563 return -1;
2564 }
2565
2566 DEBUG("allocated pty '%s' (%d/%d)",
2567 pty_info->name, pty_info->master, pty_info->slave);
2568
2569 /* Prevent leaking the file descriptors to the container */
2570 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
2571 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
2572
2573 pty_info->busy = 0;
2574 }
2575
2576 tty_info->nbtty = conf->tty;
2577
2578 INFO("tty's configured");
2579
2580 return 0;
2581 }
2582
2583 void lxc_delete_tty(struct lxc_tty_info *tty_info)
2584 {
2585 int i;
2586
2587 for (i = 0; i < tty_info->nbtty; i++) {
2588 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2589
2590 close(pty_info->master);
2591 close(pty_info->slave);
2592 }
2593
2594 free(tty_info->pty_info);
2595 tty_info->nbtty = 0;
2596 }
2597
2598 /*
2599 * given a host uid, return the ns uid if it is mapped.
2600 * if it is not mapped, return the original host id.
2601 */
2602 static int shiftid(struct lxc_conf *c, int uid, enum idtype w)
2603 {
2604 struct lxc_list *iterator;
2605 struct id_map *map;
2606 int low, high;
2607
2608 lxc_list_for_each(iterator, &c->id_map) {
2609 map = iterator->elem;
2610 if (map->idtype != w)
2611 continue;
2612
2613 low = map->nsid;
2614 high = map->nsid + map->range;
2615 if (uid < low || uid >= high)
2616 continue;
2617
2618 return uid - low + map->hostid;
2619 }
2620
2621 return uid;
2622 }
2623
2624 /*
2625 * Take a pathname for a file created on the host, and map the uid and gid
2626 * into the container if needed. (Used for ttys)
2627 */
2628 static int uid_shift_file(char *path, struct lxc_conf *c)
2629 {
2630 struct stat statbuf;
2631 int newuid, newgid;
2632
2633 if (stat(path, &statbuf)) {
2634 SYSERROR("stat(%s)", path);
2635 return -1;
2636 }
2637
2638 newuid = shiftid(c, statbuf.st_uid, ID_TYPE_UID);
2639 newgid = shiftid(c, statbuf.st_gid, ID_TYPE_GID);
2640 if (newuid != statbuf.st_uid || newgid != statbuf.st_gid) {
2641 DEBUG("chowning %s from %d:%d to %d:%d\n", path, (int)statbuf.st_uid, (int)statbuf.st_gid, newuid, newgid);
2642 if (chown(path, newuid, newgid)) {
2643 SYSERROR("chown(%s)", path);
2644 return -1;
2645 }
2646 }
2647 return 0;
2648 }
2649
2650 int uid_shift_ttys(int pid, struct lxc_conf *conf)
2651 {
2652 int i, ret;
2653 struct lxc_tty_info *tty_info = &conf->tty_info;
2654 char path[MAXPATHLEN];
2655 char *ttydir = conf->ttydir;
2656
2657 if (!conf->rootfs.path)
2658 return 0;
2659 /* first the console */
2660 ret = snprintf(path, sizeof(path), "/proc/%d/root/dev/%s/console", pid, ttydir ? ttydir : "");
2661 if (ret < 0 || ret >= sizeof(path)) {
2662 ERROR("console path too long\n");
2663 return -1;
2664 }
2665 if (uid_shift_file(path, conf)) {
2666 DEBUG("Failed to chown the console %s.\n", path);
2667 return -1;
2668 }
2669 for (i=0; i< tty_info->nbtty; i++) {
2670 ret = snprintf(path, sizeof(path), "/proc/%d/root/dev/%s/tty%d",
2671 pid, ttydir ? ttydir : "", i + 1);
2672 if (ret < 0 || ret >= sizeof(path)) {
2673 ERROR("pathname too long for ttys");
2674 return -1;
2675 }
2676 if (uid_shift_file(path, conf)) {
2677 DEBUG("Failed to chown pty %s.\n", path);
2678 return -1;
2679 }
2680 }
2681
2682 return 0;
2683 }
2684
2685 int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
2686 {
2687 #if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2688 int mounted;
2689 #endif
2690
2691 if (setup_utsname(lxc_conf->utsname)) {
2692 ERROR("failed to setup the utsname for '%s'", name);
2693 return -1;
2694 }
2695
2696 if (setup_network(&lxc_conf->network)) {
2697 ERROR("failed to setup the network for '%s'", name);
2698 return -1;
2699 }
2700
2701 if (run_lxc_hooks(name, "pre-mount", lxc_conf)) {
2702 ERROR("failed to run pre-mount hooks for container '%s'.", name);
2703 return -1;
2704 }
2705
2706 if (setup_rootfs(lxc_conf)) {
2707 ERROR("failed to setup rootfs for '%s'", name);
2708 return -1;
2709 }
2710
2711 if (lxc_conf->autodev) {
2712 if (mount_autodev(lxc_conf->rootfs.mount)) {
2713 ERROR("failed to mount /dev in the container");
2714 return -1;
2715 }
2716 }
2717
2718 if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
2719 ERROR("failed to setup the mounts for '%s'", name);
2720 return -1;
2721 }
2722
2723 if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name)) {
2724 ERROR("failed to setup the mount entries for '%s'", name);
2725 return -1;
2726 }
2727
2728 if (run_lxc_hooks(name, "mount", lxc_conf)) {
2729 ERROR("failed to run mount hooks for container '%s'.", name);
2730 return -1;
2731 }
2732
2733 if (lxc_conf->autodev) {
2734 if (run_lxc_hooks(name, "autodev", lxc_conf)) {
2735 ERROR("failed to run autodev hooks for container '%s'.", name);
2736 return -1;
2737 }
2738 if (setup_autodev(lxc_conf->rootfs.mount)) {
2739 ERROR("failed to populate /dev in the container");
2740 return -1;
2741 }
2742 }
2743
2744 if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
2745 ERROR("failed to setup the console for '%s'", name);
2746 return -1;
2747 }
2748
2749 if (setup_kmsg(&lxc_conf->rootfs, &lxc_conf->console)) // don't fail
2750 ERROR("failed to setup kmsg for '%s'", name);
2751
2752 if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
2753 ERROR("failed to setup the ttys for '%s'", name);
2754 return -1;
2755 }
2756
2757 #if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2758 INFO("rootfs path is .%s., mount is .%s.", lxc_conf->rootfs.path,
2759 lxc_conf->rootfs.mount);
2760 if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0)
2761 mounted = 0;
2762 else
2763 mounted = lsm_mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
2764 if (mounted == -1) {
2765 SYSERROR("failed to mount /proc in the container.");
2766 return -1;
2767 } else if (mounted == 1) {
2768 lxc_conf->lsm_umount_proc = 1;
2769 }
2770 #endif
2771
2772 if (setup_pivot_root(&lxc_conf->rootfs)) {
2773 ERROR("failed to set rootfs for '%s'", name);
2774 return -1;
2775 }
2776
2777 if (setup_pts(lxc_conf->pts)) {
2778 ERROR("failed to setup the new pts instance");
2779 return -1;
2780 }
2781
2782 if (setup_personality(lxc_conf->personality)) {
2783 ERROR("failed to setup personality");
2784 return -1;
2785 }
2786
2787 if (lxc_list_empty(&lxc_conf->id_map)) {
2788 if (setup_caps(&lxc_conf->caps)) {
2789 ERROR("failed to drop capabilities");
2790 return -1;
2791 }
2792 }
2793
2794 NOTICE("'%s' is setup.", name);
2795
2796 return 0;
2797 }
2798
2799 int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf)
2800 {
2801 int which = -1;
2802 struct lxc_list *it;
2803
2804 if (strcmp(hook, "pre-start") == 0)
2805 which = LXCHOOK_PRESTART;
2806 else if (strcmp(hook, "pre-mount") == 0)
2807 which = LXCHOOK_PREMOUNT;
2808 else if (strcmp(hook, "mount") == 0)
2809 which = LXCHOOK_MOUNT;
2810 else if (strcmp(hook, "autodev") == 0)
2811 which = LXCHOOK_AUTODEV;
2812 else if (strcmp(hook, "start") == 0)
2813 which = LXCHOOK_START;
2814 else if (strcmp(hook, "post-stop") == 0)
2815 which = LXCHOOK_POSTSTOP;
2816 else
2817 return -1;
2818 lxc_list_for_each(it, &conf->hooks[which]) {
2819 int ret;
2820 char *hookname = it->elem;
2821 ret = run_script(name, "lxc", hookname, hook, NULL);
2822 if (ret)
2823 return ret;
2824 }
2825 return 0;
2826 }
2827
2828 static void lxc_remove_nic(struct lxc_list *it)
2829 {
2830 struct lxc_netdev *netdev = it->elem;
2831 struct lxc_list *it2,*next;
2832
2833 lxc_list_del(it);
2834
2835 if (netdev->link)
2836 free(netdev->link);
2837 if (netdev->name)
2838 free(netdev->name);
2839 if (netdev->upscript)
2840 free(netdev->upscript);
2841 if (netdev->hwaddr)
2842 free(netdev->hwaddr);
2843 if (netdev->mtu)
2844 free(netdev->mtu);
2845 if (netdev->ipv4_gateway)
2846 free(netdev->ipv4_gateway);
2847 if (netdev->ipv6_gateway)
2848 free(netdev->ipv6_gateway);
2849 lxc_list_for_each_safe(it2, &netdev->ipv4, next) {
2850 lxc_list_del(it2);
2851 free(it2->elem);
2852 free(it2);
2853 }
2854 lxc_list_for_each_safe(it2, &netdev->ipv6, next) {
2855 lxc_list_del(it2);
2856 free(it2->elem);
2857 free(it2);
2858 }
2859 free(netdev);
2860 free(it);
2861 }
2862
2863 /* we get passed in something like '0', '0.ipv4' or '1.ipv6' */
2864 int lxc_clear_nic(struct lxc_conf *c, const char *key)
2865 {
2866 char *p1;
2867 int ret, idx, i;
2868 struct lxc_list *it;
2869 struct lxc_netdev *netdev;
2870
2871 p1 = index(key, '.');
2872 if (!p1 || *(p1+1) == '\0')
2873 p1 = NULL;
2874
2875 ret = sscanf(key, "%d", &idx);
2876 if (ret != 1) return -1;
2877 if (idx < 0)
2878 return -1;
2879
2880 i = 0;
2881 lxc_list_for_each(it, &c->network) {
2882 if (i == idx)
2883 break;
2884 i++;
2885 }
2886 if (i < idx) // we don't have that many nics defined
2887 return -1;
2888
2889 if (!it || !it->elem)
2890 return -1;
2891
2892 netdev = it->elem;
2893
2894 if (!p1) {
2895 lxc_remove_nic(it);
2896 } else if (strcmp(p1, "ipv4") == 0) {
2897 struct lxc_list *it2,*next;
2898 lxc_list_for_each_safe(it2, &netdev->ipv4, next) {
2899 lxc_list_del(it2);
2900 free(it2->elem);
2901 free(it2);
2902 }
2903 } else if (strcmp(p1, "ipv6") == 0) {
2904 struct lxc_list *it2,*next;
2905 lxc_list_for_each_safe(it2, &netdev->ipv6, next) {
2906 lxc_list_del(it2);
2907 free(it2->elem);
2908 free(it2);
2909 }
2910 } else if (strcmp(p1, "link") == 0) {
2911 if (netdev->link) {
2912 free(netdev->link);
2913 netdev->link = NULL;
2914 }
2915 } else if (strcmp(p1, "name") == 0) {
2916 if (netdev->name) {
2917 free(netdev->name);
2918 netdev->name = NULL;
2919 }
2920 } else if (strcmp(p1, "script.up") == 0) {
2921 if (netdev->upscript) {
2922 free(netdev->upscript);
2923 netdev->upscript = NULL;
2924 }
2925 } else if (strcmp(p1, "hwaddr") == 0) {
2926 if (netdev->hwaddr) {
2927 free(netdev->hwaddr);
2928 netdev->hwaddr = NULL;
2929 }
2930 } else if (strcmp(p1, "mtu") == 0) {
2931 if (netdev->mtu) {
2932 free(netdev->mtu);
2933 netdev->mtu = NULL;
2934 }
2935 } else if (strcmp(p1, "ipv4_gateway") == 0) {
2936 if (netdev->ipv4_gateway) {
2937 free(netdev->ipv4_gateway);
2938 netdev->ipv4_gateway = NULL;
2939 }
2940 } else if (strcmp(p1, "ipv6_gateway") == 0) {
2941 if (netdev->ipv6_gateway) {
2942 free(netdev->ipv6_gateway);
2943 netdev->ipv6_gateway = NULL;
2944 }
2945 }
2946 else return -1;
2947
2948 return 0;
2949 }
2950
2951 int lxc_clear_config_network(struct lxc_conf *c)
2952 {
2953 struct lxc_list *it,*next;
2954 lxc_list_for_each_safe(it, &c->network, next) {
2955 lxc_remove_nic(it);
2956 }
2957 return 0;
2958 }
2959
2960 int lxc_clear_config_caps(struct lxc_conf *c)
2961 {
2962 struct lxc_list *it,*next;
2963
2964 lxc_list_for_each_safe(it, &c->caps, next) {
2965 lxc_list_del(it);
2966 free(it->elem);
2967 free(it);
2968 }
2969 return 0;
2970 }
2971
2972 int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
2973 {
2974 struct lxc_list *it,*next;
2975 bool all = false;
2976 const char *k = key + 11;
2977
2978 if (strcmp(key, "lxc.cgroup") == 0)
2979 all = true;
2980
2981 lxc_list_for_each_safe(it, &c->cgroup, next) {
2982 struct lxc_cgroup *cg = it->elem;
2983 if (!all && strcmp(cg->subsystem, k) != 0)
2984 continue;
2985 lxc_list_del(it);
2986 free(cg->subsystem);
2987 free(cg->value);
2988 free(cg);
2989 free(it);
2990 }
2991 return 0;
2992 }
2993
2994 int lxc_clear_mount_entries(struct lxc_conf *c)
2995 {
2996 struct lxc_list *it,*next;
2997
2998 lxc_list_for_each_safe(it, &c->mount_list, next) {
2999 lxc_list_del(it);
3000 free(it->elem);
3001 free(it);
3002 }
3003 return 0;
3004 }
3005
3006 int lxc_clear_hooks(struct lxc_conf *c, const char *key)
3007 {
3008 struct lxc_list *it,*next;
3009 bool all = false, done = false;
3010 const char *k = key + 9;
3011 int i;
3012
3013 if (strcmp(key, "lxc.hook") == 0)
3014 all = true;
3015
3016 for (i=0; i<NUM_LXC_HOOKS; i++) {
3017 if (all || strcmp(k, lxchook_names[i]) == 0) {
3018 lxc_list_for_each_safe(it, &c->hooks[i], next) {
3019 lxc_list_del(it);
3020 free(it->elem);
3021 free(it);
3022 }
3023 done = true;
3024 }
3025 }
3026
3027 if (!done) {
3028 ERROR("Invalid hook key: %s", key);
3029 return -1;
3030 }
3031 return 0;
3032 }
3033
3034 void lxc_clear_saved_nics(struct lxc_conf *conf)
3035 {
3036 int i;
3037
3038 if (!conf->num_savednics)
3039 return;
3040 for (i=0; i < conf->num_savednics; i++)
3041 free(conf->saved_nics[i].orig_name);
3042 conf->saved_nics = 0;
3043 free(conf->saved_nics);
3044 }
3045
3046 void lxc_conf_free(struct lxc_conf *conf)
3047 {
3048 if (!conf)
3049 return;
3050 if (conf->console.path)
3051 free(conf->console.path);
3052 if (conf->rootfs.mount != default_rootfs_mount)
3053 free(conf->rootfs.mount);
3054 if (conf->rootfs.path)
3055 free(conf->rootfs.path);
3056 if (conf->utsname)
3057 free(conf->utsname);
3058 if (conf->ttydir)
3059 free(conf->ttydir);
3060 if (conf->fstab)
3061 free(conf->fstab);
3062 lxc_clear_config_network(conf);
3063 #if HAVE_APPARMOR
3064 if (conf->aa_profile)
3065 free(conf->aa_profile);
3066 #endif
3067 lxc_seccomp_free(conf);
3068 lxc_clear_config_caps(conf);
3069 lxc_clear_cgroups(conf, "lxc.cgroup");
3070 lxc_clear_hooks(conf, "lxc.hook");
3071 lxc_clear_mount_entries(conf);
3072 lxc_clear_saved_nics(conf);
3073 free(conf);
3074 }