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