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