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