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