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