]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/conf.c
lxc-clone: support btrfs and clean up safely
[mirror_lxc.git] / src / lxc / conf.c
CommitLineData
0ad19a3f 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>
e3b4c4c4 27#include <stdarg.h>
0ad19a3f 28#include <errno.h>
29#include <string.h>
30#include <dirent.h>
31#include <mntent.h>
32#include <unistd.h>
e3b4c4c4 33#include <sys/wait.h>
b0a33c1e 34#include <pty.h>
0ad19a3f 35
b3ecde1e
DL
36#include <linux/loop.h>
37
0ad19a3f 38#include <sys/types.h>
39#include <sys/utsname.h>
40#include <sys/param.h>
41#include <sys/stat.h>
42#include <sys/socket.h>
43#include <sys/mount.h>
44#include <sys/mman.h>
81810dd1
DL
45#include <sys/prctl.h>
46#include <sys/capability.h>
cccc74b5 47#include <sys/personality.h>
0ad19a3f 48
49#include <arpa/inet.h>
50#include <fcntl.h>
51#include <netinet/in.h>
52#include <net/if.h>
6f4a3756 53#include <libgen.h>
0ad19a3f 54
e5bda9ee 55#include "network.h"
56#include "error.h"
b2718c72 57#include "parse.h"
881450bb 58#include "config.h"
1b09f2c0
DL
59#include "utils.h"
60#include "conf.h"
61#include "log.h"
62#include "lxc.h" /* for lxc_cgroup_set() */
d55bc1ad 63#include "caps.h" /* for lxc_caps_last_cap() */
36eb9bde
CLG
64
65lxc_log_define(lxc_conf, lxc);
e5bda9ee 66
0ad19a3f 67#define MAXHWLEN 18
68#define MAXINDEXLEN 20
442cbbe6 69#define MAXMTULEN 16
0ad19a3f 70#define MAXLINELEN 128
71
968fbd36
SK
72#ifndef MS_DIRSYNC
73#define MS_DIRSYNC 128
74#endif
75
fdc03323
DL
76#ifndef MS_REC
77#define MS_REC 16384
78#endif
79
c08556c6
DL
80#ifndef MNT_DETACH
81#define MNT_DETACH 2
82#endif
83
88d413d5
SW
84#ifndef MS_RELATIME
85#define MS_RELATIME (1 << 21)
86#endif
87
88#ifndef MS_STRICTATIME
89#define MS_STRICTATIME (1 << 24)
90#endif
91
b09094da
MN
92#ifndef CAP_SETFCAP
93#define CAP_SETFCAP 31
94#endif
95
96#ifndef CAP_MAC_OVERRIDE
97#define CAP_MAC_OVERRIDE 32
98#endif
99
100#ifndef CAP_MAC_ADMIN
101#define CAP_MAC_ADMIN 33
102#endif
103
104#ifndef PR_CAPBSET_DROP
105#define PR_CAPBSET_DROP 24
106#endif
107
bf601689
MH
108extern int pivot_root(const char * new_root, const char * put_old);
109
e3b4c4c4 110typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
0ad19a3f 111
998ac676
RT
112struct mount_opt {
113 char *name;
114 int clear;
115 int flag;
116};
117
81810dd1
DL
118struct caps_opt {
119 char *name;
120 int value;
121};
122
e3b4c4c4
ST
123static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
124static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
125static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
126static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
127static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
82d5ae15 128
24654103
DL
129static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
130 [LXC_NET_VETH] = instanciate_veth,
131 [LXC_NET_MACVLAN] = instanciate_macvlan,
132 [LXC_NET_VLAN] = instanciate_vlan,
133 [LXC_NET_PHYS] = instanciate_phys,
134 [LXC_NET_EMPTY] = instanciate_empty,
0ad19a3f 135};
136
998ac676 137static struct mount_opt mount_opt[] = {
88d413d5
SW
138 { "defaults", 0, 0 },
139 { "ro", 0, MS_RDONLY },
140 { "rw", 1, MS_RDONLY },
141 { "suid", 1, MS_NOSUID },
142 { "nosuid", 0, MS_NOSUID },
143 { "dev", 1, MS_NODEV },
144 { "nodev", 0, MS_NODEV },
145 { "exec", 1, MS_NOEXEC },
146 { "noexec", 0, MS_NOEXEC },
147 { "sync", 0, MS_SYNCHRONOUS },
148 { "async", 1, MS_SYNCHRONOUS },
149 { "dirsync", 0, MS_DIRSYNC },
150 { "remount", 0, MS_REMOUNT },
151 { "mand", 0, MS_MANDLOCK },
152 { "nomand", 1, MS_MANDLOCK },
153 { "atime", 1, MS_NOATIME },
154 { "noatime", 0, MS_NOATIME },
155 { "diratime", 1, MS_NODIRATIME },
156 { "nodiratime", 0, MS_NODIRATIME },
157 { "bind", 0, MS_BIND },
158 { "rbind", 0, MS_BIND|MS_REC },
159 { "relatime", 0, MS_RELATIME },
160 { "norelatime", 1, MS_RELATIME },
161 { "strictatime", 0, MS_STRICTATIME },
162 { "nostrictatime", 1, MS_STRICTATIME },
163 { NULL, 0, 0 },
998ac676
RT
164};
165
81810dd1 166static struct caps_opt caps_opt[] = {
a6afdde9 167 { "chown", CAP_CHOWN },
1e11be34
DL
168 { "dac_override", CAP_DAC_OVERRIDE },
169 { "dac_read_search", CAP_DAC_READ_SEARCH },
170 { "fowner", CAP_FOWNER },
171 { "fsetid", CAP_FSETID },
81810dd1
DL
172 { "kill", CAP_KILL },
173 { "setgid", CAP_SETGID },
174 { "setuid", CAP_SETUID },
175 { "setpcap", CAP_SETPCAP },
176 { "linux_immutable", CAP_LINUX_IMMUTABLE },
177 { "net_bind_service", CAP_NET_BIND_SERVICE },
178 { "net_broadcast", CAP_NET_BROADCAST },
179 { "net_admin", CAP_NET_ADMIN },
180 { "net_raw", CAP_NET_RAW },
181 { "ipc_lock", CAP_IPC_LOCK },
182 { "ipc_owner", CAP_IPC_OWNER },
183 { "sys_module", CAP_SYS_MODULE },
184 { "sys_rawio", CAP_SYS_RAWIO },
185 { "sys_chroot", CAP_SYS_CHROOT },
186 { "sys_ptrace", CAP_SYS_PTRACE },
187 { "sys_pacct", CAP_SYS_PACCT },
188 { "sys_admin", CAP_SYS_ADMIN },
189 { "sys_boot", CAP_SYS_BOOT },
190 { "sys_nice", CAP_SYS_NICE },
191 { "sys_resource", CAP_SYS_RESOURCE },
192 { "sys_time", CAP_SYS_TIME },
193 { "sys_tty_config", CAP_SYS_TTY_CONFIG },
194 { "mknod", CAP_MKNOD },
195 { "lease", CAP_LEASE },
9527e566 196#ifdef CAP_AUDIT_WRITE
81810dd1 197 { "audit_write", CAP_AUDIT_WRITE },
9527e566
FW
198#endif
199#ifdef CAP_AUDIT_CONTROL
81810dd1 200 { "audit_control", CAP_AUDIT_CONTROL },
9527e566 201#endif
81810dd1
DL
202 { "setfcap", CAP_SETFCAP },
203 { "mac_override", CAP_MAC_OVERRIDE },
204 { "mac_admin", CAP_MAC_ADMIN },
5170c716
CS
205#ifdef CAP_SYSLOG
206 { "syslog", CAP_SYSLOG },
207#endif
208#ifdef CAP_WAKE_ALARM
209 { "wake_alarm", CAP_WAKE_ALARM },
210#endif
81810dd1
DL
211};
212
751d9dcd
DL
213static int run_script(const char *name, const char *section,
214 const char *script, ...)
e3b4c4c4 215{
abbfd20b
DL
216 int ret;
217 FILE *f;
218 char *buffer, *p, *output;
219 size_t size = 0;
220 va_list ap;
751d9dcd
DL
221
222 INFO("Executing script '%s' for container '%s', config section '%s'",
223 script, name, section);
e3b4c4c4 224
abbfd20b
DL
225 va_start(ap, script);
226 while ((p = va_arg(ap, char *)))
95642a10 227 size += strlen(p) + 1;
abbfd20b
DL
228 va_end(ap);
229
230 size += strlen(script);
231 size += strlen(name);
232 size += strlen(section);
95642a10 233 size += 3;
abbfd20b 234
95642a10
MS
235 if (size > INT_MAX)
236 return -1;
237
238 buffer = alloca(size);
abbfd20b
DL
239 if (!buffer) {
240 ERROR("failed to allocate memory");
751d9dcd
DL
241 return -1;
242 }
243
abbfd20b 244 ret = sprintf(buffer, "%s %s %s", script, name, section);
751d9dcd 245
abbfd20b
DL
246 va_start(ap, script);
247 while ((p = va_arg(ap, char *)))
248 ret += sprintf(buffer + ret, " %s", p);
249 va_end(ap);
751d9dcd 250
abbfd20b
DL
251 f = popen(buffer, "r");
252 if (!f) {
253 SYSERROR("popen failed");
254 return -1;
255 }
e3b4c4c4 256
abbfd20b
DL
257 output = malloc(LXC_LOG_BUFFER_SIZE);
258 if (!output) {
259 ERROR("failed to allocate memory for script output");
260 return -1;
e3b4c4c4 261 }
751d9dcd 262
abbfd20b
DL
263 while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
264 DEBUG("script output: %s", output);
265
266 free(output);
267
268 if (pclose(f)) {
269 ERROR("Script exited on error");
751d9dcd
DL
270 return -1;
271 }
272
273 return 0;
e3b4c4c4
ST
274}
275
a6afdde9 276static int find_fstype_cb(char* buffer, void *data)
78ae2fcc 277{
278 struct cbarg {
279 const char *rootfs;
a6afdde9 280 const char *target;
78ae2fcc 281 int mntopt;
282 } *cbarg = data;
283
284 char *fstype;
285
286 /* we don't try 'nodev' entries */
287 if (strstr(buffer, "nodev"))
288 return 0;
289
290 fstype = buffer;
b2718c72 291 fstype += lxc_char_left_gc(fstype, strlen(fstype));
292 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
78ae2fcc 293
a6afdde9
DL
294 DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
295 cbarg->rootfs, cbarg->target, fstype);
296
297 if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
298 DEBUG("mount failed with error: %s", strerror(errno));
78ae2fcc 299 return 0;
a6afdde9 300 }
78ae2fcc 301
a6afdde9
DL
302 INFO("mounted '%s' on '%s', with fstype '%s'",
303 cbarg->rootfs, cbarg->target, fstype);
78ae2fcc 304
305 return 1;
306}
307
2656d231 308static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
78ae2fcc 309{
a6afdde9 310 int i;
78ae2fcc 311
312 struct cbarg {
313 const char *rootfs;
a6afdde9 314 const char *target;
78ae2fcc 315 int mntopt;
316 } cbarg = {
317 .rootfs = rootfs,
a6afdde9 318 .target = target,
78ae2fcc 319 .mntopt = mntopt,
320 };
321
a6afdde9
DL
322 /*
323 * find the filesystem type with brute force:
324 * first we check with /etc/filesystems, in case the modules
78ae2fcc 325 * are auto-loaded and fall back to the supported kernel fs
326 */
327 char *fsfile[] = {
328 "/etc/filesystems",
329 "/proc/filesystems",
330 };
331
a6afdde9
DL
332 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
333
334 int ret;
335
336 if (access(fsfile[i], F_OK))
337 continue;
338
339 ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
340 if (ret < 0) {
341 ERROR("failed to parse '%s'", fsfile[i]);
342 return -1;
343 }
344
345 if (ret)
346 return 0;
78ae2fcc 347 }
348
a6afdde9
DL
349 ERROR("failed to determine fs type for '%s'", rootfs);
350 return -1;
351}
352
2656d231 353static int mount_rootfs_dir(const char *rootfs, const char *target)
a6afdde9
DL
354{
355 return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
356}
357
358static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
359{
360 int rfd;
361 int ret = -1;
362
363 rfd = open(rootfs, O_RDWR);
364 if (rfd < 0) {
365 SYSERROR("failed to open '%s'", rootfs);
78ae2fcc 366 return -1;
367 }
368
a6afdde9 369 memset(loinfo, 0, sizeof(*loinfo));
78ae2fcc 370
a6afdde9 371 loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
78ae2fcc 372
a6afdde9
DL
373 if (ioctl(fd, LOOP_SET_FD, rfd)) {
374 SYSERROR("failed to LOOP_SET_FD");
375 goto out;
78ae2fcc 376 }
377
a6afdde9
DL
378 if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
379 SYSERROR("failed to LOOP_SET_STATUS64");
78ae2fcc 380 goto out;
381 }
382
a6afdde9 383 ret = 0;
78ae2fcc 384out:
a6afdde9 385 close(rfd);
78ae2fcc 386
a6afdde9 387 return ret;
78ae2fcc 388}
389
2656d231 390static int mount_rootfs_file(const char *rootfs, const char *target)
78ae2fcc 391{
a6afdde9
DL
392 struct dirent dirent, *direntp;
393 struct loop_info64 loinfo;
394 int ret = -1, fd = -1;
395 DIR *dir;
396 char path[MAXPATHLEN];
78ae2fcc 397
a6afdde9
DL
398 dir = opendir("/dev");
399 if (!dir) {
400 SYSERROR("failed to open '/dev'");
78ae2fcc 401 return -1;
402 }
403
a6afdde9
DL
404 while (!readdir_r(dir, &dirent, &direntp)) {
405
406 if (!direntp)
407 break;
408
409 if (!strcmp(direntp->d_name, "."))
410 continue;
411
412 if (!strcmp(direntp->d_name, ".."))
413 continue;
414
415 if (strncmp(direntp->d_name, "loop", 4))
416 continue;
417
418 sprintf(path, "/dev/%s", direntp->d_name);
419 fd = open(path, O_RDWR);
420 if (fd < 0)
421 continue;
422
423 if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
424 close(fd);
425 continue;
426 }
427
428 if (errno != ENXIO) {
429 WARN("unexpected error for ioctl on '%s': %m",
430 direntp->d_name);
431 continue;
432 }
433
434 DEBUG("found '%s' free lodev", path);
435
436 ret = setup_lodev(rootfs, fd, &loinfo);
437 if (!ret)
2656d231 438 ret = mount_unknow_fs(path, target, 0);
a6afdde9
DL
439 close(fd);
440
441 break;
442 }
443
444 if (closedir(dir))
445 WARN("failed to close directory");
446
447 return ret;
78ae2fcc 448}
449
2656d231 450static int mount_rootfs_block(const char *rootfs, const char *target)
a6afdde9 451{
2656d231 452 return mount_unknow_fs(rootfs, target, 0);
a6afdde9
DL
453}
454
2656d231 455static int mount_rootfs(const char *rootfs, const char *target)
0ad19a3f 456{
b09ef133 457 char absrootfs[MAXPATHLEN];
78ae2fcc 458 struct stat s;
a6afdde9 459 int i;
78ae2fcc 460
a6afdde9 461 typedef int (*rootfs_cb)(const char *, const char *);
78ae2fcc 462
463 struct rootfs_type {
464 int type;
465 rootfs_cb cb;
466 } rtfs_type[] = {
2656d231
DL
467 { S_IFDIR, mount_rootfs_dir },
468 { S_IFBLK, mount_rootfs_block },
469 { S_IFREG, mount_rootfs_file },
78ae2fcc 470 };
0ad19a3f 471
4c8ab83b 472 if (!realpath(rootfs, absrootfs)) {
36eb9bde 473 SYSERROR("failed to get real path for '%s'", rootfs);
4c8ab83b 474 return -1;
475 }
b09ef133 476
b09ef133 477 if (access(absrootfs, F_OK)) {
36eb9bde 478 SYSERROR("'%s' is not accessible", absrootfs);
b09ef133 479 return -1;
480 }
481
78ae2fcc 482 if (stat(absrootfs, &s)) {
36eb9bde 483 SYSERROR("failed to stat '%s'", absrootfs);
9b0f0477 484 return -1;
485 }
486
78ae2fcc 487 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
9b0f0477 488
78ae2fcc 489 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
490 continue;
9b0f0477 491
a6afdde9 492 return rtfs_type[i].cb(absrootfs, target);
78ae2fcc 493 }
9b0f0477 494
36eb9bde 495 ERROR("unsupported rootfs type for '%s'", absrootfs);
78ae2fcc 496 return -1;
0ad19a3f 497}
498
4e5440c6 499static int setup_utsname(struct utsname *utsname)
0ad19a3f 500{
4e5440c6
DL
501 if (!utsname)
502 return 0;
0ad19a3f 503
4e5440c6
DL
504 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
505 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
0ad19a3f 506 return -1;
507 }
508
4e5440c6 509 INFO("'%s' hostname has been setup", utsname->nodename);
cd54d859 510
0ad19a3f 511 return 0;
512}
513
33fcb7a0
DL
514static int setup_tty(const struct lxc_rootfs *rootfs,
515 const struct lxc_tty_info *tty_info)
b0a33c1e 516{
517 char path[MAXPATHLEN];
518 int i;
519
bc9bd0e3
DL
520 if (!rootfs->path)
521 return 0;
522
b0a33c1e 523 for (i = 0; i < tty_info->nbtty; i++) {
524
525 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
526
52e35957 527 snprintf(path, sizeof(path), "%s/dev/tty%d",
12297168 528 rootfs->mount, i + 1);
b0a33c1e 529
13954cce 530 /* At this point I can not use the "access" function
b0a33c1e 531 * to check the file is present or not because it fails
532 * with EACCES errno and I don't know why :( */
13954cce 533
b0a33c1e 534 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
36eb9bde 535 WARN("failed to mount '%s'->'%s'",
52e35957 536 pty_info->name, path);
b0a33c1e 537 continue;
538 }
539 }
540
cd54d859
DL
541 INFO("%d tty(s) has been setup", tty_info->nbtty);
542
b0a33c1e 543 return 0;
544}
545
7a7ff0c6 546static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
bf601689
MH
547{
548 struct lxc_list *mountlist, *listentry, *iterator;
549 char *pivotdir, *mountpoint, *mountentry;
550 int found;
551 void **cbparm;
552
553 mountentry = buffer;
554 cbparm = (void **)data;
555
556 mountlist = cbparm[0];
557 pivotdir = cbparm[1];
558
559 /* parse entry, first field is mountname, ignore */
560 mountpoint = strtok(mountentry, " ");
561 if (!mountpoint)
562 return -1;
563
564 /* second field is mountpoint */
565 mountpoint = strtok(NULL, " ");
566 if (!mountpoint)
567 return -1;
568
569 /* only consider mountpoints below old root fs */
570 if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
571 return 0;
572
573 /* filter duplicate mountpoints */
574 found = 0;
575 lxc_list_for_each(iterator, mountlist) {
576 if (!strcmp(iterator->elem, mountpoint)) {
577 found = 1;
578 break;
579 }
580 }
581 if (found)
582 return 0;
583
584 /* add entry to list */
585 listentry = malloc(sizeof(*listentry));
586 if (!listentry) {
587 SYSERROR("malloc for mountpoint listentry failed");
588 return -1;
589 }
590
591 listentry->elem = strdup(mountpoint);
592 if (!listentry->elem) {
593 SYSERROR("strdup failed");
594 return -1;
595 }
596 lxc_list_add_tail(mountlist, listentry);
597
598 return 0;
599}
600
cc6f6dd7 601static int umount_oldrootfs(const char *oldrootfs)
bf601689 602{
2382ecff 603 char path[MAXPATHLEN];
bf601689
MH
604 void *cbparm[2];
605 struct lxc_list mountlist, *iterator;
606 int ok, still_mounted, last_still_mounted;
bf601689
MH
607
608 /* read and parse /proc/mounts in old root fs */
609 lxc_list_init(&mountlist);
610
cc6f6dd7
DL
611 /* oldrootfs is on the top tree directory now */
612 snprintf(path, sizeof(path), "/%s", oldrootfs);
bf601689 613 cbparm[0] = &mountlist;
bf601689 614
cc6f6dd7 615 cbparm[1] = strdup(path);
bf601689
MH
616 if (!cbparm[1]) {
617 SYSERROR("strdup failed");
618 return -1;
619 }
620
cc6f6dd7
DL
621 snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
622
623 ok = lxc_file_for_each_line(path,
624 setup_rootfs_pivot_root_cb, &cbparm);
bf601689
MH
625 if (ok < 0) {
626 SYSERROR("failed to read or parse mount list '%s'", path);
627 return -1;
628 }
629
630 /* umount filesystems until none left or list no longer shrinks */
631 still_mounted = 0;
632 do {
633 last_still_mounted = still_mounted;
634 still_mounted = 0;
635
636 lxc_list_for_each(iterator, &mountlist) {
637
c08556c6 638 /* umount normally */
bf601689
MH
639 if (!umount(iterator->elem)) {
640 DEBUG("umounted '%s'", (char *)iterator->elem);
641 lxc_list_del(iterator);
642 continue;
643 }
644
bf601689
MH
645 still_mounted++;
646 }
7df119ee 647
bf601689
MH
648 } while (still_mounted > 0 && still_mounted != last_still_mounted);
649
7df119ee 650
c08556c6
DL
651 lxc_list_for_each(iterator, &mountlist) {
652
653 /* let's try a lazy umount */
654 if (!umount2(iterator->elem, MNT_DETACH)) {
655 INFO("lazy unmount of '%s'", (char *)iterator->elem);
656 continue;
657 }
658
659 /* be more brutal (nfs) */
660 if (!umount2(iterator->elem, MNT_FORCE)) {
661 INFO("forced unmount of '%s'", (char *)iterator->elem);
662 continue;
663 }
664
7df119ee 665 WARN("failed to unmount '%s'", (char *)iterator->elem);
c08556c6 666 }
bf601689 667
cc6f6dd7
DL
668 return 0;
669}
670
671static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
672{
673 char path[MAXPATHLEN];
674 int remove_pivotdir = 0;
675
676 /* change into new root fs */
677 if (chdir(rootfs)) {
678 SYSERROR("can't chdir to new rootfs '%s'", rootfs);
679 return -1;
680 }
681
682 if (!pivotdir)
3103609d 683 pivotdir = "mnt";
cc6f6dd7 684
4f9293b1 685 /* compute the full path to pivotdir under rootfs */
cc6f6dd7
DL
686 snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
687
688 if (access(path, F_OK)) {
689
690 if (mkdir_p(path, 0755)) {
691 SYSERROR("failed to create pivotdir '%s'", path);
692 return -1;
693 }
694
695 remove_pivotdir = 1;
696 DEBUG("created '%s' directory", path);
697 }
698
699 DEBUG("mountpoint for old rootfs is '%s'", path);
700
701 /* pivot_root into our new root fs */
702 if (pivot_root(".", path)) {
703 SYSERROR("pivot_root syscall failed");
bf601689
MH
704 return -1;
705 }
cc6f6dd7
DL
706
707 if (chdir("/")) {
708 SYSERROR("can't chdir to / after pivot_root");
709 return -1;
710 }
711
712 DEBUG("pivot_root syscall to '%s' successful", rootfs);
713
714 /* we switch from absolute path to relative path */
715 if (umount_oldrootfs(pivotdir))
716 return -1;
bf601689 717
c08556c6
DL
718 /* remove temporary mount point, we don't consider the removing
719 * as fatal */
a91d897a
FW
720 if (remove_pivotdir && rmdir(pivotdir))
721 WARN("can't remove mountpoint '%s': %m", pivotdir);
bf601689 722
bf601689
MH
723 return 0;
724}
725
33fcb7a0 726static int setup_rootfs(const struct lxc_rootfs *rootfs)
0ad19a3f 727{
33fcb7a0 728 if (!rootfs->path)
c69bd12f 729 return 0;
0ad19a3f 730
12297168 731 if (access(rootfs->mount, F_OK)) {
b1789442 732 SYSERROR("failed to access to '%s', check it is present",
12297168 733 rootfs->mount);
b1789442
DL
734 return -1;
735 }
736
2656d231 737 if (mount_rootfs(rootfs->path, rootfs->mount)) {
a6afdde9 738 ERROR("failed to mount rootfs");
c3f0a28c 739 return -1;
740 }
0ad19a3f 741
12297168 742 DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
c69bd12f 743
ac778708
DL
744 return 0;
745}
746
747int setup_pivot_root(const struct lxc_rootfs *rootfs)
748{
ac778708
DL
749 if (!rootfs->path)
750 return 0;
751
12297168 752 if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
cc6f6dd7 753 ERROR("failed to setup pivot root");
25368b52 754 return -1;
c69bd12f
DL
755 }
756
25368b52 757 return 0;
0ad19a3f 758}
759
d852c78c 760static int setup_pts(int pts)
3c26f34e 761{
77890c6d
SW
762 char target[PATH_MAX];
763
d852c78c
DL
764 if (!pts)
765 return 0;
3c26f34e 766
767 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
36eb9bde 768 SYSERROR("failed to umount 'dev/pts'");
3c26f34e 769 return -1;
770 }
771
a6afdde9
DL
772 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
773 "newinstance,ptmxmode=0666")) {
36eb9bde 774 SYSERROR("failed to mount a new instance of '/dev/pts'");
3c26f34e 775 return -1;
776 }
777
3c26f34e 778 if (access("/dev/ptmx", F_OK)) {
779 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
780 goto out;
36eb9bde 781 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 782 return -1;
783 }
784
77890c6d
SW
785 if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
786 goto out;
787
3c26f34e 788 /* fallback here, /dev/pts/ptmx exists just mount bind */
789 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
36eb9bde 790 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 791 return -1;
792 }
cd54d859
DL
793
794 INFO("created new pts instance");
d852c78c 795
3c26f34e 796out:
797 return 0;
798}
799
cccc74b5
DL
800static int setup_personality(int persona)
801{
802 if (persona == -1)
803 return 0;
804
805 if (personality(persona) < 0) {
806 SYSERROR("failed to set personality to '0x%x'", persona);
807 return -1;
808 }
809
810 INFO("set personality to '0x%x'", persona);
811
812 return 0;
813}
814
33fcb7a0
DL
815static int setup_console(const struct lxc_rootfs *rootfs,
816 const struct lxc_console *console)
6e590161 817{
63376d7d
DL
818 char path[MAXPATHLEN];
819 struct stat s;
52e35957 820
63376d7d 821 /* We don't have a rootfs, /dev/console will be shared */
33fcb7a0 822 if (!rootfs->path)
63376d7d 823 return 0;
52e35957 824
12297168 825 snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
52e35957 826
63376d7d 827 if (access(path, F_OK)) {
466978b0 828 WARN("rootfs specified but no console found at '%s'", path);
63376d7d 829 return 0;
52e35957
DL
830 }
831
f78a1f32 832 if (console->peer == -1) {
63376d7d 833 INFO("no console output required");
f78a1f32
DL
834 return 0;
835 }
ed502555 836
63376d7d
DL
837 if (stat(path, &s)) {
838 SYSERROR("failed to stat '%s'", path);
839 return -1;
840 }
841
842 if (chmod(console->name, s.st_mode)) {
843 SYSERROR("failed to set mode '0%o' to '%s'",
844 s.st_mode, console->name);
845 return -1;
846 }
13954cce 847
63376d7d
DL
848 if (mount(console->name, path, "none", MS_BIND, 0)) {
849 ERROR("failed to mount '%s' on '%s'", console->name, path);
6e590161 850 return -1;
851 }
852
63376d7d 853 INFO("console has been setup");
cd54d859 854
6e590161 855 return 0;
856}
857
102a5303 858static int setup_cgroup(const char *name, struct lxc_list *cgroups)
576f946d 859{
102a5303
DL
860 struct lxc_list *iterator;
861 struct lxc_cgroup *cg;
88329c69 862 int ret = -1;
6f4a3756 863
102a5303
DL
864 if (lxc_list_empty(cgroups))
865 return 0;
6f4a3756 866
102a5303 867 lxc_list_for_each(iterator, cgroups) {
13954cce 868
102a5303 869 cg = iterator->elem;
6f4a3756 870
102a5303 871 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
88329c69 872 goto out;
6f4a3756 873
102a5303 874 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
6f4a3756 875 }
13954cce 876
88329c69 877 ret = 0;
cd54d859 878 INFO("cgroup has been setup");
88329c69
MN
879out:
880 return ret;
576f946d 881}
882
998ac676
RT
883static void parse_mntopt(char *opt, unsigned long *flags, char **data)
884{
885 struct mount_opt *mo;
886
887 /* If opt is found in mount_opt, set or clear flags.
888 * Otherwise append it to data. */
889
890 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
891 if (!strncmp(opt, mo->name, strlen(mo->name))) {
892 if (mo->clear)
893 *flags &= ~mo->flag;
894 else
895 *flags |= mo->flag;
896 return;
897 }
898 }
899
900 if (strlen(*data))
901 strcat(*data, ",");
902 strcat(*data, opt);
903}
904
911324ef 905static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
998ac676
RT
906 char **mntdata)
907{
908 char *s, *data;
909 char *p, *saveptr = NULL;
910
911324ef 911 *mntdata = NULL;
91656ce5 912 *mntflags = 0L;
911324ef
DL
913
914 if (!mntopts)
998ac676
RT
915 return 0;
916
911324ef 917 s = strdup(mntopts);
998ac676 918 if (!s) {
36eb9bde 919 SYSERROR("failed to allocate memory");
998ac676
RT
920 return -1;
921 }
922
923 data = malloc(strlen(s) + 1);
924 if (!data) {
36eb9bde 925 SYSERROR("failed to allocate memory");
998ac676
RT
926 free(s);
927 return -1;
928 }
929 *data = 0;
930
931 for (p = strtok_r(s, ",", &saveptr); p != NULL;
932 p = strtok_r(NULL, ",", &saveptr))
933 parse_mntopt(p, mntflags, &data);
934
935 if (*data)
936 *mntdata = data;
937 else
938 free(data);
939 free(s);
940
941 return 0;
942}
943
911324ef
DL
944static int mount_entry(const char *fsname, const char *target,
945 const char *fstype, unsigned long mountflags,
946 const char *data)
947{
948 if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
949 SYSERROR("failed to mount '%s' on '%s'", fsname, target);
950 return -1;
951 }
952
953 if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
954
955 DEBUG("remounting %s on %s to respect bind or remount options",
956 fsname, target);
957
958 if (mount(fsname, target, fstype,
959 mountflags | MS_REMOUNT, data)) {
960 SYSERROR("failed to mount '%s' on '%s'",
961 fsname, target);
962 return -1;
963 }
964 }
965
966 DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
967
968 return 0;
969}
970
971static inline int mount_entry_on_systemfs(struct mntent *mntent)
0ad19a3f 972{
998ac676
RT
973 unsigned long mntflags;
974 char *mntdata;
911324ef
DL
975 int ret;
976
977 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
978 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
979 return -1;
980 }
981
982 ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
983 mntent->mnt_type, mntflags, mntdata);
984
985 free(mntdata);
986
987 return ret;
988}
989
990static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
013bd428 991 const struct lxc_rootfs *rootfs)
911324ef 992{
013bd428 993 char *aux;
59760f5d 994 char path[MAXPATHLEN];
911324ef
DL
995 unsigned long mntflags;
996 char *mntdata;
013bd428 997 int ret = 0;
0ad19a3f 998
911324ef
DL
999 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1000 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1001 return -1;
1002 }
1bc60a65 1003
013bd428
DL
1004 aux = strstr(mntent->mnt_dir, rootfs->path);
1005 if (!aux) {
1006 WARN("ignoring mount point '%s'", mntent->mnt_dir);
1007 goto out;
1008 }
1009
071a2b8c 1010 snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
013bd428 1011 aux + strlen(rootfs->path));
d330fe7b 1012
013bd428 1013 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
911324ef 1014 mntflags, mntdata);
0ad19a3f 1015
013bd428 1016out:
911324ef
DL
1017 free(mntdata);
1018 return ret;
1019}
d330fe7b 1020
911324ef
DL
1021static int mount_entry_on_relative_rootfs(struct mntent *mntent,
1022 const char *rootfs)
1023{
1024 char path[MAXPATHLEN];
1025 unsigned long mntflags;
1026 char *mntdata;
1027 int ret;
d330fe7b 1028
911324ef
DL
1029 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1030 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1031 return -1;
1032 }
d330fe7b 1033
911324ef
DL
1034 /* relative to root mount point */
1035 snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
1036
1037 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1038 mntflags, mntdata);
1039
1040 free(mntdata);
998ac676 1041
911324ef
DL
1042 return ret;
1043}
1044
1045static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
1046{
1047 struct mntent *mntent;
1048 int ret = -1;
e76b8764 1049
911324ef 1050 while ((mntent = getmntent(file))) {
e76b8764 1051
911324ef
DL
1052 if (!rootfs->path) {
1053 if (mount_entry_on_systemfs(mntent))
e76b8764 1054 goto out;
911324ef 1055 continue;
e76b8764
CDC
1056 }
1057
911324ef
DL
1058 /* We have a separate root, mounts are relative to it */
1059 if (mntent->mnt_dir[0] != '/') {
1060 if (mount_entry_on_relative_rootfs(mntent,
1061 rootfs->mount))
1062 goto out;
1063 continue;
1064 }
cd54d859 1065
013bd428 1066 if (mount_entry_on_absolute_rootfs(mntent, rootfs))
911324ef 1067 goto out;
0ad19a3f 1068 }
cd54d859 1069
0ad19a3f 1070 ret = 0;
cd54d859
DL
1071
1072 INFO("mount points have been setup");
0ad19a3f 1073out:
e7938e9e
MN
1074 return ret;
1075}
1076
59760f5d 1077static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab)
e7938e9e
MN
1078{
1079 FILE *file;
1080 int ret;
1081
1082 if (!fstab)
1083 return 0;
1084
1085 file = setmntent(fstab, "r");
1086 if (!file) {
1087 SYSERROR("failed to use '%s'", fstab);
1088 return -1;
1089 }
1090
59760f5d 1091 ret = mount_file_entries(rootfs, file);
e7938e9e 1092
0ad19a3f 1093 endmntent(file);
1094 return ret;
1095}
1096
59760f5d 1097static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount)
e7938e9e
MN
1098{
1099 FILE *file;
1100 struct lxc_list *iterator;
1101 char *mount_entry;
1102 int ret;
1103
1104 file = tmpfile();
1105 if (!file) {
1106 ERROR("tmpfile error: %m");
1107 return -1;
1108 }
1109
1110 lxc_list_for_each(iterator, mount) {
1111 mount_entry = iterator->elem;
1d6b1976 1112 fprintf(file, "%s\n", mount_entry);
e7938e9e
MN
1113 }
1114
1115 rewind(file);
1116
59760f5d 1117 ret = mount_file_entries(rootfs, file);
e7938e9e
MN
1118
1119 fclose(file);
1120 return ret;
1121}
1122
81810dd1
DL
1123static int setup_caps(struct lxc_list *caps)
1124{
1125 struct lxc_list *iterator;
1126 char *drop_entry;
d55bc1ad 1127 char *ptr;
81810dd1
DL
1128 int i, capid;
1129
1130 lxc_list_for_each(iterator, caps) {
1131
1132 drop_entry = iterator->elem;
1133
1134 capid = -1;
1135
1136 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
1137
1138 if (strcmp(drop_entry, caps_opt[i].name))
1139 continue;
1140
1141 capid = caps_opt[i].value;
1142 break;
1143 }
1144
d55bc1ad
CS
1145 if (capid < 0) {
1146 /* try to see if it's numeric, so the user may specify
1147 * capabilities that the running kernel knows about but
1148 * we don't */
1149 capid = strtol(drop_entry, &ptr, 10);
1150 if (!ptr || *ptr != '\0' ||
1151 capid == LONG_MIN || capid == LONG_MAX)
1152 /* not a valid number */
1153 capid = -1;
1154 else if (capid > lxc_caps_last_cap())
1155 /* we have a number but it's not a valid
1156 * capability */
1157 capid = -1;
1158 }
1159
81810dd1 1160 if (capid < 0) {
1e11be34
DL
1161 ERROR("unknown capability %s", drop_entry);
1162 return -1;
81810dd1
DL
1163 }
1164
1165 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
1166
1167 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
1168 SYSERROR("failed to remove %s capability", drop_entry);
1169 return -1;
1170 }
1171
1172 }
1173
1174 DEBUG("capabilities has been setup");
1175
1176 return 0;
1177}
1178
0ad19a3f 1179static int setup_hw_addr(char *hwaddr, const char *ifname)
1180{
1181 struct sockaddr sockaddr;
1182 struct ifreq ifr;
1183 int ret, fd;
1184
3cfc0f3a
MN
1185 ret = lxc_convert_mac(hwaddr, &sockaddr);
1186 if (ret) {
1187 ERROR("mac address '%s' conversion failed : %s",
1188 hwaddr, strerror(-ret));
0ad19a3f 1189 return -1;
1190 }
1191
1192 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1193 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1194
1195 fd = socket(AF_INET, SOCK_DGRAM, 0);
1196 if (fd < 0) {
3ab87b66 1197 ERROR("socket failure : %s", strerror(errno));
0ad19a3f 1198 return -1;
1199 }
1200
1201 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1202 close(fd);
1203 if (ret)
3ab87b66 1204 ERROR("ioctl failure : %s", strerror(errno));
0ad19a3f 1205
cd54d859
DL
1206 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1207
0ad19a3f 1208 return ret;
1209}
1210
82d5ae15 1211static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1212{
82d5ae15
DL
1213 struct lxc_list *iterator;
1214 struct lxc_inetdev *inetdev;
3cfc0f3a 1215 int err;
0ad19a3f 1216
82d5ae15
DL
1217 lxc_list_for_each(iterator, ip) {
1218
1219 inetdev = iterator->elem;
1220
0093bb8c
DL
1221 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
1222 &inetdev->bcast, inetdev->prefix);
3cfc0f3a
MN
1223 if (err) {
1224 ERROR("failed to setup_ipv4_addr ifindex %d : %s",
1225 ifindex, strerror(-err));
82d5ae15
DL
1226 return -1;
1227 }
1228 }
1229
1230 return 0;
0ad19a3f 1231}
1232
82d5ae15 1233static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1234{
82d5ae15 1235 struct lxc_list *iterator;
7fa9074f 1236 struct lxc_inet6dev *inet6dev;
3cfc0f3a 1237 int err;
0ad19a3f 1238
82d5ae15
DL
1239 lxc_list_for_each(iterator, ip) {
1240
1241 inet6dev = iterator->elem;
1242
b3df193c 1243 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
0093bb8c
DL
1244 &inet6dev->mcast, &inet6dev->acast,
1245 inet6dev->prefix);
3cfc0f3a
MN
1246 if (err) {
1247 ERROR("failed to setup_ipv6_addr ifindex %d : %s",
1248 ifindex, strerror(-err));
82d5ae15 1249 return -1;
3cfc0f3a 1250 }
82d5ae15
DL
1251 }
1252
1253 return 0;
0ad19a3f 1254}
1255
82d5ae15 1256static int setup_netdev(struct lxc_netdev *netdev)
0ad19a3f 1257{
0ad19a3f 1258 char ifname[IFNAMSIZ];
0ad19a3f 1259 char *current_ifname = ifname;
3cfc0f3a 1260 int err;
0ad19a3f 1261
82d5ae15
DL
1262 /* empty network namespace */
1263 if (!netdev->ifindex) {
b0efbac4 1264 if (netdev->flags & IFF_UP) {
d472214b 1265 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1266 if (err) {
1267 ERROR("failed to set the loopback up : %s",
1268 strerror(-err));
82d5ae15
DL
1269 return -1;
1270 }
82d5ae15 1271 }
7b57e8b6 1272 return 0;
0ad19a3f 1273 }
13954cce 1274
82d5ae15
DL
1275 /* retrieve the name of the interface */
1276 if (!if_indextoname(netdev->ifindex, current_ifname)) {
36eb9bde 1277 ERROR("no interface corresponding to index '%d'",
82d5ae15 1278 netdev->ifindex);
0ad19a3f 1279 return -1;
1280 }
13954cce 1281
018ef520 1282 /* default: let the system to choose one interface name */
9d083402 1283 if (!netdev->name)
fb6d9b2f
DL
1284 netdev->name = netdev->type == LXC_NET_PHYS ?
1285 netdev->link : "eth%d";
018ef520 1286
82d5ae15 1287 /* rename the interface name */
b84f58b9 1288 err = lxc_netdev_rename_by_name(ifname, netdev->name);
3cfc0f3a
MN
1289 if (err) {
1290 ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
1291 strerror(-err));
018ef520
DL
1292 return -1;
1293 }
1294
1295 /* Re-read the name of the interface because its name has changed
1296 * and would be automatically allocated by the system
1297 */
82d5ae15 1298 if (!if_indextoname(netdev->ifindex, current_ifname)) {
018ef520 1299 ERROR("no interface corresponding to index '%d'",
82d5ae15 1300 netdev->ifindex);
018ef520 1301 return -1;
0ad19a3f 1302 }
1303
82d5ae15
DL
1304 /* set a mac address */
1305 if (netdev->hwaddr) {
1306 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
36eb9bde 1307 ERROR("failed to setup hw address for '%s'",
82d5ae15 1308 current_ifname);
0ad19a3f 1309 return -1;
1310 }
1311 }
1312
82d5ae15
DL
1313 /* setup ipv4 addresses on the interface */
1314 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
36eb9bde 1315 ERROR("failed to setup ip addresses for '%s'",
0ad19a3f 1316 ifname);
1317 return -1;
1318 }
1319
82d5ae15
DL
1320 /* setup ipv6 addresses on the interface */
1321 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
36eb9bde 1322 ERROR("failed to setup ipv6 addresses for '%s'",
0ad19a3f 1323 ifname);
1324 return -1;
1325 }
1326
82d5ae15 1327 /* set the network device up */
b0efbac4 1328 if (netdev->flags & IFF_UP) {
3cfc0f3a
MN
1329 int err;
1330
d472214b 1331 err = lxc_netdev_up(current_ifname);
3cfc0f3a
MN
1332 if (err) {
1333 ERROR("failed to set '%s' up : %s", current_ifname,
1334 strerror(-err));
0ad19a3f 1335 return -1;
1336 }
1337
1338 /* the network is up, make the loopback up too */
d472214b 1339 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1340 if (err) {
1341 ERROR("failed to set the loopback up : %s",
1342 strerror(-err));
0ad19a3f 1343 return -1;
1344 }
1345 }
1346
f8fee0e2
MK
1347 /* We can only set up the default routes after bringing
1348 * up the interface, sine bringing up the interface adds
1349 * the link-local routes and we can't add a default
1350 * route if the gateway is not reachable. */
1351
1352 /* setup ipv4 gateway on the interface */
1353 if (netdev->ipv4_gateway) {
1354 if (!(netdev->flags & IFF_UP)) {
1355 ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname);
1356 return -1;
1357 }
1358
1359 if (lxc_list_empty(&netdev->ipv4)) {
1360 ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname);
1361 return -1;
1362 }
1363
1364 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
1365 if (err) {
1366 ERROR("failed to setup ipv4 gateway for '%s': %s",
1367 ifname, strerror(-err));
19a26f82
MK
1368 if (netdev->ipv4_gateway_auto) {
1369 char buf[INET_ADDRSTRLEN];
1370 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
1371 ERROR("tried to set autodetected ipv4 gateway '%s'", buf);
1372 }
f8fee0e2
MK
1373 return -1;
1374 }
1375 }
1376
1377 /* setup ipv6 gateway on the interface */
1378 if (netdev->ipv6_gateway) {
1379 if (!(netdev->flags & IFF_UP)) {
1380 ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname);
1381 return -1;
1382 }
1383
1384 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
1385 ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname);
1386 return -1;
1387 }
1388
1389 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
1390 if (err) {
1391 ERROR("failed to setup ipv6 gateway for '%s': %s",
1392 ifname, strerror(-err));
19a26f82
MK
1393 if (netdev->ipv6_gateway_auto) {
1394 char buf[INET6_ADDRSTRLEN];
1395 inet_ntop(AF_INET, netdev->ipv6_gateway, buf, sizeof(buf));
1396 ERROR("tried to set autodetected ipv6 gateway '%s'", buf);
1397 }
f8fee0e2
MK
1398 return -1;
1399 }
1400 }
1401
cd54d859
DL
1402 DEBUG("'%s' has been setup", current_ifname);
1403
0ad19a3f 1404 return 0;
1405}
1406
5f4535a3 1407static int setup_network(struct lxc_list *network)
0ad19a3f 1408{
82d5ae15 1409 struct lxc_list *iterator;
82d5ae15 1410 struct lxc_netdev *netdev;
0ad19a3f 1411
5f4535a3 1412 lxc_list_for_each(iterator, network) {
cd54d859 1413
5f4535a3 1414 netdev = iterator->elem;
82d5ae15
DL
1415
1416 if (setup_netdev(netdev)) {
1417 ERROR("failed to setup netdev");
1418 return -1;
1419 }
1420 }
cd54d859 1421
5f4535a3
DL
1422 if (!lxc_list_empty(network))
1423 INFO("network has been setup");
cd54d859
DL
1424
1425 return 0;
0ad19a3f 1426}
1427
49684c0b
CS
1428static int setup_private_host_hw_addr(char *veth1)
1429{
1430 struct ifreq ifr;
1431 int err;
1432 int sockfd;
1433
1434 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1435 if (sockfd < 0)
1436 return -errno;
1437
1438 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
1439 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
1440 if (err < 0) {
1441 close(sockfd);
1442 return -errno;
1443 }
1444
1445 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
1446 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
1447 close(sockfd);
1448 if (err < 0)
1449 return -errno;
1450
7ad84da7
DL
1451 DEBUG("mac address of host interface '%s' changed to private "
1452 "%02x:%02x:%02x:%02x:%02x:%02x", veth1,
1453 ifr.ifr_hwaddr.sa_data[0] & 0xff,
1454 ifr.ifr_hwaddr.sa_data[1] & 0xff,
1455 ifr.ifr_hwaddr.sa_data[2] & 0xff,
1456 ifr.ifr_hwaddr.sa_data[3] & 0xff,
1457 ifr.ifr_hwaddr.sa_data[4] & 0xff,
1458 ifr.ifr_hwaddr.sa_data[5] & 0xff);
49684c0b
CS
1459
1460 return 0;
1461}
1462
7b379ab3 1463struct lxc_conf *lxc_conf_init(void)
089cd8b8 1464{
7b379ab3
MN
1465 struct lxc_conf *new;
1466
1467 new = malloc(sizeof(*new));
1468 if (!new) {
1469 ERROR("lxc_conf_init : %m");
1470 return NULL;
1471 }
1472 memset(new, 0, sizeof(*new));
1473
cccc74b5 1474 new->personality = -1;
28a4b0e5 1475 new->console.path = NULL;
63376d7d
DL
1476 new->console.peer = -1;
1477 new->console.master = -1;
1478 new->console.slave = -1;
1479 new->console.name[0] = '\0';
12297168 1480 new->rootfs.mount = LXCROOTFSMOUNT;
7b379ab3
MN
1481 lxc_list_init(&new->cgroup);
1482 lxc_list_init(&new->network);
1483 lxc_list_init(&new->mount_list);
81810dd1 1484 lxc_list_init(&new->caps);
7b379ab3
MN
1485
1486 return new;
089cd8b8
DL
1487}
1488
e3b4c4c4 1489static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1490{
8634bc19 1491 char veth1buf[IFNAMSIZ], *veth1;
0e391e57 1492 char veth2buf[IFNAMSIZ], *veth2;
3cfc0f3a 1493 int err;
13954cce 1494
e892973e
DL
1495 if (netdev->priv.veth_attr.pair)
1496 veth1 = netdev->priv.veth_attr.pair;
8634bc19
MT
1497 else {
1498 snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
0e391e57 1499 veth1 = mktemp(veth1buf);
8634bc19 1500 }
82d5ae15 1501
0e391e57
DL
1502 snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
1503 veth2 = mktemp(veth2buf);
82d5ae15
DL
1504
1505 if (!strlen(veth1) || !strlen(veth2)) {
1506 ERROR("failed to allocate a temporary name");
1507 return -1;
0ad19a3f 1508 }
1509
3cfc0f3a
MN
1510 err = lxc_veth_create(veth1, veth2);
1511 if (err) {
1512 ERROR("failed to create %s-%s : %s", veth1, veth2,
1513 strerror(-err));
6ab9ab6d 1514 return -1;
0ad19a3f 1515 }
13954cce 1516
49684c0b
CS
1517 /* changing the high byte of the mac address to 0xfe, the bridge interface
1518 * will always keep the host's mac address and not take the mac address
1519 * of a container */
1520 err = setup_private_host_hw_addr(veth1);
1521 if (err) {
1522 ERROR("failed to change mac address of host interface '%s' : %s",
1523 veth1, strerror(-err));
1524 goto out_delete;
1525 }
1526
82d5ae15 1527 if (netdev->mtu) {
d472214b 1528 err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
3cfc0f3a 1529 if (!err)
d472214b 1530 err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
3cfc0f3a
MN
1531 if (err) {
1532 ERROR("failed to set mtu '%s' for %s-%s : %s",
1533 netdev->mtu, veth1, veth2, strerror(-err));
eb14c10a 1534 goto out_delete;
75d09f83
DL
1535 }
1536 }
1537
3cfc0f3a
MN
1538 if (netdev->link) {
1539 err = lxc_bridge_attach(netdev->link, veth1);
1540 if (err) {
1541 ERROR("failed to attach '%s' to the bridge '%s' : %s",
1542 veth1, netdev->link, strerror(-err));
1543 goto out_delete;
1544 }
eb14c10a
DL
1545 }
1546
82d5ae15
DL
1547 netdev->ifindex = if_nametoindex(veth2);
1548 if (!netdev->ifindex) {
36eb9bde 1549 ERROR("failed to retrieve the index for %s", veth2);
eb14c10a
DL
1550 goto out_delete;
1551 }
1552
d472214b 1553 err = lxc_netdev_up(veth1);
6e35af2e
DL
1554 if (err) {
1555 ERROR("failed to set %s up : %s", veth1, strerror(-err));
1556 goto out_delete;
0ad19a3f 1557 }
1558
e3b4c4c4 1559 if (netdev->upscript) {
751d9dcd
DL
1560 err = run_script(handler->name, "net", netdev->upscript, "up",
1561 "veth", veth1, (char*) NULL);
1562 if (err)
e3b4c4c4 1563 goto out_delete;
e3b4c4c4
ST
1564 }
1565
82d5ae15
DL
1566 DEBUG("instanciated veth '%s/%s', index is '%d'",
1567 veth1, veth2, netdev->ifindex);
1568
6ab9ab6d 1569 return 0;
eb14c10a
DL
1570
1571out_delete:
b84f58b9 1572 lxc_netdev_delete_by_name(veth1);
6ab9ab6d 1573 return -1;
13954cce 1574}
d957ae2d 1575
e3b4c4c4 1576static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1577{
0e391e57 1578 char peerbuf[IFNAMSIZ], *peer;
3cfc0f3a 1579 int err;
d957ae2d
MT
1580
1581 if (!netdev->link) {
1582 ERROR("no link specified for macvlan netdev");
1583 return -1;
1584 }
13954cce 1585
0e391e57 1586 snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
82d5ae15 1587
0e391e57 1588 peer = mktemp(peerbuf);
82d5ae15
DL
1589 if (!strlen(peer)) {
1590 ERROR("failed to make a temporary name");
1591 return -1;
0ad19a3f 1592 }
1593
3cfc0f3a
MN
1594 err = lxc_macvlan_create(netdev->link, peer,
1595 netdev->priv.macvlan_attr.mode);
1596 if (err) {
1597 ERROR("failed to create macvlan interface '%s' on '%s' : %s",
1598 peer, netdev->link, strerror(-err));
d957ae2d 1599 return -1;
0ad19a3f 1600 }
1601
82d5ae15
DL
1602 netdev->ifindex = if_nametoindex(peer);
1603 if (!netdev->ifindex) {
36eb9bde 1604 ERROR("failed to retrieve the index for %s", peer);
b84f58b9 1605 lxc_netdev_delete_by_name(peer);
d957ae2d 1606 return -1;
22ebac19 1607 }
1608
e3b4c4c4 1609 if (netdev->upscript) {
751d9dcd
DL
1610 err = run_script(handler->name, "net", netdev->upscript, "up",
1611 "macvlan", netdev->link, (char*) NULL);
1612 if (err)
e3b4c4c4 1613 return -1;
e3b4c4c4
ST
1614 }
1615
e892973e
DL
1616 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
1617 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
0ad19a3f 1618
d957ae2d 1619 return 0;
0ad19a3f 1620}
1621
26c39028 1622/* XXX: merge with instanciate_macvlan */
e3b4c4c4 1623static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
26c39028
JHS
1624{
1625 char peer[IFNAMSIZ];
3cfc0f3a 1626 int err;
26c39028
JHS
1627
1628 if (!netdev->link) {
1629 ERROR("no link specified for vlan netdev");
1630 return -1;
1631 }
1632
e892973e 1633 snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
26c39028 1634
3cfc0f3a
MN
1635 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
1636 if (err) {
1637 ERROR("failed to create vlan interface '%s' on '%s' : %s",
1638 peer, netdev->link, strerror(-err));
26c39028
JHS
1639 return -1;
1640 }
1641
1642 netdev->ifindex = if_nametoindex(peer);
1643 if (!netdev->ifindex) {
1644 ERROR("failed to retrieve the ifindex for %s", peer);
b84f58b9 1645 lxc_netdev_delete_by_name(peer);
26c39028
JHS
1646 return -1;
1647 }
1648
e892973e
DL
1649 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
1650 netdev->ifindex);
1651
26c39028
JHS
1652 return 0;
1653}
1654
e3b4c4c4 1655static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1656{
6168e99f
DL
1657 if (!netdev->link) {
1658 ERROR("no link specified for the physical interface");
1659 return -1;
1660 }
1661
9d083402 1662 netdev->ifindex = if_nametoindex(netdev->link);
82d5ae15 1663 if (!netdev->ifindex) {
9d083402 1664 ERROR("failed to retrieve the index for %s", netdev->link);
0ad19a3f 1665 return -1;
1666 }
1667
e3b4c4c4
ST
1668 if (netdev->upscript) {
1669 int err;
751d9dcd
DL
1670 err = run_script(handler->name, "net", netdev->upscript,
1671 "up", "phys", netdev->link, (char*) NULL);
1672 if (err)
e3b4c4c4 1673 return -1;
e3b4c4c4
ST
1674 }
1675
82d5ae15 1676 return 0;
0ad19a3f 1677}
1678
e3b4c4c4 1679static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 1680{
82d5ae15 1681 netdev->ifindex = 0;
e3b4c4c4
ST
1682 if (netdev->upscript) {
1683 int err;
751d9dcd
DL
1684 err = run_script(handler->name, "net", netdev->upscript,
1685 "up", "empty", (char*) NULL);
1686 if (err)
e3b4c4c4 1687 return -1;
e3b4c4c4 1688 }
82d5ae15 1689 return 0;
0ad19a3f 1690}
1691
e3b4c4c4 1692int lxc_create_network(struct lxc_handler *handler)
0ad19a3f 1693{
e3b4c4c4 1694 struct lxc_list *network = &handler->conf->network;
82d5ae15 1695 struct lxc_list *iterator;
82d5ae15 1696 struct lxc_netdev *netdev;
0ad19a3f 1697
5f4535a3 1698 lxc_list_for_each(iterator, network) {
0ad19a3f 1699
5f4535a3 1700 netdev = iterator->elem;
13954cce 1701
24654103 1702 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
82d5ae15 1703 ERROR("invalid network configuration type '%d'",
5f4535a3 1704 netdev->type);
82d5ae15
DL
1705 return -1;
1706 }
0ad19a3f 1707
e3b4c4c4 1708 if (netdev_conf[netdev->type](handler, netdev)) {
82d5ae15
DL
1709 ERROR("failed to create netdev");
1710 return -1;
1711 }
e3b4c4c4 1712
0ad19a3f 1713 }
1714
1715 return 0;
1716}
1717
7fef7a06
DL
1718void lxc_delete_network(struct lxc_list *network)
1719{
1720 struct lxc_list *iterator;
1721 struct lxc_netdev *netdev;
1722
1723 lxc_list_for_each(iterator, network) {
1724 netdev = iterator->elem;
d472214b
DL
1725 if (netdev->ifindex == 0)
1726 continue;
1727
d8f8e352
DL
1728 if (netdev->type == LXC_NET_PHYS) {
1729 if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
1730 WARN("failed to rename to the initial name the " \
1731 "netdev '%s'", netdev->link);
d472214b 1732 continue;
d8f8e352 1733 }
d472214b 1734
d8f8e352
DL
1735 /* Recent kernel remove the virtual interfaces when the network
1736 * namespace is destroyed but in case we did not moved the
1737 * interface to the network namespace, we have to destroy it
1738 */
1739 if (lxc_netdev_delete_by_index(netdev->ifindex))
1740 WARN("failed to remove interface '%s'", netdev->name);
7fef7a06
DL
1741 }
1742}
1743
5f4535a3 1744int lxc_assign_network(struct lxc_list *network, pid_t pid)
0ad19a3f 1745{
82d5ae15 1746 struct lxc_list *iterator;
82d5ae15 1747 struct lxc_netdev *netdev;
3cfc0f3a 1748 int err;
0ad19a3f 1749
5f4535a3 1750 lxc_list_for_each(iterator, network) {
82d5ae15 1751
5f4535a3 1752 netdev = iterator->elem;
82d5ae15 1753
236087a6
DL
1754 /* empty network namespace, nothing to move */
1755 if (!netdev->ifindex)
1756 continue;
1757
d472214b 1758 err = lxc_netdev_move_by_index(netdev->ifindex, pid);
3cfc0f3a
MN
1759 if (err) {
1760 ERROR("failed to move '%s' to the container : %s",
1761 netdev->link, strerror(-err));
82d5ae15
DL
1762 return -1;
1763 }
1764
c1c75c04 1765 DEBUG("move '%s' to '%d'", netdev->name, pid);
0ad19a3f 1766 }
1767
1768 return 0;
1769}
1770
19a26f82
MK
1771int lxc_find_gateway_addresses(struct lxc_handler *handler)
1772{
1773 struct lxc_list *network = &handler->conf->network;
1774 struct lxc_list *iterator;
1775 struct lxc_netdev *netdev;
1776 int link_index;
1777
1778 lxc_list_for_each(iterator, network) {
1779 netdev = iterator->elem;
1780
1781 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
1782 continue;
1783
1784 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
1785 ERROR("gateway = auto only supported for "
1786 "veth and macvlan");
1787 return -1;
1788 }
1789
1790 if (!netdev->link) {
1791 ERROR("gateway = auto needs a link interface");
1792 return -1;
1793 }
1794
1795 link_index = if_nametoindex(netdev->link);
1796 if (!link_index)
1797 return -EINVAL;
1798
1799 if (netdev->ipv4_gateway_auto) {
1800 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
1801 ERROR("failed to automatically find ipv4 gateway "
1802 "address from link interface '%s'", netdev->link);
1803 return -1;
1804 }
1805 }
1806
1807 if (netdev->ipv6_gateway_auto) {
1808 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
1809 ERROR("failed to automatically find ipv6 gateway "
1810 "address from link interface '%s'", netdev->link);
1811 return -1;
1812 }
1813 }
1814 }
1815
1816 return 0;
1817}
1818
5e4a62bf 1819int lxc_create_tty(const char *name, struct lxc_conf *conf)
b0a33c1e 1820{
5e4a62bf 1821 struct lxc_tty_info *tty_info = &conf->tty_info;
985d15b1 1822 int i;
b0a33c1e 1823
5e4a62bf
DL
1824 /* no tty in the configuration */
1825 if (!conf->tty)
b0a33c1e 1826 return 0;
1827
13954cce 1828 tty_info->pty_info =
e4e7d59d 1829 malloc(sizeof(*tty_info->pty_info)*conf->tty);
b0a33c1e 1830 if (!tty_info->pty_info) {
36eb9bde 1831 SYSERROR("failed to allocate pty_info");
985d15b1 1832 return -1;
b0a33c1e 1833 }
1834
985d15b1 1835 for (i = 0; i < conf->tty; i++) {
13954cce 1836
b0a33c1e 1837 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1838
13954cce 1839 if (openpty(&pty_info->master, &pty_info->slave,
b0a33c1e 1840 pty_info->name, NULL, NULL)) {
36eb9bde 1841 SYSERROR("failed to create pty #%d", i);
985d15b1
MT
1842 tty_info->nbtty = i;
1843 lxc_delete_tty(tty_info);
1844 return -1;
b0a33c1e 1845 }
1846
5332bb84
DL
1847 DEBUG("allocated pty '%s' (%d/%d)",
1848 pty_info->name, pty_info->master, pty_info->slave);
1849
b035ad62
MS
1850 /* Prevent leaking the file descriptors to the container */
1851 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1852 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1853
b0a33c1e 1854 pty_info->busy = 0;
1855 }
1856
985d15b1 1857 tty_info->nbtty = conf->tty;
1ac470c0
DL
1858
1859 INFO("tty's configured");
1860
985d15b1 1861 return 0;
b0a33c1e 1862}
1863
1864void lxc_delete_tty(struct lxc_tty_info *tty_info)
1865{
1866 int i;
1867
1868 for (i = 0; i < tty_info->nbtty; i++) {
1869 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1870
1871 close(pty_info->master);
1872 close(pty_info->slave);
1873 }
1874
1875 free(tty_info->pty_info);
1876 tty_info->nbtty = 0;
1877}
1878
571e6ec8 1879int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
0ad19a3f 1880{
571e6ec8 1881 if (setup_utsname(lxc_conf->utsname)) {
36eb9bde 1882 ERROR("failed to setup the utsname for '%s'", name);
95b5ffaf 1883 return -1;
0ad19a3f 1884 }
1885
5f4535a3 1886 if (setup_network(&lxc_conf->network)) {
36eb9bde 1887 ERROR("failed to setup the network for '%s'", name);
95b5ffaf 1888 return -1;
0ad19a3f 1889 }
1890
ac778708
DL
1891 if (setup_rootfs(&lxc_conf->rootfs)) {
1892 ERROR("failed to setup rootfs for '%s'", name);
95b5ffaf 1893 return -1;
0ad19a3f 1894 }
1895
59760f5d 1896 if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab)) {
36eb9bde 1897 ERROR("failed to setup the mounts for '%s'", name);
95b5ffaf 1898 return -1;
576f946d 1899 }
1900
59760f5d 1901 if (setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list)) {
e7938e9e
MN
1902 ERROR("failed to setup the mount entries for '%s'", name);
1903 return -1;
1904 }
1905
ac778708
DL
1906 if (setup_cgroup(name, &lxc_conf->cgroup)) {
1907 ERROR("failed to setup the cgroups for '%s'", name);
1908 return -1;
1909 }
1910
33fcb7a0 1911 if (setup_console(&lxc_conf->rootfs, &lxc_conf->console)) {
36eb9bde 1912 ERROR("failed to setup the console for '%s'", name);
95b5ffaf 1913 return -1;
6e590161 1914 }
1915
33fcb7a0 1916 if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info)) {
36eb9bde 1917 ERROR("failed to setup the ttys for '%s'", name);
95b5ffaf 1918 return -1;
b0a33c1e 1919 }
1920
ac778708 1921 if (setup_pivot_root(&lxc_conf->rootfs)) {
36eb9bde 1922 ERROR("failed to set rootfs for '%s'", name);
95b5ffaf 1923 return -1;
ed502555 1924 }
1925
571e6ec8 1926 if (setup_pts(lxc_conf->pts)) {
36eb9bde 1927 ERROR("failed to setup the new pts instance");
95b5ffaf 1928 return -1;
3c26f34e 1929 }
1930
cccc74b5
DL
1931 if (setup_personality(lxc_conf->personality)) {
1932 ERROR("failed to setup personality");
1933 return -1;
1934 }
1935
81810dd1
DL
1936 if (setup_caps(&lxc_conf->caps)) {
1937 ERROR("failed to drop capabilities");
1938 return -1;
1939 }
1940
cd54d859
DL
1941 NOTICE("'%s' is setup.", name);
1942
0ad19a3f 1943 return 0;
1944}