]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/conf.c
remove logfile and loglevel from struct lxc_conf
[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>
0ad19a3f 31#include <unistd.h>
e3b4c4c4 32#include <sys/wait.h>
2d76d1d7 33#include <sys/syscall.h>
e827ff7e
SG
34
35#if HAVE_PTY_H
b0a33c1e 36#include <pty.h>
e827ff7e
SG
37#else
38#include <../include/openpty.h>
39#endif
0ad19a3f 40
b3ecde1e
DL
41#include <linux/loop.h>
42
0ad19a3f 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>
81810dd1 50#include <sys/prctl.h>
0ad19a3f 51
52#include <arpa/inet.h>
53#include <fcntl.h>
54#include <netinet/in.h>
55#include <net/if.h>
6f4a3756 56#include <libgen.h>
0ad19a3f 57
e5bda9ee 58#include "network.h"
59#include "error.h"
b2718c72 60#include "parse.h"
881450bb 61#include "config.h"
1b09f2c0
DL
62#include "utils.h"
63#include "conf.h"
64#include "log.h"
65#include "lxc.h" /* for lxc_cgroup_set() */
d55bc1ad 66#include "caps.h" /* for lxc_caps_last_cap() */
36eb9bde 67
d0a36f2c
SG
68#if HAVE_APPARMOR
69#include <apparmor.h>
70#endif
71
495d2046
SG
72#if HAVE_SYS_CAPABILITY_H
73#include <sys/capability.h>
74#endif
75
6ff05e18
SG
76#if HAVE_SYS_PERSONALITY_H
77#include <sys/personality.h>
78#endif
79
edaf8b1b
SG
80#if IS_BIONIC
81#include <../include/lxcmntent.h>
82#else
83#include <mntent.h>
84#endif
85
769872f9
SH
86#include "lxcseccomp.h"
87
36eb9bde 88lxc_log_define(lxc_conf, lxc);
e5bda9ee 89
0ad19a3f 90#define MAXHWLEN 18
91#define MAXINDEXLEN 20
442cbbe6 92#define MAXMTULEN 16
0ad19a3f 93#define MAXLINELEN 128
94
968fbd36
SK
95#ifndef MS_DIRSYNC
96#define MS_DIRSYNC 128
97#endif
98
fdc03323
DL
99#ifndef MS_REC
100#define MS_REC 16384
101#endif
102
c08556c6
DL
103#ifndef MNT_DETACH
104#define MNT_DETACH 2
105#endif
106
859a6da0
NC
107#ifndef MS_SLAVE
108#define MS_SLAVE (1<<19)
109#endif
110
88d413d5
SW
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
495d2046 119#if HAVE_SYS_CAPABILITY_H
b09094da
MN
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
495d2046 131#endif
b09094da
MN
132
133#ifndef PR_CAPBSET_DROP
134#define PR_CAPBSET_DROP 24
135#endif
136
9818cae4
SG
137#ifndef LO_FLAGS_AUTOCLEAR
138#define LO_FLAGS_AUTOCLEAR 4
139#endif
140
2d76d1d7
SG
141/* Define pivot_root() if missing from the C library */
142#ifndef HAVE_PIVOT_ROOT
143static int pivot_root(const char * new_root, const char * put_old)
144{
145#ifdef __NR_pivot_root
146return syscall(__NR_pivot_root, new_root, put_old);
147#else
148errno = ENOSYS;
149return -1;
150#endif
151}
152#else
153extern 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
158static int sethostname(const char * name, size_t len)
159{
160#ifdef __NR_sethostname
161return syscall(__NR_sethostname, name, len);
162#else
163errno = ENOSYS;
164return -1;
165#endif
166}
167#endif
168
72f919c4
SG
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
72d0e1cb 174char *lxchook_names[NUM_LXC_HOOKS] = {
5ea6163a 175 "pre-start", "pre-mount", "mount", "start", "post-stop" };
72d0e1cb 176
e3b4c4c4 177typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
0ad19a3f 178
998ac676
RT
179struct mount_opt {
180 char *name;
181 int clear;
182 int flag;
183};
184
81810dd1
DL
185struct caps_opt {
186 char *name;
187 int value;
188};
189
e3b4c4c4
ST
190static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
191static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
192static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
193static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
194static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
82d5ae15 195
24654103
DL
196static 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,
0ad19a3f 202};
203
74a2b586
JK
204static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *);
205static int shutdown_macvlan(struct lxc_handler *, struct lxc_netdev *);
206static int shutdown_vlan(struct lxc_handler *, struct lxc_netdev *);
207static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *);
208static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *);
209
210static 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
998ac676 218static struct mount_opt mount_opt[] = {
88d413d5
SW
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 },
998ac676
RT
245};
246
495d2046 247#if HAVE_SYS_CAPABILITY_H
81810dd1 248static struct caps_opt caps_opt[] = {
a6afdde9 249 { "chown", CAP_CHOWN },
1e11be34
DL
250 { "dac_override", CAP_DAC_OVERRIDE },
251 { "dac_read_search", CAP_DAC_READ_SEARCH },
252 { "fowner", CAP_FOWNER },
253 { "fsetid", CAP_FSETID },
81810dd1
DL
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 },
9527e566 278#ifdef CAP_AUDIT_WRITE
81810dd1 279 { "audit_write", CAP_AUDIT_WRITE },
9527e566
FW
280#endif
281#ifdef CAP_AUDIT_CONTROL
81810dd1 282 { "audit_control", CAP_AUDIT_CONTROL },
9527e566 283#endif
81810dd1
DL
284 { "setfcap", CAP_SETFCAP },
285 { "mac_override", CAP_MAC_OVERRIDE },
286 { "mac_admin", CAP_MAC_ADMIN },
5170c716
CS
287#ifdef CAP_SYSLOG
288 { "syslog", CAP_SYSLOG },
289#endif
290#ifdef CAP_WAKE_ALARM
291 { "wake_alarm", CAP_WAKE_ALARM },
292#endif
81810dd1 293};
495d2046
SG
294#else
295static struct caps_opt caps_opt[] = {};
296#endif
81810dd1 297
91c3830e
SH
298static 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
751d9dcd
DL
328static int run_script(const char *name, const char *section,
329 const char *script, ...)
e3b4c4c4 330{
abbfd20b 331 int ret;
91c3830e 332 char *buffer, *p;
abbfd20b
DL
333 size_t size = 0;
334 va_list ap;
751d9dcd
DL
335
336 INFO("Executing script '%s' for container '%s', config section '%s'",
337 script, name, section);
e3b4c4c4 338
abbfd20b
DL
339 va_start(ap, script);
340 while ((p = va_arg(ap, char *)))
95642a10 341 size += strlen(p) + 1;
abbfd20b
DL
342 va_end(ap);
343
344 size += strlen(script);
345 size += strlen(name);
346 size += strlen(section);
95642a10 347 size += 3;
abbfd20b 348
95642a10
MS
349 if (size > INT_MAX)
350 return -1;
351
352 buffer = alloca(size);
abbfd20b
DL
353 if (!buffer) {
354 ERROR("failed to allocate memory");
751d9dcd
DL
355 return -1;
356 }
357
9ba8130c
SH
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 }
751d9dcd 364
abbfd20b 365 va_start(ap, script);
9ba8130c
SH
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 }
abbfd20b 377 va_end(ap);
751d9dcd 378
91c3830e 379 return run_buffer(buffer);
e3b4c4c4
ST
380}
381
a6afdde9 382static int find_fstype_cb(char* buffer, void *data)
78ae2fcc 383{
384 struct cbarg {
385 const char *rootfs;
a6afdde9 386 const char *target;
78ae2fcc 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;
b2718c72 397 fstype += lxc_char_left_gc(fstype, strlen(fstype));
398 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
78ae2fcc 399
a6afdde9
DL
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));
78ae2fcc 405 return 0;
a6afdde9 406 }
78ae2fcc 407
a6afdde9
DL
408 INFO("mounted '%s' on '%s', with fstype '%s'",
409 cbarg->rootfs, cbarg->target, fstype);
78ae2fcc 410
411 return 1;
412}
413
2656d231 414static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
78ae2fcc 415{
a6afdde9 416 int i;
78ae2fcc 417
418 struct cbarg {
419 const char *rootfs;
a6afdde9 420 const char *target;
78ae2fcc 421 int mntopt;
422 } cbarg = {
423 .rootfs = rootfs,
a6afdde9 424 .target = target,
78ae2fcc 425 .mntopt = mntopt,
426 };
427
a6afdde9
DL
428 /*
429 * find the filesystem type with brute force:
430 * first we check with /etc/filesystems, in case the modules
78ae2fcc 431 * are auto-loaded and fall back to the supported kernel fs
432 */
433 char *fsfile[] = {
434 "/etc/filesystems",
435 "/proc/filesystems",
436 };
437
a6afdde9
DL
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;
78ae2fcc 453 }
454
a6afdde9
DL
455 ERROR("failed to determine fs type for '%s'", rootfs);
456 return -1;
457}
458
2656d231 459static int mount_rootfs_dir(const char *rootfs, const char *target)
a6afdde9
DL
460{
461 return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
462}
463
464static 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);
78ae2fcc 472 return -1;
473 }
474
a6afdde9 475 memset(loinfo, 0, sizeof(*loinfo));
78ae2fcc 476
a6afdde9 477 loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
78ae2fcc 478
a6afdde9
DL
479 if (ioctl(fd, LOOP_SET_FD, rfd)) {
480 SYSERROR("failed to LOOP_SET_FD");
481 goto out;
78ae2fcc 482 }
483
a6afdde9
DL
484 if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
485 SYSERROR("failed to LOOP_SET_STATUS64");
78ae2fcc 486 goto out;
487 }
488
a6afdde9 489 ret = 0;
78ae2fcc 490out:
a6afdde9 491 close(rfd);
78ae2fcc 492
a6afdde9 493 return ret;
78ae2fcc 494}
495
2656d231 496static int mount_rootfs_file(const char *rootfs, const char *target)
78ae2fcc 497{
a6afdde9
DL
498 struct dirent dirent, *direntp;
499 struct loop_info64 loinfo;
9ba8130c 500 int ret = -1, fd = -1, rc;
a6afdde9
DL
501 DIR *dir;
502 char path[MAXPATHLEN];
78ae2fcc 503
a6afdde9
DL
504 dir = opendir("/dev");
505 if (!dir) {
506 SYSERROR("failed to open '/dev'");
78ae2fcc 507 return -1;
508 }
509
a6afdde9
DL
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
9ba8130c
SH
524 rc = snprintf(path, MAXPATHLEN, "/dev/%s", direntp->d_name);
525 if (rc < 0 || rc >= MAXPATHLEN)
526 continue;
527
a6afdde9
DL
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)
2656d231 547 ret = mount_unknow_fs(path, target, 0);
a6afdde9
DL
548 close(fd);
549
550 break;
551 }
552
553 if (closedir(dir))
554 WARN("failed to close directory");
555
556 return ret;
78ae2fcc 557}
558
2656d231 559static int mount_rootfs_block(const char *rootfs, const char *target)
a6afdde9 560{
2656d231 561 return mount_unknow_fs(rootfs, target, 0);
a6afdde9
DL
562}
563
0c547523
SH
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 */
573int pin_rootfs(const char *rootfs)
574{
575 char absrootfs[MAXPATHLEN];
576 char absrootfspin[MAXPATHLEN];
577 struct stat s;
578 int ret, fd;
579
e99ee0de
SH
580 if (rootfs == NULL || strlen(rootfs) == 0)
581 return 0;
582
0c547523
SH
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
72f919c4 598 if (!S_ISDIR(s.st_mode))
0c547523
SH
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
2656d231 612static int mount_rootfs(const char *rootfs, const char *target)
0ad19a3f 613{
b09ef133 614 char absrootfs[MAXPATHLEN];
78ae2fcc 615 struct stat s;
a6afdde9 616 int i;
78ae2fcc 617
a6afdde9 618 typedef int (*rootfs_cb)(const char *, const char *);
78ae2fcc 619
620 struct rootfs_type {
621 int type;
622 rootfs_cb cb;
623 } rtfs_type[] = {
2656d231
DL
624 { S_IFDIR, mount_rootfs_dir },
625 { S_IFBLK, mount_rootfs_block },
626 { S_IFREG, mount_rootfs_file },
78ae2fcc 627 };
0ad19a3f 628
4c8ab83b 629 if (!realpath(rootfs, absrootfs)) {
36eb9bde 630 SYSERROR("failed to get real path for '%s'", rootfs);
4c8ab83b 631 return -1;
632 }
b09ef133 633
b09ef133 634 if (access(absrootfs, F_OK)) {
36eb9bde 635 SYSERROR("'%s' is not accessible", absrootfs);
b09ef133 636 return -1;
637 }
638
78ae2fcc 639 if (stat(absrootfs, &s)) {
36eb9bde 640 SYSERROR("failed to stat '%s'", absrootfs);
9b0f0477 641 return -1;
642 }
643
78ae2fcc 644 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
9b0f0477 645
78ae2fcc 646 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
647 continue;
9b0f0477 648
a6afdde9 649 return rtfs_type[i].cb(absrootfs, target);
78ae2fcc 650 }
9b0f0477 651
36eb9bde 652 ERROR("unsupported rootfs type for '%s'", absrootfs);
78ae2fcc 653 return -1;
0ad19a3f 654}
655
4e5440c6 656static int setup_utsname(struct utsname *utsname)
0ad19a3f 657{
4e5440c6
DL
658 if (!utsname)
659 return 0;
0ad19a3f 660
4e5440c6
DL
661 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
662 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
0ad19a3f 663 return -1;
664 }
665
4e5440c6 666 INFO("'%s' hostname has been setup", utsname->nodename);
cd54d859 667
0ad19a3f 668 return 0;
669}
670
33fcb7a0 671static int setup_tty(const struct lxc_rootfs *rootfs,
7c6ef2a2 672 const struct lxc_tty_info *tty_info, char *ttydir)
b0a33c1e 673{
7c6ef2a2
SH
674 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
675 int i, ret;
b0a33c1e 676
bc9bd0e3
DL
677 if (!rootfs->path)
678 return 0;
679
b0a33c1e 680 for (i = 0; i < tty_info->nbtty; i++) {
681
682 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
683
7c6ef2a2 684 ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
12297168 685 rootfs->mount, i + 1);
7c6ef2a2
SH
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" */
9ba8130c 692 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
7c6ef2a2
SH
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 }
b0a33c1e 709
7c6ef2a2
SH
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 }
13954cce 715
9ba8130c
SH
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 }
7c6ef2a2
SH
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 {
c6883f38
SH
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 }
7c6ef2a2
SH
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 }
b0a33c1e 741 }
742 }
743
cd54d859
DL
744 INFO("%d tty(s) has been setup", tty_info->nbtty);
745
b0a33c1e 746 return 0;
747}
748
7a7ff0c6 749static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
bf601689
MH
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
cc6f6dd7 804static int umount_oldrootfs(const char *oldrootfs)
bf601689 805{
2382ecff 806 char path[MAXPATHLEN];
bf601689 807 void *cbparm[2];
9ebb03ad 808 struct lxc_list mountlist, *iterator, *next;
bf601689 809 int ok, still_mounted, last_still_mounted;
9ba8130c 810 int rc;
bf601689
MH
811
812 /* read and parse /proc/mounts in old root fs */
813 lxc_list_init(&mountlist);
814
cc6f6dd7 815 /* oldrootfs is on the top tree directory now */
9ba8130c
SH
816 rc = snprintf(path, sizeof(path), "/%s", oldrootfs);
817 if (rc >= sizeof(path)) {
818 ERROR("rootfs name too long");
819 return -1;
820 }
bf601689 821 cbparm[0] = &mountlist;
bf601689 822
cc6f6dd7 823 cbparm[1] = strdup(path);
bf601689
MH
824 if (!cbparm[1]) {
825 SYSERROR("strdup failed");
826 return -1;
827 }
828
9ba8130c
SH
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 }
cc6f6dd7
DL
834
835 ok = lxc_file_for_each_line(path,
836 setup_rootfs_pivot_root_cb, &cbparm);
bf601689
MH
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
9ebb03ad 848 lxc_list_for_each_safe(iterator, &mountlist, next) {
bf601689 849
c08556c6 850 /* umount normally */
bf601689
MH
851 if (!umount(iterator->elem)) {
852 DEBUG("umounted '%s'", (char *)iterator->elem);
853 lxc_list_del(iterator);
854 continue;
855 }
856
bf601689
MH
857 still_mounted++;
858 }
7df119ee 859
bf601689
MH
860 } while (still_mounted > 0 && still_mounted != last_still_mounted);
861
7df119ee 862
c08556c6
DL
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
7df119ee 877 WARN("failed to unmount '%s'", (char *)iterator->elem);
c08556c6 878 }
bf601689 879
cc6f6dd7
DL
880 return 0;
881}
882
883static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
884{
885 char path[MAXPATHLEN];
886 int remove_pivotdir = 0;
9ba8130c 887 int rc;
cc6f6dd7
DL
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)
30c5d292 896 pivotdir = "lxc_putold";
cc6f6dd7 897
4f9293b1 898 /* compute the full path to pivotdir under rootfs */
9ba8130c
SH
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 }
cc6f6dd7
DL
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");
bf601689
MH
921 return -1;
922 }
cc6f6dd7
DL
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;
bf601689 934
c08556c6
DL
935 /* remove temporary mount point, we don't consider the removing
936 * as fatal */
a91d897a
FW
937 if (remove_pivotdir && rmdir(pivotdir))
938 WARN("can't remove mountpoint '%s': %m", pivotdir);
bf601689 939
bf601689
MH
940 return 0;
941}
942
91c3830e
SH
943/*
944 * Do we want to add options for max size of /dev and a file to
945 * specify which devices to create?
946 */
947static 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/*
975 * Try to run MAKEDEV console in the container. If something fails,
976 * continue anyway as it should not be detrimental to the container.
977 * This makes sure that things like /dev/vcs* exist.
978 * (Pass devpath in to reduce stack usage)
979 */
980static void run_makedev(char *devpath)
981{
982 int curd;
983 int ret;
984
985 curd = open(".", O_RDONLY);
986 if (curd < 0)
987 return;
988 ret = chdir(devpath);
989 if (ret) {
990 close(curd);
991 return;
992 }
993 if (run_buffer("/sbin/MAKEDEV console"))
994 INFO("Error running MAKEDEV console in %s", devpath);
61435768
SH
995 ret = fchdir(curd);
996 if (ret)
997 INFO("Error returning to original directory: expect breakage");
91c3830e
SH
998 close(curd);
999}
1000
c6883f38
SH
1001struct lxc_devs {
1002 char *name;
1003 mode_t mode;
1004 int maj;
1005 int min;
1006};
1007
1008struct lxc_devs lxc_devs[] = {
1009 { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
1010 { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
1011 { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 },
1012 { "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 },
1013 { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 },
1014 { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 },
1015 { "console", S_IFCHR | S_IRUSR | S_IWUSR, 5, 1 },
1016};
1017
c6883f38
SH
1018static int setup_autodev(char *root)
1019{
1020 int ret;
1021 struct lxc_devs *d;
1022 char path[MAXPATHLEN];
1023 int i;
3a32201c 1024 mode_t cmask;
c6883f38 1025
91c3830e
SH
1026 INFO("Creating initial consoles under %s/dev\n", root);
1027
c6883f38 1028 ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
91c3830e
SH
1029 if (ret < 0 || ret >= MAXPATHLEN) {
1030 ERROR("Error calculating container /dev location");
c6883f38 1031 return -1;
91c3830e
SH
1032 } else
1033 run_makedev(path);
1034
1035 INFO("Populating /dev under %s\n", root);
3a32201c 1036 cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
c6883f38
SH
1037 for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
1038 d = &lxc_devs[i];
1039 ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name);
1040 if (ret < 0 || ret >= MAXPATHLEN)
1041 return -1;
1042 ret = mknod(path, d->mode, makedev(d->maj, d->min));
91c3830e 1043 if (ret && errno != EEXIST) {
c6883f38
SH
1044 SYSERROR("Error creating %s\n", d->name);
1045 return -1;
1046 }
1047 }
3a32201c 1048 umask(cmask);
c6883f38
SH
1049
1050 INFO("Populated /dev under %s\n", root);
1051 return 0;
1052}
1053
cc28d0b0
SH
1054/*
1055 * Detect whether / is mounted MS_SHARED. The only way I know of to
1056 * check that is through /proc/self/mountinfo.
1057 * I'm only checking for /. If the container rootfs or mount location
1058 * is MS_SHARED, but not '/', then you're out of luck - figuring that
1059 * out would be too much work to be worth it.
1060 */
1061#define LINELEN 4096
1062int detect_shared_rootfs(void)
1063{
1064 char buf[LINELEN], *p;
1065 FILE *f;
1066 int i;
1067 char *p2;
1068
1069 f = fopen("/proc/self/mountinfo", "r");
1070 if (!f)
1071 return 0;
1072 while ((p = fgets(buf, LINELEN, f))) {
1073 INFO("looking at .%s.", p);
1074 for (p = buf, i=0; p && i < 4; i++)
1075 p = index(p+1, ' ');
1076 if (!p)
1077 continue;
1078 p2 = index(p+1, ' ');
1079 if (!p2)
1080 continue;
1081 *p2 = '\0';
1082 INFO("now p is .%s.", p);
1083 if (strcmp(p+1, "/") == 0) {
1084 // this is '/'. is it shared?
1085 p = index(p2+1, ' ');
1086 if (strstr(p, "shared:"))
1087 return 1;
1088 }
1089 }
1090 fclose(f);
1091 return 0;
1092}
1093
1094/*
1095 * I'll forgive you for asking whether all of this is needed :) The
1096 * answer is yes.
1097 * pivot_root will fail if the new root, the put_old dir, or the parent
1098 * of current->fs->root are MS_SHARED. (parent of current->fs_root may
1099 * or may not be current->fs_root - if we assumed it always was, we could
1100 * just mount --make-rslave /). So,
1101 * 1. mount a tiny tmpfs to be parent of current->fs->root.
1102 * 2. make that MS_SLAVE
1103 * 3. make a 'root' directory under that
1104 * 4. mount --rbind / under the $tinyroot/root.
1105 * 5. make that rslave
1106 * 6. chdir and chroot into $tinyroot/root
1107 * 7. $tinyroot will be unmounted by our parent in start.c
1108 */
1109static int chroot_into_slave(struct lxc_conf *conf)
1110{
1111 char path[MAXPATHLEN];
1112 const char *destpath = conf->rootfs.mount;
1113 int ret;
1114
1115 if (mount(destpath, destpath, NULL, MS_BIND, 0)) {
1116 SYSERROR("failed to mount %s bind", destpath);
1117 return -1;
1118 }
1119 if (mount("", destpath, NULL, MS_SLAVE, 0)) {
1120 SYSERROR("failed to make %s slave", destpath);
1121 return -1;
1122 }
1123 if (mount("none", destpath, "tmpfs", 0, "size=10000")) {
1124 SYSERROR("Failed to mount tmpfs / at %s", destpath);
1125 return -1;
1126 }
1127 ret = snprintf(path, MAXPATHLEN, "%s/root", destpath);
1128 if (ret < 0 || ret >= MAXPATHLEN) {
1129 ERROR("out of memory making root path");
1130 return -1;
1131 }
1132 if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1133 SYSERROR("Failed to create /dev/pts in container");
1134 return -1;
1135 }
1136 if (mount("/", path, NULL, MS_BIND|MS_REC, 0)) {
1137 SYSERROR("Failed to rbind mount / to %s", path);
1138 return -1;
1139 }
1140 if (mount("", destpath, NULL, MS_SLAVE|MS_REC, 0)) {
1141 SYSERROR("Failed to make tmp-/ at %s rslave", path);
1142 return -1;
1143 }
1144 if (chdir(path)) {
1145 SYSERROR("Failed to chdir into tmp-/");
1146 return -1;
1147 }
1148 if (chroot(path)) {
1149 SYSERROR("Failed to chroot into tmp-/");
1150 return -1;
1151 }
1152 INFO("Chrooted into tmp-/ at %s\n", path);
1153 return 0;
1154}
1155
1156static int setup_rootfs(struct lxc_conf *conf)
0ad19a3f 1157{
cc28d0b0
SH
1158 const struct lxc_rootfs *rootfs = &conf->rootfs;
1159
33fcb7a0 1160 if (!rootfs->path)
c69bd12f 1161 return 0;
0ad19a3f 1162
12297168 1163 if (access(rootfs->mount, F_OK)) {
b1789442 1164 SYSERROR("failed to access to '%s', check it is present",
12297168 1165 rootfs->mount);
b1789442
DL
1166 return -1;
1167 }
1168
cc28d0b0
SH
1169 if (detect_shared_rootfs()) {
1170 if (chroot_into_slave(conf)) {
1171 ERROR("Failed to chroot into slave /");
1172 return -1;
1173 }
1174 }
1175
2656d231 1176 if (mount_rootfs(rootfs->path, rootfs->mount)) {
a6afdde9 1177 ERROR("failed to mount rootfs");
c3f0a28c 1178 return -1;
1179 }
0ad19a3f 1180
12297168 1181 DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
c69bd12f 1182
ac778708
DL
1183 return 0;
1184}
1185
1186int setup_pivot_root(const struct lxc_rootfs *rootfs)
1187{
ac778708
DL
1188 if (!rootfs->path)
1189 return 0;
1190
12297168 1191 if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
cc6f6dd7 1192 ERROR("failed to setup pivot root");
25368b52 1193 return -1;
c69bd12f
DL
1194 }
1195
25368b52 1196 return 0;
0ad19a3f 1197}
1198
d852c78c 1199static int setup_pts(int pts)
3c26f34e 1200{
77890c6d
SW
1201 char target[PATH_MAX];
1202
d852c78c
DL
1203 if (!pts)
1204 return 0;
3c26f34e 1205
1206 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
36eb9bde 1207 SYSERROR("failed to umount 'dev/pts'");
3c26f34e 1208 return -1;
1209 }
1210
a6afdde9
DL
1211 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
1212 "newinstance,ptmxmode=0666")) {
36eb9bde 1213 SYSERROR("failed to mount a new instance of '/dev/pts'");
3c26f34e 1214 return -1;
1215 }
1216
3c26f34e 1217 if (access("/dev/ptmx", F_OK)) {
1218 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
1219 goto out;
36eb9bde 1220 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 1221 return -1;
1222 }
1223
77890c6d
SW
1224 if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
1225 goto out;
1226
3c26f34e 1227 /* fallback here, /dev/pts/ptmx exists just mount bind */
1228 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
36eb9bde 1229 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 1230 return -1;
1231 }
cd54d859
DL
1232
1233 INFO("created new pts instance");
d852c78c 1234
3c26f34e 1235out:
1236 return 0;
1237}
1238
cccc74b5
DL
1239static int setup_personality(int persona)
1240{
6ff05e18 1241 #if HAVE_SYS_PERSONALITY_H
cccc74b5
DL
1242 if (persona == -1)
1243 return 0;
1244
1245 if (personality(persona) < 0) {
1246 SYSERROR("failed to set personality to '0x%x'", persona);
1247 return -1;
1248 }
1249
1250 INFO("set personality to '0x%x'", persona);
6ff05e18 1251 #endif
cccc74b5
DL
1252
1253 return 0;
1254}
1255
7c6ef2a2 1256static int setup_dev_console(const struct lxc_rootfs *rootfs,
33fcb7a0 1257 const struct lxc_console *console)
6e590161 1258{
63376d7d
DL
1259 char path[MAXPATHLEN];
1260 struct stat s;
7c6ef2a2 1261 int ret;
52e35957 1262
7c6ef2a2
SH
1263 ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1264 if (ret >= sizeof(path)) {
1265 ERROR("console path too long\n");
1266 return -1;
1267 }
52e35957 1268
63376d7d 1269 if (access(path, F_OK)) {
466978b0 1270 WARN("rootfs specified but no console found at '%s'", path);
63376d7d 1271 return 0;
52e35957
DL
1272 }
1273
f78a1f32 1274 if (console->peer == -1) {
63376d7d 1275 INFO("no console output required");
f78a1f32
DL
1276 return 0;
1277 }
ed502555 1278
63376d7d
DL
1279 if (stat(path, &s)) {
1280 SYSERROR("failed to stat '%s'", path);
1281 return -1;
1282 }
1283
1284 if (chmod(console->name, s.st_mode)) {
1285 SYSERROR("failed to set mode '0%o' to '%s'",
1286 s.st_mode, console->name);
1287 return -1;
1288 }
13954cce 1289
63376d7d
DL
1290 if (mount(console->name, path, "none", MS_BIND, 0)) {
1291 ERROR("failed to mount '%s' on '%s'", console->name, path);
6e590161 1292 return -1;
1293 }
1294
63376d7d 1295 INFO("console has been setup");
7c6ef2a2
SH
1296 return 0;
1297}
1298
1299static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
1300 const struct lxc_console *console,
1301 char *ttydir)
1302{
1303 char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
1304 int ret;
1305
1306 /* create rootfs/dev/<ttydir> directory */
1307 ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
1308 ttydir);
1309 if (ret >= sizeof(path))
1310 return -1;
1311 ret = mkdir(path, 0755);
1312 if (ret && errno != EEXIST) {
1313 SYSERROR("failed with errno %d to create %s\n", errno, path);
1314 return -1;
1315 }
1316 INFO("created %s\n", path);
1317
1318 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
1319 rootfs->mount, ttydir);
1320 if (ret >= sizeof(lxcpath)) {
1321 ERROR("console path too long\n");
1322 return -1;
1323 }
1324
1325 snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
1326 ret = unlink(path);
1327 if (ret && errno != ENOENT) {
1328 SYSERROR("error unlinking %s\n", path);
1329 return -1;
1330 }
1331
1332 ret = creat(lxcpath, 0660);
1333 if (ret==-1 && errno != EEXIST) {
1334 SYSERROR("error %d creating %s\n", errno, lxcpath);
1335 return -1;
1336 }
1337 close(ret);
1338
1339 if (console->peer == -1) {
1340 INFO("no console output required");
1341 return 0;
1342 }
1343
1344 if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
1345 ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
1346 return -1;
1347 }
1348
1349 /* create symlink from rootfs/dev/console to 'lxc/console' */
9ba8130c
SH
1350 ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
1351 if (ret >= sizeof(lxcpath)) {
1352 ERROR("lxc/console path too long");
1353 return -1;
1354 }
7c6ef2a2
SH
1355 ret = symlink(lxcpath, path);
1356 if (ret) {
1357 SYSERROR("failed to create symlink for console");
1358 return -1;
1359 }
1360
1361 INFO("console has been setup on %s", lxcpath);
cd54d859 1362
6e590161 1363 return 0;
1364}
1365
7c6ef2a2
SH
1366static int setup_console(const struct lxc_rootfs *rootfs,
1367 const struct lxc_console *console,
1368 char *ttydir)
1369{
1370 /* We don't have a rootfs, /dev/console will be shared */
1371 if (!rootfs->path)
1372 return 0;
1373 if (!ttydir)
1374 return setup_dev_console(rootfs, console);
1375
1376 return setup_ttydir_console(rootfs, console, ttydir);
1377}
1378
1bd051a6
SH
1379static int setup_kmsg(const struct lxc_rootfs *rootfs,
1380 const struct lxc_console *console)
1381{
1382 char kpath[MAXPATHLEN];
1383 int ret;
1384
222fea5a
DE
1385 if (!rootfs->path)
1386 return 0;
1bd051a6
SH
1387 ret = snprintf(kpath, sizeof(kpath), "%s/dev/kmsg", rootfs->mount);
1388 if (ret < 0 || ret >= sizeof(kpath))
1389 return -1;
1390
1391 ret = unlink(kpath);
1392 if (ret && errno != ENOENT) {
1393 SYSERROR("error unlinking %s\n", kpath);
1394 return -1;
1395 }
1396
1397 ret = symlink("console", kpath);
1398 if (ret) {
1399 SYSERROR("failed to create symlink for kmsg");
1400 return -1;
1401 }
1402
1403 return 0;
1404}
1405
cc28d0b0 1406int setup_cgroup(const char *name, struct lxc_list *cgroups)
576f946d 1407{
102a5303
DL
1408 struct lxc_list *iterator;
1409 struct lxc_cgroup *cg;
88329c69 1410 int ret = -1;
6f4a3756 1411
102a5303
DL
1412 if (lxc_list_empty(cgroups))
1413 return 0;
6f4a3756 1414
102a5303 1415 lxc_list_for_each(iterator, cgroups) {
13954cce 1416
102a5303 1417 cg = iterator->elem;
6f4a3756 1418
102a5303 1419 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
88329c69 1420 goto out;
6f4a3756 1421
102a5303 1422 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
6f4a3756 1423 }
13954cce 1424
88329c69 1425 ret = 0;
cd54d859 1426 INFO("cgroup has been setup");
88329c69
MN
1427out:
1428 return ret;
576f946d 1429}
1430
998ac676
RT
1431static void parse_mntopt(char *opt, unsigned long *flags, char **data)
1432{
1433 struct mount_opt *mo;
1434
1435 /* If opt is found in mount_opt, set or clear flags.
1436 * Otherwise append it to data. */
1437
1438 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
1439 if (!strncmp(opt, mo->name, strlen(mo->name))) {
1440 if (mo->clear)
1441 *flags &= ~mo->flag;
1442 else
1443 *flags |= mo->flag;
1444 return;
1445 }
1446 }
1447
1448 if (strlen(*data))
1449 strcat(*data, ",");
1450 strcat(*data, opt);
1451}
1452
911324ef 1453static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
998ac676
RT
1454 char **mntdata)
1455{
1456 char *s, *data;
1457 char *p, *saveptr = NULL;
1458
911324ef 1459 *mntdata = NULL;
91656ce5 1460 *mntflags = 0L;
911324ef
DL
1461
1462 if (!mntopts)
998ac676
RT
1463 return 0;
1464
911324ef 1465 s = strdup(mntopts);
998ac676 1466 if (!s) {
36eb9bde 1467 SYSERROR("failed to allocate memory");
998ac676
RT
1468 return -1;
1469 }
1470
1471 data = malloc(strlen(s) + 1);
1472 if (!data) {
36eb9bde 1473 SYSERROR("failed to allocate memory");
998ac676
RT
1474 free(s);
1475 return -1;
1476 }
1477 *data = 0;
1478
1479 for (p = strtok_r(s, ",", &saveptr); p != NULL;
1480 p = strtok_r(NULL, ",", &saveptr))
1481 parse_mntopt(p, mntflags, &data);
1482
1483 if (*data)
1484 *mntdata = data;
1485 else
1486 free(data);
1487 free(s);
1488
1489 return 0;
1490}
1491
911324ef
DL
1492static int mount_entry(const char *fsname, const char *target,
1493 const char *fstype, unsigned long mountflags,
1494 const char *data)
1495{
1496 if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
1497 SYSERROR("failed to mount '%s' on '%s'", fsname, target);
1498 return -1;
1499 }
1500
1501 if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
1502
1503 DEBUG("remounting %s on %s to respect bind or remount options",
1504 fsname, target);
1505
1506 if (mount(fsname, target, fstype,
1507 mountflags | MS_REMOUNT, data)) {
1508 SYSERROR("failed to mount '%s' on '%s'",
1509 fsname, target);
1510 return -1;
1511 }
1512 }
1513
1514 DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
1515
1516 return 0;
1517}
1518
1519static inline int mount_entry_on_systemfs(struct mntent *mntent)
0ad19a3f 1520{
998ac676
RT
1521 unsigned long mntflags;
1522 char *mntdata;
911324ef
DL
1523 int ret;
1524
1525 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1526 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1527 return -1;
1528 }
1529
1530 ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
1531 mntent->mnt_type, mntflags, mntdata);
1532
1533 free(mntdata);
1534
1535 return ret;
1536}
1537
1538static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
80a881b2
SH
1539 const struct lxc_rootfs *rootfs,
1540 const char *lxc_name)
911324ef 1541{
013bd428 1542 char *aux;
59760f5d 1543 char path[MAXPATHLEN];
911324ef
DL
1544 unsigned long mntflags;
1545 char *mntdata;
80a881b2 1546 int r, ret = 0, offset;
0ad19a3f 1547
911324ef
DL
1548 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1549 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1550 return -1;
1551 }
1bc60a65 1552
80a881b2 1553 /* if rootfs->path is a blockdev path, allow container fstab to
e29bf450
DE
1554 * use $LXCPATH/CN/rootfs as the target prefix */
1555 r = snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", lxc_name);
80a881b2
SH
1556 if (r < 0 || r >= MAXPATHLEN)
1557 goto skipvarlib;
1558
1559 aux = strstr(mntent->mnt_dir, path);
1560 if (aux) {
1561 offset = strlen(path);
1562 goto skipabs;
1563 }
1564
1565skipvarlib:
013bd428
DL
1566 aux = strstr(mntent->mnt_dir, rootfs->path);
1567 if (!aux) {
1568 WARN("ignoring mount point '%s'", mntent->mnt_dir);
1569 goto out;
1570 }
80a881b2
SH
1571 offset = strlen(rootfs->path);
1572
1573skipabs:
013bd428 1574
9ba8130c 1575 r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
80a881b2
SH
1576 aux + offset);
1577 if (r < 0 || r >= MAXPATHLEN) {
1578 WARN("pathnme too long for '%s'", mntent->mnt_dir);
1579 ret = -1;
1580 goto out;
1581 }
1582
d330fe7b 1583
013bd428 1584 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
911324ef 1585 mntflags, mntdata);
0ad19a3f 1586
013bd428 1587out:
911324ef
DL
1588 free(mntdata);
1589 return ret;
1590}
d330fe7b 1591
911324ef
DL
1592static int mount_entry_on_relative_rootfs(struct mntent *mntent,
1593 const char *rootfs)
1594{
1595 char path[MAXPATHLEN];
1596 unsigned long mntflags;
1597 char *mntdata;
1598 int ret;
d330fe7b 1599
911324ef
DL
1600 if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1601 ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1602 return -1;
1603 }
d330fe7b 1604
911324ef 1605 /* relative to root mount point */
9ba8130c
SH
1606 ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
1607 if (ret >= sizeof(path)) {
1608 ERROR("path name too long");
1609 return -1;
1610 }
911324ef
DL
1611
1612 ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1613 mntflags, mntdata);
1614
1615 free(mntdata);
998ac676 1616
911324ef
DL
1617 return ret;
1618}
1619
80a881b2
SH
1620static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
1621 const char *lxc_name)
911324ef
DL
1622{
1623 struct mntent *mntent;
1624 int ret = -1;
e76b8764 1625
911324ef 1626 while ((mntent = getmntent(file))) {
e76b8764 1627
911324ef
DL
1628 if (!rootfs->path) {
1629 if (mount_entry_on_systemfs(mntent))
e76b8764 1630 goto out;
911324ef 1631 continue;
e76b8764
CDC
1632 }
1633
911324ef
DL
1634 /* We have a separate root, mounts are relative to it */
1635 if (mntent->mnt_dir[0] != '/') {
1636 if (mount_entry_on_relative_rootfs(mntent,
1637 rootfs->mount))
1638 goto out;
1639 continue;
1640 }
cd54d859 1641
80a881b2 1642 if (mount_entry_on_absolute_rootfs(mntent, rootfs, lxc_name))
911324ef 1643 goto out;
0ad19a3f 1644 }
cd54d859 1645
0ad19a3f 1646 ret = 0;
cd54d859
DL
1647
1648 INFO("mount points have been setup");
0ad19a3f 1649out:
e7938e9e
MN
1650 return ret;
1651}
1652
80a881b2
SH
1653static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
1654 const char *lxc_name)
e7938e9e
MN
1655{
1656 FILE *file;
1657 int ret;
1658
1659 if (!fstab)
1660 return 0;
1661
1662 file = setmntent(fstab, "r");
1663 if (!file) {
1664 SYSERROR("failed to use '%s'", fstab);
1665 return -1;
1666 }
1667
80a881b2 1668 ret = mount_file_entries(rootfs, file, lxc_name);
e7938e9e 1669
0ad19a3f 1670 endmntent(file);
1671 return ret;
1672}
1673
80a881b2
SH
1674static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
1675 const char *lxc_name)
e7938e9e
MN
1676{
1677 FILE *file;
1678 struct lxc_list *iterator;
1679 char *mount_entry;
1680 int ret;
1681
1682 file = tmpfile();
1683 if (!file) {
1684 ERROR("tmpfile error: %m");
1685 return -1;
1686 }
1687
1688 lxc_list_for_each(iterator, mount) {
1689 mount_entry = iterator->elem;
1d6b1976 1690 fprintf(file, "%s\n", mount_entry);
e7938e9e
MN
1691 }
1692
1693 rewind(file);
1694
80a881b2 1695 ret = mount_file_entries(rootfs, file, lxc_name);
e7938e9e
MN
1696
1697 fclose(file);
1698 return ret;
1699}
1700
81810dd1
DL
1701static int setup_caps(struct lxc_list *caps)
1702{
1703 struct lxc_list *iterator;
1704 char *drop_entry;
d55bc1ad 1705 char *ptr;
81810dd1
DL
1706 int i, capid;
1707
1708 lxc_list_for_each(iterator, caps) {
1709
1710 drop_entry = iterator->elem;
1711
1712 capid = -1;
1713
1714 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
1715
1716 if (strcmp(drop_entry, caps_opt[i].name))
1717 continue;
1718
1719 capid = caps_opt[i].value;
1720 break;
1721 }
1722
d55bc1ad
CS
1723 if (capid < 0) {
1724 /* try to see if it's numeric, so the user may specify
1725 * capabilities that the running kernel knows about but
1726 * we don't */
1727 capid = strtol(drop_entry, &ptr, 10);
1728 if (!ptr || *ptr != '\0' ||
1729 capid == LONG_MIN || capid == LONG_MAX)
1730 /* not a valid number */
1731 capid = -1;
1732 else if (capid > lxc_caps_last_cap())
1733 /* we have a number but it's not a valid
1734 * capability */
1735 capid = -1;
1736 }
1737
81810dd1 1738 if (capid < 0) {
1e11be34
DL
1739 ERROR("unknown capability %s", drop_entry);
1740 return -1;
81810dd1
DL
1741 }
1742
1743 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
1744
1745 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
1746 SYSERROR("failed to remove %s capability", drop_entry);
1747 return -1;
1748 }
1749
1750 }
1751
1752 DEBUG("capabilities has been setup");
1753
1754 return 0;
1755}
1756
0ad19a3f 1757static int setup_hw_addr(char *hwaddr, const char *ifname)
1758{
1759 struct sockaddr sockaddr;
1760 struct ifreq ifr;
1761 int ret, fd;
1762
3cfc0f3a
MN
1763 ret = lxc_convert_mac(hwaddr, &sockaddr);
1764 if (ret) {
1765 ERROR("mac address '%s' conversion failed : %s",
1766 hwaddr, strerror(-ret));
0ad19a3f 1767 return -1;
1768 }
1769
1770 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1771 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1772
1773 fd = socket(AF_INET, SOCK_DGRAM, 0);
1774 if (fd < 0) {
3ab87b66 1775 ERROR("socket failure : %s", strerror(errno));
0ad19a3f 1776 return -1;
1777 }
1778
1779 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1780 close(fd);
1781 if (ret)
3ab87b66 1782 ERROR("ioctl failure : %s", strerror(errno));
0ad19a3f 1783
cd54d859
DL
1784 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1785
0ad19a3f 1786 return ret;
1787}
1788
82d5ae15 1789static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1790{
82d5ae15
DL
1791 struct lxc_list *iterator;
1792 struct lxc_inetdev *inetdev;
3cfc0f3a 1793 int err;
0ad19a3f 1794
82d5ae15
DL
1795 lxc_list_for_each(iterator, ip) {
1796
1797 inetdev = iterator->elem;
1798
0093bb8c
DL
1799 err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
1800 &inetdev->bcast, inetdev->prefix);
3cfc0f3a
MN
1801 if (err) {
1802 ERROR("failed to setup_ipv4_addr ifindex %d : %s",
1803 ifindex, strerror(-err));
82d5ae15
DL
1804 return -1;
1805 }
1806 }
1807
1808 return 0;
0ad19a3f 1809}
1810
82d5ae15 1811static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 1812{
82d5ae15 1813 struct lxc_list *iterator;
7fa9074f 1814 struct lxc_inet6dev *inet6dev;
3cfc0f3a 1815 int err;
0ad19a3f 1816
82d5ae15
DL
1817 lxc_list_for_each(iterator, ip) {
1818
1819 inet6dev = iterator->elem;
1820
b3df193c 1821 err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
0093bb8c
DL
1822 &inet6dev->mcast, &inet6dev->acast,
1823 inet6dev->prefix);
3cfc0f3a
MN
1824 if (err) {
1825 ERROR("failed to setup_ipv6_addr ifindex %d : %s",
1826 ifindex, strerror(-err));
82d5ae15 1827 return -1;
3cfc0f3a 1828 }
82d5ae15
DL
1829 }
1830
1831 return 0;
0ad19a3f 1832}
1833
82d5ae15 1834static int setup_netdev(struct lxc_netdev *netdev)
0ad19a3f 1835{
0ad19a3f 1836 char ifname[IFNAMSIZ];
0ad19a3f 1837 char *current_ifname = ifname;
3cfc0f3a 1838 int err;
0ad19a3f 1839
82d5ae15
DL
1840 /* empty network namespace */
1841 if (!netdev->ifindex) {
b0efbac4 1842 if (netdev->flags & IFF_UP) {
d472214b 1843 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1844 if (err) {
1845 ERROR("failed to set the loopback up : %s",
1846 strerror(-err));
82d5ae15
DL
1847 return -1;
1848 }
82d5ae15 1849 }
7b57e8b6 1850 return 0;
0ad19a3f 1851 }
13954cce 1852
82d5ae15
DL
1853 /* retrieve the name of the interface */
1854 if (!if_indextoname(netdev->ifindex, current_ifname)) {
36eb9bde 1855 ERROR("no interface corresponding to index '%d'",
82d5ae15 1856 netdev->ifindex);
0ad19a3f 1857 return -1;
1858 }
13954cce 1859
018ef520 1860 /* default: let the system to choose one interface name */
9d083402 1861 if (!netdev->name)
fb6d9b2f
DL
1862 netdev->name = netdev->type == LXC_NET_PHYS ?
1863 netdev->link : "eth%d";
018ef520 1864
82d5ae15 1865 /* rename the interface name */
b84f58b9 1866 err = lxc_netdev_rename_by_name(ifname, netdev->name);
3cfc0f3a
MN
1867 if (err) {
1868 ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
1869 strerror(-err));
018ef520
DL
1870 return -1;
1871 }
1872
1873 /* Re-read the name of the interface because its name has changed
1874 * and would be automatically allocated by the system
1875 */
82d5ae15 1876 if (!if_indextoname(netdev->ifindex, current_ifname)) {
018ef520 1877 ERROR("no interface corresponding to index '%d'",
82d5ae15 1878 netdev->ifindex);
018ef520 1879 return -1;
0ad19a3f 1880 }
1881
82d5ae15
DL
1882 /* set a mac address */
1883 if (netdev->hwaddr) {
1884 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
36eb9bde 1885 ERROR("failed to setup hw address for '%s'",
82d5ae15 1886 current_ifname);
0ad19a3f 1887 return -1;
1888 }
1889 }
1890
82d5ae15
DL
1891 /* setup ipv4 addresses on the interface */
1892 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
36eb9bde 1893 ERROR("failed to setup ip addresses for '%s'",
0ad19a3f 1894 ifname);
1895 return -1;
1896 }
1897
82d5ae15
DL
1898 /* setup ipv6 addresses on the interface */
1899 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
36eb9bde 1900 ERROR("failed to setup ipv6 addresses for '%s'",
0ad19a3f 1901 ifname);
1902 return -1;
1903 }
1904
82d5ae15 1905 /* set the network device up */
b0efbac4 1906 if (netdev->flags & IFF_UP) {
3cfc0f3a
MN
1907 int err;
1908
d472214b 1909 err = lxc_netdev_up(current_ifname);
3cfc0f3a
MN
1910 if (err) {
1911 ERROR("failed to set '%s' up : %s", current_ifname,
1912 strerror(-err));
0ad19a3f 1913 return -1;
1914 }
1915
1916 /* the network is up, make the loopback up too */
d472214b 1917 err = lxc_netdev_up("lo");
3cfc0f3a
MN
1918 if (err) {
1919 ERROR("failed to set the loopback up : %s",
1920 strerror(-err));
0ad19a3f 1921 return -1;
1922 }
1923 }
1924
f8fee0e2
MK
1925 /* We can only set up the default routes after bringing
1926 * up the interface, sine bringing up the interface adds
1927 * the link-local routes and we can't add a default
1928 * route if the gateway is not reachable. */
1929
1930 /* setup ipv4 gateway on the interface */
1931 if (netdev->ipv4_gateway) {
1932 if (!(netdev->flags & IFF_UP)) {
1933 ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname);
1934 return -1;
1935 }
1936
1937 if (lxc_list_empty(&netdev->ipv4)) {
1938 ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname);
1939 return -1;
1940 }
1941
1942 err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
1943 if (err) {
1944 ERROR("failed to setup ipv4 gateway for '%s': %s",
1945 ifname, strerror(-err));
19a26f82
MK
1946 if (netdev->ipv4_gateway_auto) {
1947 char buf[INET_ADDRSTRLEN];
1948 inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
1949 ERROR("tried to set autodetected ipv4 gateway '%s'", buf);
1950 }
f8fee0e2
MK
1951 return -1;
1952 }
1953 }
1954
1955 /* setup ipv6 gateway on the interface */
1956 if (netdev->ipv6_gateway) {
1957 if (!(netdev->flags & IFF_UP)) {
1958 ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname);
1959 return -1;
1960 }
1961
1962 if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
1963 ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname);
1964 return -1;
1965 }
1966
1967 err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
1968 if (err) {
1969 ERROR("failed to setup ipv6 gateway for '%s': %s",
1970 ifname, strerror(-err));
19a26f82
MK
1971 if (netdev->ipv6_gateway_auto) {
1972 char buf[INET6_ADDRSTRLEN];
72d0e1cb 1973 inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
19a26f82
MK
1974 ERROR("tried to set autodetected ipv6 gateway '%s'", buf);
1975 }
f8fee0e2
MK
1976 return -1;
1977 }
1978 }
1979
cd54d859
DL
1980 DEBUG("'%s' has been setup", current_ifname);
1981
0ad19a3f 1982 return 0;
1983}
1984
5f4535a3 1985static int setup_network(struct lxc_list *network)
0ad19a3f 1986{
82d5ae15 1987 struct lxc_list *iterator;
82d5ae15 1988 struct lxc_netdev *netdev;
0ad19a3f 1989
5f4535a3 1990 lxc_list_for_each(iterator, network) {
cd54d859 1991
5f4535a3 1992 netdev = iterator->elem;
82d5ae15
DL
1993
1994 if (setup_netdev(netdev)) {
1995 ERROR("failed to setup netdev");
1996 return -1;
1997 }
1998 }
cd54d859 1999
5f4535a3
DL
2000 if (!lxc_list_empty(network))
2001 INFO("network has been setup");
cd54d859
DL
2002
2003 return 0;
0ad19a3f 2004}
2005
7b35f3d6
SH
2006void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf)
2007{
2008 int i;
2009
2010 INFO("running to reset %d nic names", conf->num_savednics);
2011 for (i=0; i<conf->num_savednics; i++) {
2012 struct saved_nic *s = &conf->saved_nics[i];
2013 INFO("resetting nic %d to %s\n", s->ifindex, s->orig_name);
2014 lxc_netdev_rename_by_index(s->ifindex, s->orig_name);
2015 free(s->orig_name);
2016 }
2017 conf->num_savednics = 0;
2018 free(conf->saved_nics);
2019}
2020
49684c0b
CS
2021static int setup_private_host_hw_addr(char *veth1)
2022{
2023 struct ifreq ifr;
2024 int err;
2025 int sockfd;
2026
2027 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2028 if (sockfd < 0)
2029 return -errno;
2030
2031 snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
2032 err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
2033 if (err < 0) {
2034 close(sockfd);
2035 return -errno;
2036 }
2037
2038 ifr.ifr_hwaddr.sa_data[0] = 0xfe;
2039 err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
2040 close(sockfd);
2041 if (err < 0)
2042 return -errno;
2043
7ad84da7
DL
2044 DEBUG("mac address of host interface '%s' changed to private "
2045 "%02x:%02x:%02x:%02x:%02x:%02x", veth1,
2046 ifr.ifr_hwaddr.sa_data[0] & 0xff,
2047 ifr.ifr_hwaddr.sa_data[1] & 0xff,
2048 ifr.ifr_hwaddr.sa_data[2] & 0xff,
2049 ifr.ifr_hwaddr.sa_data[3] & 0xff,
2050 ifr.ifr_hwaddr.sa_data[4] & 0xff,
2051 ifr.ifr_hwaddr.sa_data[5] & 0xff);
49684c0b
CS
2052
2053 return 0;
2054}
2055
ae9242c8
SH
2056static char *default_rootfs_mount = LXCROOTFSMOUNT;
2057
7b379ab3 2058struct lxc_conf *lxc_conf_init(void)
089cd8b8 2059{
7b379ab3 2060 struct lxc_conf *new;
26ddeedd 2061 int i;
7b379ab3
MN
2062
2063 new = malloc(sizeof(*new));
2064 if (!new) {
2065 ERROR("lxc_conf_init : %m");
2066 return NULL;
2067 }
2068 memset(new, 0, sizeof(*new));
2069
cccc74b5 2070 new->personality = -1;
596a818d
DE
2071 new->console.log_path = NULL;
2072 new->console.log_fd = -1;
28a4b0e5 2073 new->console.path = NULL;
63376d7d
DL
2074 new->console.peer = -1;
2075 new->console.master = -1;
2076 new->console.slave = -1;
2077 new->console.name[0] = '\0';
d2e30e99 2078 new->maincmd_fd = -1;
ae9242c8 2079 new->rootfs.mount = default_rootfs_mount;
7b379ab3
MN
2080 lxc_list_init(&new->cgroup);
2081 lxc_list_init(&new->network);
2082 lxc_list_init(&new->mount_list);
81810dd1 2083 lxc_list_init(&new->caps);
26ddeedd
SH
2084 for (i=0; i<NUM_LXC_HOOKS; i++)
2085 lxc_list_init(&new->hooks[i]);
e075f5d9
SH
2086#if HAVE_APPARMOR
2087 new->aa_profile = NULL;
2088#endif
2089#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2090 new->lsm_umount_proc = 0;
2091#endif
7b379ab3
MN
2092
2093 return new;
089cd8b8
DL
2094}
2095
e3b4c4c4 2096static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2097{
8634bc19 2098 char veth1buf[IFNAMSIZ], *veth1;
0e391e57 2099 char veth2buf[IFNAMSIZ], *veth2;
3cfc0f3a 2100 int err;
13954cce 2101
e892973e
DL
2102 if (netdev->priv.veth_attr.pair)
2103 veth1 = netdev->priv.veth_attr.pair;
8634bc19 2104 else {
9ba8130c
SH
2105 err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
2106 if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
2107 ERROR("veth1 name too long");
2108 return -1;
2109 }
0e391e57 2110 veth1 = mktemp(veth1buf);
74a2b586
JK
2111 /* store away for deconf */
2112 memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
8634bc19 2113 }
82d5ae15 2114
0e391e57
DL
2115 snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
2116 veth2 = mktemp(veth2buf);
82d5ae15
DL
2117
2118 if (!strlen(veth1) || !strlen(veth2)) {
2119 ERROR("failed to allocate a temporary name");
2120 return -1;
0ad19a3f 2121 }
2122
3cfc0f3a
MN
2123 err = lxc_veth_create(veth1, veth2);
2124 if (err) {
2125 ERROR("failed to create %s-%s : %s", veth1, veth2,
2126 strerror(-err));
6ab9ab6d 2127 return -1;
0ad19a3f 2128 }
13954cce 2129
49684c0b
CS
2130 /* changing the high byte of the mac address to 0xfe, the bridge interface
2131 * will always keep the host's mac address and not take the mac address
2132 * of a container */
2133 err = setup_private_host_hw_addr(veth1);
2134 if (err) {
2135 ERROR("failed to change mac address of host interface '%s' : %s",
2136 veth1, strerror(-err));
2137 goto out_delete;
2138 }
2139
82d5ae15 2140 if (netdev->mtu) {
d472214b 2141 err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
3cfc0f3a 2142 if (!err)
d472214b 2143 err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
3cfc0f3a
MN
2144 if (err) {
2145 ERROR("failed to set mtu '%s' for %s-%s : %s",
2146 netdev->mtu, veth1, veth2, strerror(-err));
eb14c10a 2147 goto out_delete;
75d09f83
DL
2148 }
2149 }
2150
3cfc0f3a
MN
2151 if (netdev->link) {
2152 err = lxc_bridge_attach(netdev->link, veth1);
2153 if (err) {
2154 ERROR("failed to attach '%s' to the bridge '%s' : %s",
2155 veth1, netdev->link, strerror(-err));
2156 goto out_delete;
2157 }
eb14c10a
DL
2158 }
2159
82d5ae15
DL
2160 netdev->ifindex = if_nametoindex(veth2);
2161 if (!netdev->ifindex) {
36eb9bde 2162 ERROR("failed to retrieve the index for %s", veth2);
eb14c10a
DL
2163 goto out_delete;
2164 }
2165
d472214b 2166 err = lxc_netdev_up(veth1);
6e35af2e
DL
2167 if (err) {
2168 ERROR("failed to set %s up : %s", veth1, strerror(-err));
2169 goto out_delete;
0ad19a3f 2170 }
2171
e3b4c4c4 2172 if (netdev->upscript) {
751d9dcd
DL
2173 err = run_script(handler->name, "net", netdev->upscript, "up",
2174 "veth", veth1, (char*) NULL);
2175 if (err)
e3b4c4c4 2176 goto out_delete;
e3b4c4c4
ST
2177 }
2178
82d5ae15
DL
2179 DEBUG("instanciated veth '%s/%s', index is '%d'",
2180 veth1, veth2, netdev->ifindex);
2181
6ab9ab6d 2182 return 0;
eb14c10a
DL
2183
2184out_delete:
b84f58b9 2185 lxc_netdev_delete_by_name(veth1);
6ab9ab6d 2186 return -1;
13954cce 2187}
d957ae2d 2188
74a2b586
JK
2189static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
2190{
2191 char *veth1;
2192 int err;
2193
2194 if (netdev->priv.veth_attr.pair)
2195 veth1 = netdev->priv.veth_attr.pair;
2196 else
2197 veth1 = netdev->priv.veth_attr.veth1;
2198
2199 if (netdev->downscript) {
2200 err = run_script(handler->name, "net", netdev->downscript,
2201 "down", "veth", veth1, (char*) NULL);
2202 if (err)
2203 return -1;
2204 }
2205 return 0;
2206}
2207
e3b4c4c4 2208static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2209{
0e391e57 2210 char peerbuf[IFNAMSIZ], *peer;
3cfc0f3a 2211 int err;
d957ae2d
MT
2212
2213 if (!netdev->link) {
2214 ERROR("no link specified for macvlan netdev");
2215 return -1;
2216 }
13954cce 2217
9ba8130c
SH
2218 err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
2219 if (err >= sizeof(peerbuf))
2220 return -1;
82d5ae15 2221
0e391e57 2222 peer = mktemp(peerbuf);
82d5ae15
DL
2223 if (!strlen(peer)) {
2224 ERROR("failed to make a temporary name");
2225 return -1;
0ad19a3f 2226 }
2227
3cfc0f3a
MN
2228 err = lxc_macvlan_create(netdev->link, peer,
2229 netdev->priv.macvlan_attr.mode);
2230 if (err) {
2231 ERROR("failed to create macvlan interface '%s' on '%s' : %s",
2232 peer, netdev->link, strerror(-err));
d957ae2d 2233 return -1;
0ad19a3f 2234 }
2235
82d5ae15
DL
2236 netdev->ifindex = if_nametoindex(peer);
2237 if (!netdev->ifindex) {
36eb9bde 2238 ERROR("failed to retrieve the index for %s", peer);
b84f58b9 2239 lxc_netdev_delete_by_name(peer);
d957ae2d 2240 return -1;
22ebac19 2241 }
2242
e3b4c4c4 2243 if (netdev->upscript) {
751d9dcd
DL
2244 err = run_script(handler->name, "net", netdev->upscript, "up",
2245 "macvlan", netdev->link, (char*) NULL);
2246 if (err)
e3b4c4c4 2247 return -1;
e3b4c4c4
ST
2248 }
2249
e892973e
DL
2250 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
2251 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
0ad19a3f 2252
d957ae2d 2253 return 0;
0ad19a3f 2254}
2255
74a2b586
JK
2256static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2257{
2258 int err;
2259
2260 if (netdev->downscript) {
2261 err = run_script(handler->name, "net", netdev->downscript,
2262 "down", "macvlan", netdev->link,
2263 (char*) NULL);
2264 if (err)
2265 return -1;
2266 }
2267 return 0;
2268}
2269
26c39028 2270/* XXX: merge with instanciate_macvlan */
e3b4c4c4 2271static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
26c39028
JHS
2272{
2273 char peer[IFNAMSIZ];
3cfc0f3a 2274 int err;
26c39028
JHS
2275
2276 if (!netdev->link) {
2277 ERROR("no link specified for vlan netdev");
2278 return -1;
2279 }
2280
9ba8130c
SH
2281 err = snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
2282 if (err >= sizeof(peer)) {
2283 ERROR("peer name too long");
2284 return -1;
2285 }
26c39028 2286
3cfc0f3a
MN
2287 err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
2288 if (err) {
2289 ERROR("failed to create vlan interface '%s' on '%s' : %s",
2290 peer, netdev->link, strerror(-err));
26c39028
JHS
2291 return -1;
2292 }
2293
2294 netdev->ifindex = if_nametoindex(peer);
2295 if (!netdev->ifindex) {
2296 ERROR("failed to retrieve the ifindex for %s", peer);
b84f58b9 2297 lxc_netdev_delete_by_name(peer);
26c39028
JHS
2298 return -1;
2299 }
2300
e892973e
DL
2301 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
2302 netdev->ifindex);
2303
26c39028
JHS
2304 return 0;
2305}
2306
74a2b586
JK
2307static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2308{
2309 return 0;
2310}
2311
e3b4c4c4 2312static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2313{
6168e99f
DL
2314 if (!netdev->link) {
2315 ERROR("no link specified for the physical interface");
2316 return -1;
2317 }
2318
9d083402 2319 netdev->ifindex = if_nametoindex(netdev->link);
82d5ae15 2320 if (!netdev->ifindex) {
9d083402 2321 ERROR("failed to retrieve the index for %s", netdev->link);
0ad19a3f 2322 return -1;
2323 }
2324
e3b4c4c4
ST
2325 if (netdev->upscript) {
2326 int err;
751d9dcd
DL
2327 err = run_script(handler->name, "net", netdev->upscript,
2328 "up", "phys", netdev->link, (char*) NULL);
2329 if (err)
e3b4c4c4 2330 return -1;
e3b4c4c4
ST
2331 }
2332
82d5ae15 2333 return 0;
0ad19a3f 2334}
2335
74a2b586
JK
2336static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
2337{
2338 int err;
2339
2340 if (netdev->downscript) {
2341 err = run_script(handler->name, "net", netdev->downscript,
2342 "down", "phys", netdev->link, (char*) NULL);
2343 if (err)
2344 return -1;
2345 }
2346 return 0;
2347}
2348
e3b4c4c4 2349static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
0ad19a3f 2350{
82d5ae15 2351 netdev->ifindex = 0;
e3b4c4c4
ST
2352 if (netdev->upscript) {
2353 int err;
751d9dcd
DL
2354 err = run_script(handler->name, "net", netdev->upscript,
2355 "up", "empty", (char*) NULL);
2356 if (err)
e3b4c4c4 2357 return -1;
e3b4c4c4 2358 }
82d5ae15 2359 return 0;
0ad19a3f 2360}
2361
74a2b586
JK
2362static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
2363{
2364 int err;
2365
2366 if (netdev->downscript) {
2367 err = run_script(handler->name, "net", netdev->downscript,
2368 "down", "empty", (char*) NULL);
2369 if (err)
2370 return -1;
2371 }
2372 return 0;
2373}
2374
e3b4c4c4 2375int lxc_create_network(struct lxc_handler *handler)
0ad19a3f 2376{
e3b4c4c4 2377 struct lxc_list *network = &handler->conf->network;
82d5ae15 2378 struct lxc_list *iterator;
82d5ae15 2379 struct lxc_netdev *netdev;
0ad19a3f 2380
5f4535a3 2381 lxc_list_for_each(iterator, network) {
0ad19a3f 2382
5f4535a3 2383 netdev = iterator->elem;
13954cce 2384
24654103 2385 if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
82d5ae15 2386 ERROR("invalid network configuration type '%d'",
5f4535a3 2387 netdev->type);
82d5ae15
DL
2388 return -1;
2389 }
0ad19a3f 2390
e3b4c4c4 2391 if (netdev_conf[netdev->type](handler, netdev)) {
82d5ae15
DL
2392 ERROR("failed to create netdev");
2393 return -1;
2394 }
e3b4c4c4 2395
0ad19a3f 2396 }
2397
2398 return 0;
2399}
2400
74a2b586 2401void lxc_delete_network(struct lxc_handler *handler)
7fef7a06 2402{
74a2b586 2403 struct lxc_list *network = &handler->conf->network;
7fef7a06
DL
2404 struct lxc_list *iterator;
2405 struct lxc_netdev *netdev;
2406
2407 lxc_list_for_each(iterator, network) {
2408 netdev = iterator->elem;
d472214b 2409
74a2b586 2410 if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
d8f8e352
DL
2411 if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
2412 WARN("failed to rename to the initial name the " \
2413 "netdev '%s'", netdev->link);
d472214b 2414 continue;
d8f8e352 2415 }
d472214b 2416
74a2b586
JK
2417 if (netdev_deconf[netdev->type](handler, netdev)) {
2418 WARN("failed to destroy netdev");
2419 }
2420
d8f8e352
DL
2421 /* Recent kernel remove the virtual interfaces when the network
2422 * namespace is destroyed but in case we did not moved the
2423 * interface to the network namespace, we have to destroy it
2424 */
74a2b586
JK
2425 if (netdev->ifindex != 0 &&
2426 lxc_netdev_delete_by_index(netdev->ifindex))
d8f8e352 2427 WARN("failed to remove interface '%s'", netdev->name);
7fef7a06
DL
2428 }
2429}
2430
5f4535a3 2431int lxc_assign_network(struct lxc_list *network, pid_t pid)
0ad19a3f 2432{
82d5ae15 2433 struct lxc_list *iterator;
82d5ae15 2434 struct lxc_netdev *netdev;
3cfc0f3a 2435 int err;
0ad19a3f 2436
5f4535a3 2437 lxc_list_for_each(iterator, network) {
82d5ae15 2438
5f4535a3 2439 netdev = iterator->elem;
82d5ae15 2440
236087a6
DL
2441 /* empty network namespace, nothing to move */
2442 if (!netdev->ifindex)
2443 continue;
2444
d472214b 2445 err = lxc_netdev_move_by_index(netdev->ifindex, pid);
3cfc0f3a
MN
2446 if (err) {
2447 ERROR("failed to move '%s' to the container : %s",
2448 netdev->link, strerror(-err));
82d5ae15
DL
2449 return -1;
2450 }
2451
c1c75c04 2452 DEBUG("move '%s' to '%d'", netdev->name, pid);
0ad19a3f 2453 }
2454
2455 return 0;
2456}
2457
19a26f82
MK
2458int lxc_find_gateway_addresses(struct lxc_handler *handler)
2459{
2460 struct lxc_list *network = &handler->conf->network;
2461 struct lxc_list *iterator;
2462 struct lxc_netdev *netdev;
2463 int link_index;
2464
2465 lxc_list_for_each(iterator, network) {
2466 netdev = iterator->elem;
2467
2468 if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto)
2469 continue;
2470
2471 if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) {
2472 ERROR("gateway = auto only supported for "
2473 "veth and macvlan");
2474 return -1;
2475 }
2476
2477 if (!netdev->link) {
2478 ERROR("gateway = auto needs a link interface");
2479 return -1;
2480 }
2481
2482 link_index = if_nametoindex(netdev->link);
2483 if (!link_index)
2484 return -EINVAL;
2485
2486 if (netdev->ipv4_gateway_auto) {
2487 if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) {
2488 ERROR("failed to automatically find ipv4 gateway "
2489 "address from link interface '%s'", netdev->link);
2490 return -1;
2491 }
2492 }
2493
2494 if (netdev->ipv6_gateway_auto) {
2495 if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) {
2496 ERROR("failed to automatically find ipv6 gateway "
2497 "address from link interface '%s'", netdev->link);
2498 return -1;
2499 }
2500 }
2501 }
2502
2503 return 0;
2504}
2505
5e4a62bf 2506int lxc_create_tty(const char *name, struct lxc_conf *conf)
b0a33c1e 2507{
5e4a62bf 2508 struct lxc_tty_info *tty_info = &conf->tty_info;
985d15b1 2509 int i;
b0a33c1e 2510
5e4a62bf
DL
2511 /* no tty in the configuration */
2512 if (!conf->tty)
b0a33c1e 2513 return 0;
2514
13954cce 2515 tty_info->pty_info =
e4e7d59d 2516 malloc(sizeof(*tty_info->pty_info)*conf->tty);
b0a33c1e 2517 if (!tty_info->pty_info) {
36eb9bde 2518 SYSERROR("failed to allocate pty_info");
985d15b1 2519 return -1;
b0a33c1e 2520 }
2521
985d15b1 2522 for (i = 0; i < conf->tty; i++) {
13954cce 2523
b0a33c1e 2524 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2525
13954cce 2526 if (openpty(&pty_info->master, &pty_info->slave,
b0a33c1e 2527 pty_info->name, NULL, NULL)) {
36eb9bde 2528 SYSERROR("failed to create pty #%d", i);
985d15b1
MT
2529 tty_info->nbtty = i;
2530 lxc_delete_tty(tty_info);
2531 return -1;
b0a33c1e 2532 }
2533
5332bb84
DL
2534 DEBUG("allocated pty '%s' (%d/%d)",
2535 pty_info->name, pty_info->master, pty_info->slave);
2536
b035ad62
MS
2537 /* Prevent leaking the file descriptors to the container */
2538 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
2539 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
2540
b0a33c1e 2541 pty_info->busy = 0;
2542 }
2543
985d15b1 2544 tty_info->nbtty = conf->tty;
1ac470c0
DL
2545
2546 INFO("tty's configured");
2547
985d15b1 2548 return 0;
b0a33c1e 2549}
2550
2551void lxc_delete_tty(struct lxc_tty_info *tty_info)
2552{
2553 int i;
2554
2555 for (i = 0; i < tty_info->nbtty; i++) {
2556 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2557
2558 close(pty_info->master);
2559 close(pty_info->slave);
2560 }
2561
2562 free(tty_info->pty_info);
2563 tty_info->nbtty = 0;
2564}
2565
571e6ec8 2566int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
0ad19a3f 2567{
e075f5d9
SH
2568#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
2569 int mounted;
2570#endif
2571
571e6ec8 2572 if (setup_utsname(lxc_conf->utsname)) {
36eb9bde 2573 ERROR("failed to setup the utsname for '%s'", name);
95b5ffaf 2574 return -1;
0ad19a3f 2575 }
2576
5f4535a3 2577 if (setup_network(&lxc_conf->network)) {
36eb9bde 2578 ERROR("failed to setup the network for '%s'", name);
95b5ffaf 2579 return -1;
0ad19a3f 2580 }
2581
89eaa05e
SH
2582 if (run_lxc_hooks(name, "pre-mount", lxc_conf)) {
2583 ERROR("failed to run pre-mount hooks for container '%s'.", name);
2584 return -1;
2585 }
5ea6163a 2586
cc28d0b0 2587 if (setup_rootfs(lxc_conf)) {
ac778708 2588 ERROR("failed to setup rootfs for '%s'", name);
95b5ffaf 2589 return -1;
0ad19a3f 2590 }
2591
c6883f38 2592 if (lxc_conf->autodev) {
91c3830e
SH
2593 if (mount_autodev(lxc_conf->rootfs.mount)) {
2594 ERROR("failed to mount /dev in the container");
c6883f38
SH
2595 return -1;
2596 }
2597 }
2598
80a881b2 2599 if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
36eb9bde 2600 ERROR("failed to setup the mounts for '%s'", name);
95b5ffaf 2601 return -1;
576f946d 2602 }
2603
c1dc38c2 2604 if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name)) {
e7938e9e
MN
2605 ERROR("failed to setup the mount entries for '%s'", name);
2606 return -1;
2607 }
2608
773fb9ca
SH
2609 if (run_lxc_hooks(name, "mount", lxc_conf)) {
2610 ERROR("failed to run mount hooks for container '%s'.", name);
2611 return -1;
2612 }
2613
91c3830e
SH
2614 if (lxc_conf->autodev) {
2615 if (setup_autodev(lxc_conf->rootfs.mount)) {
2616 ERROR("failed to populate /dev in the container");
2617 return -1;
2618 }
2619 }
2620
ac778708
DL
2621 if (setup_cgroup(name, &lxc_conf->cgroup)) {
2622 ERROR("failed to setup the cgroups for '%s'", name);
2623 return -1;
2624 }
2625
7c6ef2a2 2626 if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
36eb9bde 2627 ERROR("failed to setup the console for '%s'", name);
95b5ffaf 2628 return -1;
6e590161 2629 }
2630
f62b3449 2631 if (setup_kmsg(&lxc_conf->rootfs, &lxc_conf->console)) // don't fail
1bd051a6 2632 ERROR("failed to setup kmsg for '%s'", name);
1bd051a6 2633
7c6ef2a2 2634 if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
36eb9bde 2635 ERROR("failed to setup the ttys for '%s'", name);
95b5ffaf 2636 return -1;
b0a33c1e 2637 }
2638
e075f5d9 2639#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
9ac3ffb5
SG
2640 INFO("rootfs path is .%s., mount is .%s.", lxc_conf->rootfs.path,
2641 lxc_conf->rootfs.mount);
2642 if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0)
2643 mounted = 0;
2644 else
2645 mounted = lsm_mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
e075f5d9
SH
2646 if (mounted == -1) {
2647 SYSERROR("failed to mount /proc in the container.");
2648 return -1;
2649 } else if (mounted == 1) {
2650 lxc_conf->lsm_umount_proc = 1;
2651 }
2652#endif
2653
ac778708 2654 if (setup_pivot_root(&lxc_conf->rootfs)) {
36eb9bde 2655 ERROR("failed to set rootfs for '%s'", name);
95b5ffaf 2656 return -1;
ed502555 2657 }
2658
571e6ec8 2659 if (setup_pts(lxc_conf->pts)) {
36eb9bde 2660 ERROR("failed to setup the new pts instance");
95b5ffaf 2661 return -1;
3c26f34e 2662 }
2663
cccc74b5
DL
2664 if (setup_personality(lxc_conf->personality)) {
2665 ERROR("failed to setup personality");
2666 return -1;
2667 }
2668
81810dd1
DL
2669 if (setup_caps(&lxc_conf->caps)) {
2670 ERROR("failed to drop capabilities");
2671 return -1;
2672 }
2673
cd54d859
DL
2674 NOTICE("'%s' is setup.", name);
2675
0ad19a3f 2676 return 0;
2677}
26ddeedd
SH
2678
2679int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf)
2680{
2681 int which = -1;
2682 struct lxc_list *it;
2683
2684 if (strcmp(hook, "pre-start") == 0)
2685 which = LXCHOOK_PRESTART;
5ea6163a
SH
2686 else if (strcmp(hook, "pre-mount") == 0)
2687 which = LXCHOOK_PREMOUNT;
26ddeedd
SH
2688 else if (strcmp(hook, "mount") == 0)
2689 which = LXCHOOK_MOUNT;
2690 else if (strcmp(hook, "start") == 0)
2691 which = LXCHOOK_START;
2692 else if (strcmp(hook, "post-stop") == 0)
2693 which = LXCHOOK_POSTSTOP;
2694 else
2695 return -1;
2696 lxc_list_for_each(it, &conf->hooks[which]) {
2697 int ret;
2698 char *hookname = it->elem;
2699 ret = run_script(name, "lxc", hookname, hook, NULL);
2700 if (ret)
2701 return ret;
2702 }
2703 return 0;
2704}
72d0e1cb 2705
427b3a21 2706static void lxc_remove_nic(struct lxc_list *it)
72d0e1cb
SG
2707{
2708 struct lxc_netdev *netdev = it->elem;
9ebb03ad 2709 struct lxc_list *it2,*next;
72d0e1cb
SG
2710
2711 lxc_list_del(it);
2712
2713 if (netdev->link)
2714 free(netdev->link);
2715 if (netdev->name)
2716 free(netdev->name);
2717 if (netdev->upscript)
2718 free(netdev->upscript);
2719 if (netdev->hwaddr)
2720 free(netdev->hwaddr);
2721 if (netdev->mtu)
2722 free(netdev->mtu);
2723 if (netdev->ipv4_gateway)
2724 free(netdev->ipv4_gateway);
2725 if (netdev->ipv6_gateway)
2726 free(netdev->ipv6_gateway);
9ebb03ad 2727 lxc_list_for_each_safe(it2, &netdev->ipv4, next) {
72d0e1cb
SG
2728 lxc_list_del(it2);
2729 free(it2->elem);
2730 free(it2);
2731 }
9ebb03ad 2732 lxc_list_for_each_safe(it2, &netdev->ipv6, next) {
72d0e1cb
SG
2733 lxc_list_del(it2);
2734 free(it2->elem);
2735 free(it2);
2736 }
d95db067 2737 free(netdev);
72d0e1cb
SG
2738 free(it);
2739}
2740
2741/* we get passed in something like '0', '0.ipv4' or '1.ipv6' */
12a50cc6 2742int lxc_clear_nic(struct lxc_conf *c, const char *key)
72d0e1cb
SG
2743{
2744 char *p1;
2745 int ret, idx, i;
2746 struct lxc_list *it;
2747 struct lxc_netdev *netdev;
2748
2749 p1 = index(key, '.');
2750 if (!p1 || *(p1+1) == '\0')
2751 p1 = NULL;
2752
2753 ret = sscanf(key, "%d", &idx);
2754 if (ret != 1) return -1;
2755 if (idx < 0)
2756 return -1;
2757
2758 i = 0;
2759 lxc_list_for_each(it, &c->network) {
2760 if (i == idx)
2761 break;
2762 i++;
2763 }
2764 if (i < idx) // we don't have that many nics defined
2765 return -1;
2766
2767 if (!it || !it->elem)
2768 return -1;
2769
2770 netdev = it->elem;
2771
2772 if (!p1) {
2773 lxc_remove_nic(it);
2774 } else if (strcmp(p1, "ipv4") == 0) {
9ebb03ad
DE
2775 struct lxc_list *it2,*next;
2776 lxc_list_for_each_safe(it2, &netdev->ipv4, next) {
72d0e1cb
SG
2777 lxc_list_del(it2);
2778 free(it2->elem);
2779 free(it2);
2780 }
2781 } else if (strcmp(p1, "ipv6") == 0) {
9ebb03ad
DE
2782 struct lxc_list *it2,*next;
2783 lxc_list_for_each_safe(it2, &netdev->ipv6, next) {
72d0e1cb
SG
2784 lxc_list_del(it2);
2785 free(it2->elem);
2786 free(it2);
2787 }
2788 } else if (strcmp(p1, "link") == 0) {
2789 if (netdev->link) {
2790 free(netdev->link);
2791 netdev->link = NULL;
2792 }
2793 } else if (strcmp(p1, "name") == 0) {
2794 if (netdev->name) {
2795 free(netdev->name);
2796 netdev->name = NULL;
2797 }
2798 } else if (strcmp(p1, "script.up") == 0) {
2799 if (netdev->upscript) {
2800 free(netdev->upscript);
2801 netdev->upscript = NULL;
2802 }
2803 } else if (strcmp(p1, "hwaddr") == 0) {
2804 if (netdev->hwaddr) {
2805 free(netdev->hwaddr);
2806 netdev->hwaddr = NULL;
2807 }
2808 } else if (strcmp(p1, "mtu") == 0) {
2809 if (netdev->mtu) {
2810 free(netdev->mtu);
2811 netdev->mtu = NULL;
2812 }
2813 } else if (strcmp(p1, "ipv4_gateway") == 0) {
2814 if (netdev->ipv4_gateway) {
2815 free(netdev->ipv4_gateway);
2816 netdev->ipv4_gateway = NULL;
2817 }
2818 } else if (strcmp(p1, "ipv6_gateway") == 0) {
2819 if (netdev->ipv6_gateway) {
2820 free(netdev->ipv6_gateway);
2821 netdev->ipv6_gateway = NULL;
2822 }
2823 }
2824 else return -1;
2825
2826 return 0;
2827}
2828
2829int lxc_clear_config_network(struct lxc_conf *c)
2830{
9ebb03ad
DE
2831 struct lxc_list *it,*next;
2832 lxc_list_for_each_safe(it, &c->network, next) {
72d0e1cb
SG
2833 lxc_remove_nic(it);
2834 }
2835 return 0;
2836}
2837
2838int lxc_clear_config_caps(struct lxc_conf *c)
2839{
9ebb03ad 2840 struct lxc_list *it,*next;
72d0e1cb 2841
9ebb03ad 2842 lxc_list_for_each_safe(it, &c->caps, next) {
72d0e1cb
SG
2843 lxc_list_del(it);
2844 free(it->elem);
2845 free(it);
2846 }
2847 return 0;
2848}
2849
12a50cc6 2850int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
72d0e1cb 2851{
9ebb03ad 2852 struct lxc_list *it,*next;
72d0e1cb 2853 bool all = false;
12a50cc6 2854 const char *k = key + 11;
72d0e1cb
SG
2855
2856 if (strcmp(key, "lxc.cgroup") == 0)
2857 all = true;
2858
9ebb03ad 2859 lxc_list_for_each_safe(it, &c->cgroup, next) {
72d0e1cb
SG
2860 struct lxc_cgroup *cg = it->elem;
2861 if (!all && strcmp(cg->subsystem, k) != 0)
2862 continue;
2863 lxc_list_del(it);
2864 free(cg->subsystem);
2865 free(cg->value);
2866 free(cg);
2867 free(it);
2868 }
2869 return 0;
2870}
2871
2872int lxc_clear_mount_entries(struct lxc_conf *c)
2873{
9ebb03ad 2874 struct lxc_list *it,*next;
72d0e1cb 2875
9ebb03ad 2876 lxc_list_for_each_safe(it, &c->mount_list, next) {
72d0e1cb
SG
2877 lxc_list_del(it);
2878 free(it->elem);
2879 free(it);
2880 }
2881 return 0;
2882}
2883
12a50cc6 2884int lxc_clear_hooks(struct lxc_conf *c, const char *key)
72d0e1cb 2885{
9ebb03ad 2886 struct lxc_list *it,*next;
17ed13a3 2887 bool all = false, done = false;
12a50cc6 2888 const char *k = key + 9;
72d0e1cb
SG
2889 int i;
2890
17ed13a3
SH
2891 if (strcmp(key, "lxc.hook") == 0)
2892 all = true;
2893
72d0e1cb 2894 for (i=0; i<NUM_LXC_HOOKS; i++) {
17ed13a3 2895 if (all || strcmp(k, lxchook_names[i]) == 0) {
9ebb03ad 2896 lxc_list_for_each_safe(it, &c->hooks[i], next) {
17ed13a3
SH
2897 lxc_list_del(it);
2898 free(it->elem);
2899 free(it);
2900 }
2901 done = true;
72d0e1cb
SG
2902 }
2903 }
17ed13a3
SH
2904
2905 if (!done) {
2906 ERROR("Invalid hook key: %s", key);
2907 return -1;
2908 }
72d0e1cb
SG
2909 return 0;
2910}
8eb5694b 2911
7b35f3d6
SH
2912void lxc_clear_saved_nics(struct lxc_conf *conf)
2913{
2914 int i;
2915
2916 if (!conf->num_savednics)
2917 return;
2918 for (i=0; i < conf->num_savednics; i++)
2919 free(conf->saved_nics[i].orig_name);
2920 conf->saved_nics = 0;
2921 free(conf->saved_nics);
2922}
2923
8eb5694b
SH
2924void lxc_conf_free(struct lxc_conf *conf)
2925{
2926 if (!conf)
2927 return;
2928 if (conf->console.path)
2929 free(conf->console.path);
ae9242c8 2930 if (conf->rootfs.mount != default_rootfs_mount)
8eb5694b 2931 free(conf->rootfs.mount);
d95db067
DE
2932 if (conf->rootfs.path)
2933 free(conf->rootfs.path);
2934 if (conf->utsname)
2935 free(conf->utsname);
2936 if (conf->ttydir)
2937 free(conf->ttydir);
2938 if (conf->fstab)
2939 free(conf->fstab);
8eb5694b 2940 lxc_clear_config_network(conf);
1f530df6 2941#if HAVE_APPARMOR
8eb5694b
SH
2942 if (conf->aa_profile)
2943 free(conf->aa_profile);
1f530df6 2944#endif
769872f9 2945 lxc_seccomp_free(conf);
8eb5694b
SH
2946 lxc_clear_config_caps(conf);
2947 lxc_clear_cgroups(conf, "lxc.cgroup");
17ed13a3 2948 lxc_clear_hooks(conf, "lxc.hook");
8eb5694b 2949 lxc_clear_mount_entries(conf);
7b35f3d6 2950 lxc_clear_saved_nics(conf);
8eb5694b
SH
2951 free(conf);
2952}