]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
reject out of range memory in SetMemory APIs
authorJán Tomko <jtomko@redhat.com>
Tue, 5 May 2015 15:58:49 +0000 (17:58 +0200)
committerJán Tomko <jtomko@redhat.com>
Thu, 14 May 2015 15:17:40 +0000 (17:17 +0200)
The APIs take the memory value in KiB and we store it in KiB
internally, but we cannot parse the whole ULONG_MAX range
on 64-bit systems, because virDomainParseScaledValue
needs to fit the value in bytes in an unsigned long long.

https://bugzilla.redhat.com/show_bug.cgi?id=1176739

src/conf/domain_conf.c
src/libvirt-domain.c
src/libvirt_private.syms
src/util/virutil.c
src/util/virutil.h

index 68cac1de01c974cb3c0599befd3d2edc8573531b..d150582897e92c93f76b2cc00acb5fc373c13f71 100644 (file)
@@ -7098,12 +7098,7 @@ virDomainParseMemory(const char *xpath,
     int ret = -1;
     unsigned long long bytes, max;
 
-    /* On 32-bit machines, our bound is 0xffffffff * KiB. On 64-bit
-     * machines, our bound is off_t (2^63).  */
-    if (capped && sizeof(unsigned long) < sizeof(long long))
-        max = 1024ull * ULONG_MAX;
-    else
-        max = LLONG_MAX;
+    max = virMemoryMaxValue(capped);
 
     ret = virDomainParseScaledValue(xpath, units_xpath, ctxt,
                                     &bytes, 1024, max, required);
index 7dcd40e4209449498bafb9de7c44020c84b5bb56..d4677581b4245888cad0600614abd77a0b662bdb 100644 (file)
@@ -1850,6 +1850,12 @@ virDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
     virCheckReadOnlyGoto(conn->flags, error);
     virCheckNonZeroArgGoto(memory, error);
 
+    if (virMemoryMaxValue(true) / 1024 <= memory) {
+        virReportError(VIR_ERR_OVERFLOW, _("input too large: %lu"),
+                       memory);
+        goto error;
+    }
+
     if (conn->driver->domainSetMaxMemory) {
         int ret;
         ret = conn->driver->domainSetMaxMemory(domain, memory);
@@ -1896,6 +1902,12 @@ virDomainSetMemory(virDomainPtr domain, unsigned long memory)
     virCheckReadOnlyGoto(conn->flags, error);
     virCheckNonZeroArgGoto(memory, error);
 
+    if (virMemoryMaxValue(true) / 1024 <= memory) {
+        virReportError(VIR_ERR_OVERFLOW, _("input too large: %lu"),
+                       memory);
+        goto error;
+    }
+
     if (conn->driver->domainSetMemory) {
         int ret;
         ret = conn->driver->domainSetMemory(domain, memory);
@@ -1953,6 +1965,12 @@ virDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
     virCheckReadOnlyGoto(conn->flags, error);
     virCheckNonZeroArgGoto(memory, error);
 
+    if (virMemoryMaxValue(true) / 1024 <= memory) {
+        virReportError(VIR_ERR_OVERFLOW, _("input too large: %lu"),
+                       memory);
+        goto error;
+    }
+
     if (conn->driver->domainSetMemoryFlags) {
         int ret;
         ret = conn->driver->domainSetMemoryFlags(domain, memory, flags);
index 67a7e21a204488f48e486dac28da0cb3c38ac740..6e33f84e493d2ce5332fcfc7b871b84f3220a0c0 100644 (file)
@@ -2334,6 +2334,7 @@ virIsSUID;
 virManageVport;
 virMemoryLimitIsSet;
 virMemoryLimitTruncate;
+virMemoryMaxValue;
 virParseNumber;
 virParseOwnershipIds;
 virParseVersionString;
index 042651703fa57e03aba2acdb9646581f0b5ba284..638d6e2166e64ae7815fc840bcd94bfa3e9cd465 100644 (file)
@@ -2598,3 +2598,23 @@ virMemoryLimitIsSet(unsigned long long value)
 {
     return value < VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 }
+
+
+/**
+ * virMemoryMaxValue
+ *
+ * @ulong: whether the value must fit into unsigned long
+ *   (long long is assumed otherwise)
+ *
+ * Returns the maximum possible memory value in bytes.
+ */
+unsigned long long
+virMemoryMaxValue(bool ulong)
+{
+    /* On 32-bit machines, our bound is 0xffffffff * KiB. On 64-bit
+     * machines, our bound is off_t (2^63).  */
+    if (ulong && sizeof(unsigned long) < sizeof(long long))
+        return 1024ull * ULONG_MAX;
+    else
+        return LLONG_MAX;
+}
index 55a3bd62217f21938e376ea6aa7cef5ca0dc8b50..c78b357b4367d61a5d52e3c6d7188489906d6f00 100644 (file)
@@ -245,5 +245,6 @@ long virGetSystemPageSizeKB(void);
 
 unsigned long long virMemoryLimitTruncate(unsigned long long value);
 bool virMemoryLimitIsSet(unsigned long long value);
+unsigned long long virMemoryMaxValue(bool ulong);
 
 #endif /* __VIR_UTIL_H__ */