CVE-2011-2511 Fix integer overflow in VirDomainGetVcpus
Closes: #633630
Guido Günther
12 years ago
0 | From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org> | |
1 | Date: Tue, 12 Jul 2011 15:03:09 +0200 | |
2 | Subject: Fix integer overflow in VirDomainGetVcpus | |
3 | ||
4 | Patch taken from upsteam. (CVE-2011-2511) | |
5 | ||
6 | Closes: #633630 | |
7 | --- | |
8 | daemon/remote.c | 4 ++- | |
9 | gnulib/lib/intprops.h | 61 ++++++++++++++++++++++++++++++++++++++++++++ | |
10 | src/libvirt.c | 5 ++- | |
11 | src/remote/remote_driver.c | 4 ++- | |
12 | 4 files changed, 70 insertions(+), 4 deletions(-) | |
13 | ||
14 | diff --git a/daemon/remote.c b/daemon/remote.c | |
15 | index a8258ca..4c45044 100644 | |
16 | --- a/daemon/remote.c | |
17 | +++ b/daemon/remote.c | |
18 | @@ -58,6 +58,7 @@ | |
19 | #include "util.h" | |
20 | #include "stream.h" | |
21 | #include "libvirt/libvirt-qemu.h" | |
22 | +#include "intprops.h" | |
23 | ||
24 | #define VIR_FROM_THIS VIR_FROM_REMOTE | |
25 | #define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__) | |
26 | @@ -1697,7 +1698,8 @@ remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, | |
27 | return -1; | |
28 | } | |
29 | ||
30 | - if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) { | |
31 | + if (INT_MULTIPLY_OVERFLOW(args->maxinfo, args->maplen) || | |
32 | + args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) { | |
33 | virDomainFree(dom); | |
34 | remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX")); | |
35 | return -1; | |
36 | diff --git a/gnulib/lib/intprops.h b/gnulib/lib/intprops.h | |
37 | index 6c84df6..e842db1 100644 | |
38 | --- a/gnulib/lib/intprops.h | |
39 | +++ b/gnulib/lib/intprops.h | |
40 | @@ -82,4 +82,65 @@ | |
41 | including the terminating null. */ | |
42 | # define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) | |
43 | ||
44 | +#define INT_MULTIPLY_OVERFLOW(a, b) \ | |
45 | + _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) | |
46 | + | |
47 | +/* Return 1 if the expression A <op> B would overflow, | |
48 | + where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, | |
49 | + assuming MIN and MAX are the minimum and maximum for the result type. | |
50 | + Arguments should be free of side effects. */ | |
51 | +#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ | |
52 | + op_result_overflow (a, b, \ | |
53 | + _GL_INT_MINIMUM (0 * (b) + (a)), \ | |
54 | + _GL_INT_MAXIMUM (0 * (b) + (a))) | |
55 | + | |
56 | +/* The maximum and minimum values for the type of the expression E, | |
57 | + after integer promotion. E should not have side effects. */ | |
58 | +#define _GL_INT_MINIMUM(e) \ | |
59 | + (_GL_INT_SIGNED (e) \ | |
60 | + ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \ | |
61 | + : _GL_INT_CONVERT (e, 0)) | |
62 | +#define _GL_INT_MAXIMUM(e) \ | |
63 | + (_GL_INT_SIGNED (e) \ | |
64 | + ? _GL_SIGNED_INT_MAXIMUM (e) \ | |
65 | + : _GL_INT_NEGATE_CONVERT (e, 1)) | |
66 | +#define _GL_SIGNED_INT_MAXIMUM(e) \ | |
67 | + (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1) | |
68 | + | |
69 | +/* Return 1 if the integer expression E, after integer promotion, has | |
70 | + a signed type. */ | |
71 | +#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) | |
72 | + | |
73 | +/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see | |
74 | + <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>. */ | |
75 | +#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v)) | |
76 | + | |
77 | +/* Return an integer value, converted to the same type as the integer | |
78 | + expression E after integer type promotion. V is the unconverted value. */ | |
79 | +#define _GL_INT_CONVERT(e, v) (0 * (e) + (v)) | |
80 | + | |
81 | +/* True if the signed integer expression E uses two's complement. */ | |
82 | +#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1) | |
83 | + | |
84 | +#define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ | |
85 | + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ | |
86 | + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) | |
87 | + | |
88 | +/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. | |
89 | + See above for restrictions. Avoid && and || as they tickle | |
90 | + bugs in Sun C 5.11 2010/08/13 and other compilers; see | |
91 | + <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */ | |
92 | +#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ | |
93 | + ((b) < 0 \ | |
94 | + ? ((a) < 0 \ | |
95 | + ? (a) < (max) / (b) \ | |
96 | + : (b) == -1 \ | |
97 | + ? 0 \ | |
98 | + : (min) / (b) < (a)) \ | |
99 | + : (b) == 0 \ | |
100 | + ? 0 \ | |
101 | + : ((a) < 0 \ | |
102 | + ? (a) < (min) / (b) \ | |
103 | + : (max) / (b) < (a))) | |
104 | + | |
105 | #endif /* GL_INTPROPS_H */ | |
106 | diff --git a/src/libvirt.c b/src/libvirt.c | |
107 | index 5e5a758..6981852 100644 | |
108 | --- a/src/libvirt.c | |
109 | +++ b/src/libvirt.c | |
110 | @@ -39,6 +39,7 @@ | |
111 | #include "uuid.h" | |
112 | #include "util.h" | |
113 | #include "memory.h" | |
114 | +#include "intprops.h" | |
115 | ||
116 | #ifndef WITH_DRIVER_MODULES | |
117 | # ifdef WITH_TEST | |
118 | @@ -5218,8 +5219,8 @@ virDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, | |
119 | ||
120 | /* Ensure that domainGetVcpus (aka remoteDomainGetVcpus) does not | |
121 | try to memcpy anything into a NULL pointer. */ | |
122 | - if ((cpumaps == NULL && maplen != 0) | |
123 | - || (cpumaps && maplen <= 0)) { | |
124 | + if (!cpumaps ? maplen != 0 | |
125 | + : (maplen <= 0 || INT_MULTIPLY_OVERFLOW(maxinfo, maplen))) { | |
126 | virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); | |
127 | goto error; | |
128 | } | |
129 | diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c | |
130 | index 5fab9c1..11b2e21 100644 | |
131 | --- a/src/remote/remote_driver.c | |
132 | +++ b/src/remote/remote_driver.c | |
133 | @@ -82,6 +82,7 @@ | |
134 | #include "util.h" | |
135 | #include "event.h" | |
136 | #include "ignore-value.h" | |
137 | +#include "intprops.h" | |
138 | ||
139 | #define VIR_FROM_THIS VIR_FROM_REMOTE | |
140 | ||
141 | @@ -2500,7 +2501,8 @@ remoteDomainGetVcpus (virDomainPtr domain, | |
142 | maxinfo, REMOTE_VCPUINFO_MAX); | |
143 | goto done; | |
144 | } | |
145 | - if (maxinfo * maplen > REMOTE_CPUMAPS_MAX) { | |
146 | + if (INT_MULTIPLY_OVERFLOW(maxinfo, maplen) || | |
147 | + maxinfo * maplen > REMOTE_CPUMAPS_MAX) { | |
148 | remoteError(VIR_ERR_RPC, | |
149 | _("vCPU map buffer length exceeds maximum: %d > %d"), | |
150 | maxinfo * maplen, REMOTE_CPUMAPS_MAX); | |
151 | -- |