[libvirt] PATCH: 3/3: Control file device access

Daniel P. Berrange berrange at redhat.com
Thu Feb 26 16:42:59 UTC 2009


This patch is more focused on access control. CGroups has a controller
that enforces ACLs on device nodes. This allows us to restrict exactly
what block/character devices  a guest is allowed to access. So in the
absence of something like SELinux sVirt, you can get a degree of 
isolation between VMs on block device backed disks.

This sets up an initial deny-all policy, and then iterates over all
the disks defined for a VM, allowing each one in turn. Finally it
allows a handy of common nodes like /dev/null, /dev/random, /dev/ptmx
and friends, which all processes need to use.

Daniel

diff --git a/src/cgroup.c b/src/cgroup.c
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -788,6 +788,23 @@ int virCgroupAllowDeviceMajor(virCgroupP
     return rc;
 }
 
+int virCgroupAllowDevicePath(virCgroupPtr group,
+                             const char *path)
+{
+    struct stat sb;
+
+    if (stat(path, &sb) < 0)
+        return -errno;
+
+    if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
+        return -EINVAL;
+
+    return virCgroupAllowDevice(group,
+                                S_ISCHR(sb.st_mode) ? 'c' : 'b',
+                                major(sb.st_rdev),
+                                minor(sb.st_rdev));
+}
+
 int virCgroupSetCpuShares(virCgroupPtr group, unsigned long shares)
 {
     return virCgroupSetValueU64(group, "cpu.shares", (uint64_t)shares);
diff --git a/src/cgroup.h b/src/cgroup.h
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -38,6 +38,8 @@ int virCgroupAllowDevice(virCgroupPtr gr
 int virCgroupAllowDeviceMajor(virCgroupPtr group,
                               char type,
                               int major);
+int virCgroupAllowDevicePath(virCgroupPtr group,
+                             const char *path);
 
 int virCgroupSetCpuShares(virCgroupPtr group, unsigned long shares);
 int virCgroupGetCpuShares(virCgroupPtr group, unsigned long *shares);
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1135,11 +1135,18 @@ static int qemudNextFreeVNCPort(struct q
 static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                             const char *name);
 
+static const char *const devs[] = {
+    "/dev/null", "/dev/full", "/dev/zero",
+    "/dev/random", "/dev/urandom",
+    "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
+};
+
 static int qemuSetupCgroup(virConnectPtr conn,
                            struct qemud_driver *driver ATTRIBUTE_UNUSED,
                            virDomainObjPtr vm)
 {
     virCgroupPtr cgroup = NULL;
+    unsigned int i;
 
     if (virCgroupHaveSupport() != 0)
         return 0; /* Not supported, so claim success */
@@ -1151,6 +1158,41 @@ static int qemuSetupCgroup(virConnectPtr
         goto cleanup;
     }
 
+    if (virCgroupDenyAllDevices(cgroup) != 0)
+        goto cleanup;
+
+    for (i = 0; i < vm->def->ndisks ; i++) {
+        if (vm->def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK)
+            continue;
+
+        if (virCgroupAllowDevicePath(cgroup,
+                                     vm->def->disks[i]->src) < 0) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                             _("unable to allow device %s"),
+                             vm->def->disks[i]->src);
+            goto cleanup;
+        }
+    }
+
+    if (virCgroupAllowDeviceMajor(cgroup, 'c', 136) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("unable to allow device %s"),
+                         devs[i]);
+        goto cleanup;
+    }
+
+    for (i = 0; i < ARRAY_CARDINALITY(devs) ; i++) {
+        int rc;
+        if ((rc = virCgroupAllowDevicePath(cgroup,
+                                           devs[i])) < 0 &&
+            rc != -ENOENT) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                             _("unable to allow device %s"),
+                             devs[i]);
+            goto cleanup;
+        }
+    }
+
     virCgroupFree(&cgroup);
     return 0;
 

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list