qmemman: prefix variables read from xenstore with "untrusted_"
Additionally move all already existing checks to an already existing is_meminfo_suspicious procedure.
This commit is contained in:
parent
d84289f983
commit
18e207cbc5
@ -96,8 +96,8 @@ class SystemState:
|
|||||||
time.sleep(self.BALOON_DELAY)
|
time.sleep(self.BALOON_DELAY)
|
||||||
niter = niter + 1
|
niter = niter + 1
|
||||||
|
|
||||||
def refresh_meminfo(self, domid, val):
|
def refresh_meminfo(self, domid, untrusted_meminfo_key):
|
||||||
qmemman_algo.refresh_meminfo_for_domain(self.domdict[domid], val)
|
qmemman_algo.refresh_meminfo_for_domain(self.domdict[domid], untrusted_meminfo_key)
|
||||||
self.do_balance()
|
self.do_balance()
|
||||||
|
|
||||||
def is_balance_req_significant(self, memset_reqs, xenfree):
|
def is_balance_req_significant(self, memset_reqs, xenfree):
|
||||||
|
@ -1,45 +1,58 @@
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
def parse_meminfo(meminfo):
|
#untrusted meminfo size is taken from xenstore key, thus its size is limited
|
||||||
dict = {}
|
#so splits do not require excessive memory
|
||||||
l1 = string.split(meminfo,"\n")
|
def parse_meminfo(untrusted_meminfo):
|
||||||
for i in l1:
|
untrusted_dict = {}
|
||||||
l2 = string.split(i)
|
#split meminfo contents into lines
|
||||||
if len(l2) >= 2:
|
untrusted_lines = string.split(untrusted_meminfo,"\n")
|
||||||
dict[string.rstrip(l2[0], ":")] = l2[1]
|
for untrusted_lines_iterator in untrusted_lines:
|
||||||
|
#split a single meminfo line into words
|
||||||
|
untrusted_words = string.split(untrusted_lines_iterator)
|
||||||
|
if len(untrusted_words) >= 2:
|
||||||
|
untrusted_dict[string.rstrip(untrusted_words[0], ":")] = untrusted_words[1]
|
||||||
|
|
||||||
|
return untrusted_dict
|
||||||
|
|
||||||
|
def is_meminfo_suspicious(dom, untrusted_meminfo):
|
||||||
|
ret = False
|
||||||
|
|
||||||
|
#check whether the required keys exist and are not negative
|
||||||
try:
|
try:
|
||||||
for i in ('MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal', 'SwapFree'):
|
for i in ('MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal', 'SwapFree'):
|
||||||
val = int(dict[i])*1024
|
val = int(untrusted_meminfo[i])*1024
|
||||||
if (val < 0):
|
if (val < 0):
|
||||||
return None
|
ret = True
|
||||||
dict[i] = val
|
untrusted_meminfo[i] = val
|
||||||
except:
|
except:
|
||||||
return None
|
|
||||||
|
|
||||||
if dict['SwapTotal'] < dict['SwapFree']:
|
|
||||||
return None
|
|
||||||
return dict
|
|
||||||
|
|
||||||
def is_suspicious(dom):
|
|
||||||
ret = False
|
|
||||||
if dom.meminfo['SwapTotal'] < dom.meminfo['SwapFree']:
|
|
||||||
ret = True
|
ret = True
|
||||||
if dom.meminfo['MemTotal'] < dom.meminfo['MemFree'] + dom.meminfo['Cached'] + dom.meminfo['Buffers']:
|
|
||||||
|
if not ret and untrusted_meminfo['SwapTotal'] < untrusted_meminfo['SwapFree']:
|
||||||
ret = True
|
ret = True
|
||||||
|
if not ret and untrusted_meminfo['MemTotal'] < untrusted_meminfo['MemFree'] + untrusted_meminfo['Cached'] + untrusted_meminfo['Buffers']:
|
||||||
|
ret = True
|
||||||
|
#we could also impose some limits on all the above values
|
||||||
|
#but it has little purpose - all the domain can gain by passing e.g.
|
||||||
|
#very large SwapTotal is that it will be assigned all free Xen memory
|
||||||
|
#it can be achieved with legal values, too, and it will not allow to
|
||||||
|
#starve existing domains, by design
|
||||||
if ret:
|
if ret:
|
||||||
print 'suspicious meminfo for domain', dom.id, 'mem actual', dom.memory_actual, dom.meminfo
|
print 'suspicious meminfo for domain', dom.id, 'mem actual', dom.memory_actual, untrusted_meminfo
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def refresh_meminfo_for_domain(dom, xenstore_key):
|
def refresh_meminfo_for_domain(dom, untrusted_xenstore_key):
|
||||||
meminfo = parse_meminfo(xenstore_key)
|
untrusted_meminfo = parse_meminfo(untrusted_xenstore_key)
|
||||||
dom.meminfo = meminfo
|
if untrusted_meminfo is None:
|
||||||
if meminfo is None:
|
dom.meminfo = None
|
||||||
return
|
return
|
||||||
if is_suspicious(dom):
|
#sanitize start
|
||||||
|
if is_meminfo_suspicious(dom, untrusted_meminfo):
|
||||||
|
#sanitize end
|
||||||
dom.meminfo = None
|
dom.meminfo = None
|
||||||
dom.mem_used = None
|
dom.mem_used = None
|
||||||
else:
|
else:
|
||||||
|
#sanitized, can assign
|
||||||
|
dom.meminfo = untrusted_meminfo
|
||||||
dom.mem_used = dom.meminfo['MemTotal'] - dom.meminfo['MemFree'] - dom.meminfo['Cached'] - dom.meminfo['Buffers'] + dom.meminfo['SwapTotal'] - dom.meminfo['SwapFree']
|
dom.mem_used = dom.meminfo['MemTotal'] - dom.meminfo['MemFree'] - dom.meminfo['Cached'] - dom.meminfo['Buffers'] + dom.meminfo['SwapTotal'] - dom.meminfo['SwapFree']
|
||||||
|
|
||||||
def prefmem(dom):
|
def prefmem(dom):
|
||||||
|
@ -49,11 +49,11 @@ class XS_Watcher:
|
|||||||
global_lock.release()
|
global_lock.release()
|
||||||
|
|
||||||
def request(self, domain_id):
|
def request(self, domain_id):
|
||||||
ret = self.handle.read('', get_req_node(domain_id))
|
untrusted_meminfo_key = self.handle.read('', get_req_node(domain_id))
|
||||||
if ret == None or ret == '':
|
if untrusted_meminfo_key == None or untrusted_meminfo_key == '':
|
||||||
return
|
return
|
||||||
global_lock.acquire()
|
global_lock.acquire()
|
||||||
system_state.refresh_meminfo(domain_id, ret)
|
system_state.refresh_meminfo(domain_id, untrusted_meminfo_key)
|
||||||
global_lock.release()
|
global_lock.release()
|
||||||
|
|
||||||
def watch_loop(self):
|
def watch_loop(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user