~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to src/lxc/lxc_container.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-13 15:44:12 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20120513154412-fgmn5sxqdzgnzlx3
Tags: 0.9.12-0ubuntu1
* New upstream version:
  * Synchronize with debian packaging:
    - debian/control: Update build depends.
    - debian/libvirt-bin.postrm: Cleanup /var/log/libvirt
      on purge.
    - Bump standards verson (no changes).
    - debian/patches/Don-t-fail-if-we-can-t-setup-avahi.patch: Added
  * Dropped patches:
    - debian/patches/Debianize-libvirt-guests.patch
    - debian/patches/rewrite-lxc-controller-eof-handling-yet-again
    - debian/patches/ubuntu/libnl13.patch
    - debian/patches/ubuntu/fix-lxc-startup-error.patch
    - debian/patches/ubuntu/fix-bridge-fd.patch
    - debian/patches/ubuntu/skip-labelling-network-disks.patch
    - debian/patches/ubuntu/xen-xend-shutdown-detection.patch
    - debian/patches/ubuntu/xen-config-no-vfb-for-hvm.patch
    - debian/patches/debian/Disable-daemon-start-test.patch
    - debian/patches/debian/Disable-gnulib-s-test-nonplocking-pipe.sh.patch
    - debian/patches/ubuntu/9006-default-config-test-case.patch
    - debian/patches/fix-block-migration.patch
    - debian/patches/ubuntu/9022-qemu-unescape-HMP-commands-before-converting-them-to.patch
    - debian/patches/ubuntu/9023-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/9024-qemu-allow-snapshotting-of-sheepdog-and-rbd-disks.patch
    - debian/patches/9025-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/arm-gcc-workaround.patch
  * Rediffed:
    - debian/patches/Allow-libvirt-group-to-access-the-socket.patch
    - debian/patches/Disable-failing-virnetsockettest.patch
    - debian/patches/dnsmasq-as-priv-user
    - debian/patches/9002-better_default_uri_virsh.patch
  * debian/control: Add libnl-route-3-dev ass a build depends.
  * debian/patches/libnl3-build-fix.patch: Fix build with libnl3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2008-2011 Red Hat, Inc.
 
2
 * Copyright (C) 2008-2012 Red Hat, Inc.
3
3
 * Copyright (C) 2008 IBM Corp.
4
4
 *
5
5
 * lxc_container.c: file description
36
36
#include <unistd.h>
37
37
#include <mntent.h>
38
38
 
 
39
#if HAVE_SELINUX
 
40
# include <selinux/selinux.h>
 
41
#endif
 
42
 
39
43
/* Yes, we want linux private one, for _syscall2() macro */
40
44
#include <linux/unistd.h>
41
45
 
