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:
Rafal Wojtczuk 2011-05-04 17:10:01 +02:00
parent d84289f983
commit 18e207cbc5
3 changed files with 44 additions and 31 deletions

View File

@ -96,8 +96,8 @@ class SystemState:
time.sleep(self.BALOON_DELAY)
niter = niter + 1
def refresh_meminfo(self, domid, val):
qmemman_algo.refresh_meminfo_for_domain(self.domdict[domid], val)
def refresh_meminfo(self, domid, untrusted_meminfo_key):
qmemman_algo.refresh_meminfo_for_domain(self.domdict[domid], untrusted_meminfo_key)
self.do_balance()
def is_balance_req_significant(self, memset_reqs, xenfree):

View File

@ -1,45 +1,58 @@
import string
def parse_meminfo(meminfo):
dict = {}
l1 = string.split(meminfo,"\n")
for i in l1:
l2 = string.split(i)
if len(l2) >= 2:
dict[string.rstrip(l2[0], ":")] = l2[1]
#untrusted meminfo size is taken from xenstore key, thus its size is limited
#so splits do not require excessive memory
def parse_meminfo(untrusted_meminfo):
untrusted_dict = {}
#split meminfo contents into lines
untrusted_lines = string.split(untrusted_meminfo,"\n")
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:
for i in ('MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal', 'SwapFree'):
val = int(dict[i])*1024
val = int(untrusted_meminfo[i])*1024
if (val < 0):
return None
dict[i] = val
ret = True
untrusted_meminfo[i] = val
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
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
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:
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
def refresh_meminfo_for_domain(dom, xenstore_key):
meminfo = parse_meminfo(xenstore_key)
dom.meminfo = meminfo
if meminfo is None:
def refresh_meminfo_for_domain(dom, untrusted_xenstore_key):
untrusted_meminfo = parse_meminfo(untrusted_xenstore_key)
if untrusted_meminfo is None:
dom.meminfo = None
return
if is_suspicious(dom):
#sanitize start
if is_meminfo_suspicious(dom, untrusted_meminfo):
#sanitize end
dom.meminfo = None
dom.mem_used = None
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']
def prefmem(dom):

View File

@ -49,11 +49,11 @@ class XS_Watcher:
global_lock.release()
def request(self, domain_id):
ret = self.handle.read('', get_req_node(domain_id))
if ret == None or ret == '':
untrusted_meminfo_key = self.handle.read('', get_req_node(domain_id))
if untrusted_meminfo_key == None or untrusted_meminfo_key == '':
return
global_lock.acquire()
system_state.refresh_meminfo(domain_id, ret)
system_state.refresh_meminfo(domain_id, untrusted_meminfo_key)
global_lock.release()
def watch_loop(self):