Hi Guido

On Tue, Jul 12, 2011 at 11:24:26PM +0200, Guido Günther wrote:
> On Tue, Jul 12, 2011 at 12:29:14PM +0200, Salvatore Bonaccorso wrote:
> > Source: libvirt
> > Version: 0.9.2
> > Severity: important
> > Tags: security
> > 
> > Hi Guido
> > 
> > In [1] (CVE-2011-2511) an integer overflow in VirDomainGetVcpus for
> > libvirt is mentioned. This is fixed in new upstream 0.9.3. Here [2] is
> > the patch applied by upstream. Can/should there be an update to for
> > stable (if affected?).
> > 
> >  [1] http://www.securityfocus.com/bid/48478/info
> >  [2] https://www.redhat.com/archives/libvir-list/2011-June/msg01278.html
> >  [3] http://security-tracker.debian.org/CVE-2011-2511
> 
> Attached patch fixes the issue for stable. We should also fix #623222
> while at that. O.k. to upload a version to stable-security?

Wow thanks for you fast work :-). Note, I have only reported the issue
via BTS, but I'm not in security team. I'm Cc'ing this to the security
team list.

Regards
Salvatore
From 0b0d2cb2d5055991de4b6e979dc61148aaf097ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guido=20G=C3=BCnther?= <[email protected]>
Date: Tue, 12 Jul 2011 15:03:09 +0200
Subject: [PATCH 1/2] Fix integer overflow in VirDomainGetVcpus

Patch taken from upsteam. (CVE-2011-2511)

Closes: #633630
Gbp-Pq-Topic: security
---
 daemon/remote.c            |    4 ++-
 gnulib/lib/intprops.h      |   61 ++++++++++++++++++++++++++++++++++++++++++++
 src/libvirt.c              |    5 ++-
 src/remote/remote_driver.c |    4 ++-
 4 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 118654c..a163067 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -58,6 +58,7 @@
 #include "util.h"
 #include "stream.h"
 #include "libvirt/libvirt-qemu.h"
+#include "intprops.h"
 
 #define VIR_FROM_THIS VIR_FROM_REMOTE
 #define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
@@ -1695,7 +1696,8 @@ remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
         return -1;
     }
 
-    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
+    if (INT_MULTIPLY_OVERFLOW(args->maxinfo, args->maplen) ||
+        args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
         virDomainFree(dom);
         remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
         return -1;
diff --git a/gnulib/lib/intprops.h b/gnulib/lib/intprops.h
index 6c84df6..e842db1 100644
--- a/gnulib/lib/intprops.h
+++ b/gnulib/lib/intprops.h
@@ -82,4 +82,65 @@
    including the terminating null.  */
 # define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
 
+#define INT_MULTIPLY_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
+
+/* Return 1 if the expression A <op> B would overflow,
+   where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
+   assuming MIN and MAX are the minimum and maximum for the result type.
+   Arguments should be free of side effects.  */
+#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
+  op_result_overflow (a, b,                                     \
+                      _GL_INT_MINIMUM (0 * (b) + (a)),          \
+                      _GL_INT_MAXIMUM (0 * (b) + (a)))
+
+/* The maximum and minimum values for the type of the expression E,
+   after integer promotion.  E should not have side effects.  */
+#define _GL_INT_MINIMUM(e)                                              \
+  (_GL_INT_SIGNED (e)                                                   \
+   ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e)         \
+   : _GL_INT_CONVERT (e, 0))
+#define _GL_INT_MAXIMUM(e)                                              \
+  (_GL_INT_SIGNED (e)                                                   \
+   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
+   : _GL_INT_NEGATE_CONVERT (e, 1))
+#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
+  (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1)
+
+/* Return 1 if the integer expression E, after integer promotion, has
+   a signed type.  */
+#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+
+/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
+   <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>.  */
+#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
+
+/* Return an integer value, converted to the same type as the integer
+   expression E after integer type promotion.  V is the unconverted value.  */
+#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
+
+/* True if the signed integer expression E uses two's complement.  */
+#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1)
+
+#define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
+  (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
+   || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
+
+/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Avoid && and || as they tickle
+   bugs in Sun C 5.11 2010/08/13 and other compilers; see
+   <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>.  */
+#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
+  ((b) < 0                                              \
+   ? ((a) < 0                                           \
+      ? (a) < (max) / (b)                               \
+      : (b) == -1                                       \
+      ? 0                                               \
+      : (min) / (b) < (a))                              \
+   : (b) == 0                                           \
+   ? 0                                                  \
+   : ((a) < 0                                           \
+      ? (a) < (min) / (b)                               \
+      : (max) / (b) < (a)))
+
 #endif /* GL_INTPROPS_H */
diff --git a/src/libvirt.c b/src/libvirt.c
index 5e5a758..6981852 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -39,6 +39,7 @@
 #include "uuid.h"
 #include "util.h"
 #include "memory.h"
+#include "intprops.h"
 
 #ifndef WITH_DRIVER_MODULES
 # ifdef WITH_TEST
@@ -5218,8 +5219,8 @@ virDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
 
     /* Ensure that domainGetVcpus (aka remoteDomainGetVcpus) does not
        try to memcpy anything into a NULL pointer.  */
-    if ((cpumaps == NULL && maplen != 0)
-        || (cpumaps && maplen <= 0)) {
+    if (!cpumaps ? maplen != 0
+        : (maplen <= 0 || INT_MULTIPLY_OVERFLOW(maxinfo, maplen))) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
         goto error;
     }
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 5fab9c1..11b2e21 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -82,6 +82,7 @@
 #include "util.h"
 #include "event.h"
 #include "ignore-value.h"
+#include "intprops.h"
 
 #define VIR_FROM_THIS VIR_FROM_REMOTE
 
@@ -2500,7 +2501,8 @@ remoteDomainGetVcpus (virDomainPtr domain,
                     maxinfo, REMOTE_VCPUINFO_MAX);
         goto done;
     }
-    if (maxinfo * maplen > REMOTE_CPUMAPS_MAX) {
+    if (INT_MULTIPLY_OVERFLOW(maxinfo, maplen) ||
+        maxinfo * maplen > REMOTE_CPUMAPS_MAX) {
         remoteError(VIR_ERR_RPC,
                     _("vCPU map buffer length exceeds maximum: %d > %d"),
                     maxinfo * maplen, REMOTE_CPUMAPS_MAX);
-- 
1.7.5.4

Attachment: signature.asc
Description: Digital signature

Reply via email to