92
96
typedef struct __lxc_child_argv lxc_child_argv_t;
93
97
struct __lxc_child_argv {
94
98
    virDomainDefPtr config;
 
99
    virSecurityManagerPtr securityDriver;
95
100
    unsigned int nveths;
96
101
    char **veths;
97
102
    int monitor;
118
123
 
119
124
    cmd = virCommandNew(vmDef->os.init);
120
125
 
 
126
    if (vmDef->os.initargv && vmDef->os.initargv[0])
 
127
        virCommandAddArgSet(cmd, (const char **)vmDef->os.initargv);
 
128
 
121
129
    virCommandAddEnvString(cmd, "PATH=/bin:/sbin");
122
130
    virCommandAddEnvString(cmd, "TERM=linux");
 
131
    virCommandAddEnvString(cmd, "container=lxc-libvirt");
 
132
    virCommandAddEnvPair(cmd, "container_uuid", uuidstr);
123
133
    virCommandAddEnvPair(cmd, "LIBVIRT_LXC_UUID", uuidstr);
124
134
    virCommandAddEnvPair(cmd, "LIBVIRT_LXC_NAME", vmDef->name);
125
135
    if (vmDef->os.cmdline)
255
265
 *
256
266
 * Returns 0 on success or nonzero in case of error
257
267
 */
258
 
static int lxcContainerRenameAndEnableInterfaces(unsigned int nveths,
 
268
static int lxcContainerRenameAndEnableInterfaces(bool privNet,
 
269
                                                 unsigned int nveths,
259
270
                                                 char **veths)
260
271
{
261
272
    int rc = 0;
283
294
    }
284
295
 
285
296
    /* enable lo device only if there were other net devices */
286
 
    if (veths)
 
297
    if (veths || privNet)
287
298
        rc = virNetDevSetOnline("lo", true);
288
299
 
289
300
error_out:
419
430
static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
420
431
{
421
432
    const struct {
422
 
        bool onlyPivotRoot;
423
433
        bool needPrefix;
424
434
        const char *src;
425
435
        const char *dst;
428
438
        int mflags;
429
439
    } mnts[] = {
430
440
        /* When we want to make a bind mount readonly, for unknown reasons,
431
 
         * it is currently neccessary to bind it once, and then remount the
 
441
         * it is currently necessary to bind it once, and then remount the
432
442
         * bind with the readonly flag. If this is not done, then the original
433
443
         * mount point in the main OS becomes readonly too which is not what
434
444
         * we want. Hence some things have two entries here.
435
445
         */
436
 
        { true, false, "devfs", "/dev", "tmpfs", "mode=755", MS_NOSUID },
437
 
        { false, false, "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
438
 
        { false, false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND },
439
 
        { false, false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
440
 
        { false, true, "/sys", "/sys", NULL, NULL, MS_BIND },
441
 
        { false, true, "/sys", "/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
442
 
        { false, true, "/selinux", "/selinux", NULL, NULL, MS_BIND },
443
 
        { false, true, "/selinux", "/selinux", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
 
446
        { false, "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
 
447
        { false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND },
 
448
        { false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
 
449
        { true, "/sys", "/sys", NULL, NULL, MS_BIND },
 
450
        { true, "/sys", "/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
 
451
#if HAVE_SELINUX
 
452
        { true, SELINUX_MOUNT, SELINUX_MOUNT, NULL, NULL, MS_BIND },
 
453
        { true, SELINUX_MOUNT, SELINUX_MOUNT, NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
 
454
#endif
444
455
    };
445
456
    int i, rc = -1;
 
457
    char *opts = NULL;
 
458
#if HAVE_SELINUX
 
459
    security_context_t con;
 
460
#endif
446
461
 
447
462
    VIR_DEBUG("Mounting basic filesystems %s pivotRoot=%d", NULLSTR(srcprefix), pivotRoot);
448
463
 
450
465
        char *src = NULL;
451
466
        const char *srcpath = NULL;
452
467
 
453
 
        VIR_DEBUG("Consider %s onlyPivotRoot=%d",
454
 
                  mnts[i].src, mnts[i].onlyPivotRoot);
455
 
        if (mnts[i].onlyPivotRoot && !pivotRoot)
456
 
            continue;
 
468
        VIR_DEBUG("Processing %s -> %s",
 
469
                  mnts[i].src, mnts[i].dst);
457
470
 
458
471
        if (virFileMakePath(mnts[i].dst) < 0) {
459
472
            virReportSystemError(errno,
474
487
 
475
488
        /* Skip if mount doesn't exist in source */
476
489
        if ((srcpath[0] == '/') &&
477
 
            (access(srcpath, R_OK) < 0))
 
490
            (access(srcpath, R_OK) < 0)) {
 
491
            VIR_FREE(src);
478
492
            continue;
 
493
        }
479
494
 
480
495
        VIR_DEBUG("Mount %s on %s type=%s flags=%x, opts=%s",
481
496
                  srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts);
489
504
        VIR_FREE(src);
490
505
    }
491
506
 
 
507
    if (pivotRoot) {
 
508
#if HAVE_SELINUX
 
509
        if (getfilecon("/", &con) < 0 &&
 
510
            errno != ENOTSUP) {
 
511
            virReportSystemError(errno, "%s",
 
512
                                 _("Failed to query file context on /"));
 
513
            goto cleanup;
 
514
        }
 
515
#endif
 
516
        /*
 
517
         * tmpfs is limited to 64kb, since we only have device nodes in there
 
518
         * and don't want to DOS the entire OS RAM usage
 
519
         */
 
520
 
 
521
#if HAVE_SELINUX
 
522
        if (con)
 
523
            ignore_value(virAsprintf(&opts,
 
524
                                     "mode=755,size=65536,context=\"%s\"",
 
525
                                     (const char *)con));
 
526
        else
 
527
#endif
 
528
            opts = strdup("mode=755,size=65536");
 
529
 
 
530
        if (!opts) {
 
531
            virReportOOMError();
 
532
            goto cleanup;
 
533
        }
 
534
 
 
535
        VIR_DEBUG("Mount devfs on /dev type=tmpfs flags=%x, opts=%s",
 
536
                  MS_NOSUID, opts);
 
537
        if (mount("devfs", "/dev", "tmpfs", MS_NOSUID, opts) < 0) {
 
538
            virReportSystemError(errno,
 
539
                                 _("Failed to mount %s on %s type %s"),
 
540
                                 "devfs", "/dev", "tmpfs");
 
541
            goto cleanup;
 
542
        }
 
543
    }
 
544
 
492
545
    rc = 0;
493
546
 
494
547
cleanup:
495
548
    VIR_DEBUG("rc=%d", rc);
 
549
    VIR_FREE(opts);
496
550
    return rc;
497
551
}
498
552
 
499
553
 
500
 
static int lxcContainerMountDevFS(virDomainFSDefPtr root)
 
554
static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root)
501
555
{
502
556
    char *devpts = NULL;
503
557
    int rc = -1;
543
597
        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
544
598
        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
545
599
    };
 
600
    const struct {
 
601
        const char *src;
 
602
        const char *dst;
 
603
    } links[] = {
 
604
        { "/proc/self/fd/0", "/dev/stdin" },
 
605
        { "/proc/self/fd/1", "/dev/stdout" },
 
606
        { "/proc/self/fd/2", "/dev/stderr" },
 
607
        { "/proc/self/fd", "/dev/fd" },
 
608
    };
546
609
 
547
610
    /* Populate /dev/ with a few important bits */
548
611
    for (i = 0 ; i < ARRAY_CARDINALITY(devs) ; i++) {
556
619
        }
557
620
    }
558
621
 
559
 
    dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX);
560
 
    if (mknod("/dev/ptmx", S_IFCHR, dev) < 0 ||
561
 
        chmod("/dev/ptmx", 0666)) {
562
 
        virReportSystemError(errno, "%s",
563
 
                             _("Failed to make device /dev/ptmx"));
564
 
        return -1;
 
622
    for (i = 0 ; i < ARRAY_CARDINALITY(links) ; i++) {
 
623
        if (symlink(links[i].src, links[i].dst) < 0) {
 
624
            virReportSystemError(errno,
 
625
                                 _("Failed to symlink device %s to %s"),
 
626
                                 links[i].dst, links[i].src);
 
627
            return -1;
 
628
        }
565
629
    }
566
630
 
567
631
    if (access("/dev/pts/ptmx", W_OK) == 0) {
 
632
        /* We have private devpts capability, so bind that */
 
633
        if (virFileTouch("/dev/ptmx", 0666) < 0)
 
634
            return -1;
 
635
 
568
636
        if (mount("/dev/pts/ptmx", "/dev/ptmx", "ptmx", MS_BIND, NULL) < 0) {
569
637
            virReportSystemError(errno, "%s",
570
 
                                 _("Failed to bind-mount /dev/ptmx to /dev/pts/ptmx"));
 
638
                                 _("Failed to bind /dev/pts/ptmx on to /dev/ptmx"));
 
639
            return -1;
 
640
        }
 
641
    } else {
 
642
        /* Legacy devpts, so we need to just use shared one */
 
643
        dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX);
 
644
        if (mknod("/dev/ptmx", S_IFCHR, dev) < 0 ||
 
645
            chmod("/dev/ptmx", 0666)) {
 
646
            virReportSystemError(errno, "%s",
 
647
                                 _("Failed to make device /dev/ptmx"));
571
648
            return -1;
572
649
        }
573
650
    }
1064
1141
    if (lxcContainerMountBasicFS("/.oldroot", true) < 0)
1065
1142
        return -1;
1066
1143
 
1067
 
    /* Mounts /dev and /dev/pts */
1068
 
    if (lxcContainerMountDevFS(root) < 0)
 
1144
    /* Mounts /dev/pts */
 
1145
    if (lxcContainerMountFSDevPTS(root) < 0)
1069
1146
        return -1;
1070
1147
 
1071
1148
    /* Populates device nodes in /dev/ */
1112
1189
    return 0;
1113
1190
}
1114
1191
 
 
1192
 
 
1193
static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
 
1194
{
 
1195
    char *newroot;
 
1196
    size_t i;
 
1197
 
 
1198
    for (i = 0 ; i < vmDef->nfss ; i++) {
 
1199
        virDomainFSDefPtr fs = vmDef->fss[i];
 
1200
        if (virFileResolveAllLinks(fs->src, &newroot) < 0)
 
1201
            return -1;
 
1202
 
 
1203
        VIR_DEBUG("Resolved '%s' to %s", fs->src, newroot);
 
1204
 
 
1205
        VIR_FREE(fs->src);
 
1206
        fs->src = newroot;
 
1207
    }
 
1208
 
 
1209
    return 0;
 
1210
}
 
1211
 
1115
1212
static int lxcContainerSetupMounts(virDomainDefPtr vmDef,
1116
1213
                                   virDomainFSDefPtr root,
1117
1214
                                   char **ttyPaths,
1118
1215
                                   size_t nttyPaths)
1119
1216
{
 
1217
    if (lxcContainerResolveSymlinks(vmDef) < 0)
 
1218
        return -1;
 
1219
 
1120
1220
    if (root)
1121
1221
        return lxcContainerSetupPivotRoot(vmDef, root, ttyPaths, nttyPaths);
1122
1222
    else
1250
1350
    VIR_DEBUG("Received container continue message");
1251
1351
 
1252
1352
    /* rename and enable interfaces */
1253
 
    if (lxcContainerRenameAndEnableInterfaces(argv->nveths,
 
1353
    if (lxcContainerRenameAndEnableInterfaces(!!(vmDef->features &
 
1354
                                                 (1 << VIR_DOMAIN_FEATURE_PRIVNET)),
 
1355
                                              argv->nveths,
1254
1356
                                              argv->veths) < 0) {
1255
1357
        goto cleanup;
1256
1358
    }
1265
1367
        goto cleanup;
1266
1368
    }
1267
1369
 
 
1370
    VIR_DEBUG("Setting up security labeling");
 
1371
    if (virSecurityManagerSetProcessLabel(argv->securityDriver, vmDef) < 0)
 
1372
        goto cleanup;
 
1373
 
1268
1374
    if (lxcContainerSetStdio(argv->monitor, ttyfd, argv->handshakefd) < 0) {
1269
1375
        goto cleanup;
1270
1376
    }
1331
1437
 * Returns PID of container on success or -1 in case of error
1332
1438
 */
1333
1439
int lxcContainerStart(virDomainDefPtr def,
 
1440
                      virSecurityManagerPtr securityDriver,
1334
1441
                      unsigned int nveths,
1335
1442
                      char **veths,
1336
1443
                      int control,
1342
1449
    int cflags;
1343
1450
    int stacksize = getpagesize() * 4;
1344
1451
    char *stack, *stacktop;
1345
 
    lxc_child_argv_t args = { def, nveths, veths, control,
 
1452
    lxc_child_argv_t args = { def, securityDriver,
 
1453
                              nveths, veths, control,
1346
1454
                              ttyPaths, nttyPaths, handshakefd};
1347
1455
 
1348
1456
    /* allocate a stack for the container */
1359
1467
        cflags |= CLONE_NEWUSER;
1360
1468
    }
1361
1469
 
1362
 
    if (def->nets != NULL) {
 
1470
    if (def->nets != NULL ||
 
1471
        (def->features & (1 << VIR_DOMAIN_FEATURE_PRIVNET))) {
1363
1472
        VIR_DEBUG("Enable network namespaces");
1364
1473
        cflags |= CLONE_NEWNET;
1365
1474
    }
1409
1518
    if (cpid < 0) {
1410
1519
        char ebuf[1024] ATTRIBUTE_UNUSED;
1411
1520
        VIR_DEBUG("clone call returned %s, container support is not enabled",
1412
 
              virStrerror(errno, ebuf, sizeof ebuf));
 
1521
                  virStrerror(errno, ebuf, sizeof(ebuf)));
1413
1522
        return -1;
1414
1523
    } else if (virPidWait(cpid, NULL) < 0) {
1415
1524
        return -1;