]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add call to sanlock_restrict() in QEMU lock driver
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 2 Jun 2011 10:46:56 +0000 (11:46 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 2 Jun 2011 16:23:44 +0000 (17:23 +0100)
In between fork and exec, a connection to sanlock is acquired
and the socket file descriptor is intionally leaked to the
child process. sanlock watches this FD for POLL_HANGUP to
detect when QEMU has exited. We don't want a rogus/compromised
QEMU from issuing sanlock RPC calls on the leaked FD though,
since that could be used to DOS other guests. By calling
sanlock_restrict() on the socket before exec() we can lock
it down.

* configure.ac: Check for sanlock_restrict API
* src/locking/domain_lock.c: Restrict lock acquired in
  process startup phase
* src/locking/lock_driver.h: Add VIR_LOCK_MANAGER_ACQUIRE_RESTRICT
* src/locking/lock_driver_sanlock.c: Add call to sanlock_restrict
  when requested by VIR_LOCK_MANAGER_ACQUIRE_RESTRICT flag

configure.ac
src/locking/domain_lock.c
src/locking/lock_driver.h
src/locking/lock_driver_sanlock.c

index a1bd64d21306de1ffe82bcbab3f6baae792ab55f..25669cfb17a9069507ef21ca87394e2a8dfe98e2 100644 (file)
@@ -972,7 +972,7 @@ if test "x$with_sanlock" != "xno"; then
         fail=1
     fi])
   if test "x$with_sanlock" != "xno" ; then
-    AC_CHECK_LIB([sanlock], [sanlock_acquire],[
+    AC_CHECK_LIB([sanlock], [sanlock_restrict],[
       SANLOCK_LIBS="$SANLOCK_LIBS -lsanlock"
       with_sanlock=yes
     ],[
index 85352e232adc5ae51fb998fb336bdf0c547502d8..f0a11b7f14331d5f504fe361bf1d3ce86ad6ff12 100644 (file)
@@ -159,10 +159,12 @@ int virDomainLockProcessStart(virLockManagerPluginPtr plugin,
 {
     virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, true);
     int ret;
+    int flags = VIR_LOCK_MANAGER_ACQUIRE_RESTRICT;
+
     if (paused)
-        ret = virLockManagerAcquire(lock, NULL, VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY);
-    else
-        ret = virLockManagerAcquire(lock, NULL, 0);
+        flags |= VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY;
+
+    ret = virLockManagerAcquire(lock, NULL, flags);
 
     virLockManagerFree(lock);
 
index 40a55f6ffed0b580b52700e7469d2cdfb67d0f93..2e71113fc2036fd9a9d103cb4d30911490262d7e 100644 (file)
@@ -59,7 +59,9 @@ typedef enum {
 
 typedef enum {
     /* Don't acquire the resources, just register the object PID */
-    VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY = (1 << 0)
+    VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY = (1 << 0),
+    /* Prevent further lock/unlock calls from this process */
+    VIR_LOCK_MANAGER_ACQUIRE_RESTRICT = (1 << 1),
 } virLockManagerAcquireFlags;
 
 enum {
index 7e0610d1bfcd79959963d19608e003a67a30d0fe..a60d7ce0f81cefb77eb6593eca32a45f655bda44 100644 (file)
@@ -240,7 +240,8 @@ static int virLockManagerSanlockAcquire(virLockManagerPtr lock,
     int rv;
     int i;
 
-    virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY, -1);
+    virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_RESTRICT |
+                  VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY, -1);
 
     if (priv->res_count == 0 &&
         priv->hasRWDisks) {
@@ -327,6 +328,18 @@ static int virLockManagerSanlockAcquire(virLockManagerPtr lock,
         virSetInherit(sock, true) < 0)
         goto error;
 
+    if (flags & VIR_LOCK_MANAGER_ACQUIRE_RESTRICT) {
+        if ((rv = sanlock_restrict(sock, SANLK_RESTRICT_ALL)) < 0) {
+            if (rv <= -200)
+                virLockError(VIR_ERR_INTERNAL_ERROR,
+                             _("Failed to restrict process: error %d"), rv);
+            else
+                virReportSystemError(-rv, "%s",
+                                     _("Failed to restrict process"));
+            goto error;
+        }
+    }
+
     VIR_DEBUG("Acquire completed fd=%d", sock);
 
     if (res_free) {