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