mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 19:11:16 +00:00
reject out of range memory in SetMemory APIs
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
This commit is contained in:
parent
07df9e1f74
commit
3511c12244
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -2334,6 +2334,7 @@ virIsSUID;
|
||||
virManageVport;
|
||||
virMemoryLimitIsSet;
|
||||
virMemoryLimitTruncate;
|
||||
virMemoryMaxValue;
|
||||
virParseNumber;
|
||||
virParseOwnershipIds;
|
||||
virParseVersionString;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user