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