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