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

2009-02-27 Thread Daniel Veillard
On Thu, Feb 26, 2009 at 04:42:59PM +, Daniel P. Berrange wrote:
 
 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.

  Will that work for dynamically plugged block devices ? This seems to
have the potential to break things there, isn't-it ?

 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.

[...]
 +if (virCgroupAllowDeviceMajor(cgroup, 'c', 136)  0) {

  errr ... what is 136 ? Maybe a descriptive constant would help :-)

  In gneral how much testing do we need before pushing those patches ?

Daniel

-- 
Daniel Veillard  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
dan...@veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


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

2009-02-26 Thread Daniel P. Berrange

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 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list