From f00eabed8da80563b168f6bfe598018b3e89ee8e Mon Sep 17 00:00:00 2001 From: Bjoern Tropf Date: Sat, 6 Jun 2009 11:18:28 +0200 Subject: Move is_in_interval() to kernellib.py; Use dict for genpatches --- TODO | 49 +----------------- kernel-check.py | 8 +-- kernellib.py | 153 +++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 103 insertions(+), 107 deletions(-) diff --git a/TODO b/TODO index 61fee79..0ff31d5 100644 --- a/TODO +++ b/TODO @@ -1,15 +1,13 @@ Todo ==== - Fix all TODO markers -- Move is_in_interval to kernellib.py -- Use dict instead of list for genpatches - Create a vulnerability class Clean code ========== - Add more logging messages - Use more telling variables -- Rework Descriptions +- Rework Descriptions - Remove unused code/find better ways Documentation @@ -19,7 +17,7 @@ Documentation Future ====== -- Implement webserver for kernel-check +- Implement a webserver for kernel-check Intervall documentation @@ -51,46 +49,3 @@ expand: Boolean, defines whether the entry is shadowing less specific entries of a patch fixing the vulnerability has been backported to the genpatches. Kernels 2.6.17 and earlier are not affected. - -def is_in_interval(self, version): - """ Returns True if the given version is inside our specified interval, False otherwise. - Note: 'name' is discarded in the comparison. """ - if version == None: - return True - - if self.lower: # We actually have a lower boundary set - result = portage_versions.vercmp(version, self.lower) - if result == None: - raise BugError("Could not compare %s and %s" % (self.lower, version, str(self))) - - """" We check the lower boundary. Two things will lead to False: - (1) The Result is "equal" and the lower boundary is not inclusive - aka: version = 2.6.24 on "> 2.6.24" - (2) The Result is "lower": - aka: version = 2.6.18 on ">= 2.6.24" """ - if result == 0 and not self.lower_inclusive: - return False - if result == 0 and self.lower_inclusive: - return True - if result < 0: - return False - - if self.upper: # We actually have an upper boundary set - result = portage_versions.vercmp(version, self.upper) - if result == None: - raise BugError("Could not compare %s and %s" % (self.upper, version, str(self))) - - """" We check the upper boundary. Two things will lead to False: - (1) The Result is "equal" and the upper boundary is not inclusive - aka: version = 2.6.24 on "< 2.6.24" - (2) The Result is "lower": - aka: version = 2.6.24 on "<= 2.6.18" """ - if result == 0 and not self.upper_inclusive: - return False - if result == 0 and self.upper_inclusive: - return True - if result > 0: - return False - - # Seems we're outa luck, we fell into the vulnerable versions - return True diff --git a/kernel-check.py b/kernel-check.py index e5de4d3..c8f2019 100755 --- a/kernel-check.py +++ b/kernel-check.py @@ -28,8 +28,8 @@ def main(argv): KERNEL = lib.extract_version(os.uname()[2]) ARCH = os.uname()[4] - BEST = lib.best_version(KERNEL['source'] + '-sources') - CVE = [345, 284, 274, 0, 4] #TODO: Implement + BEST = lib.best_version(KERNEL['source']) + CVE = [345, 284, 274, 0, 4] #TODO: Implement + use dict! GENPATCH = lib.get_genpatch(lib.read_genpatch_file('out'), KERNEL) info = portage.output.EOutput().einfo @@ -60,13 +60,13 @@ def main(argv): if KERNEL: info('Kernel version: ' + color('GOOD', KERNEL['version'] + '-' + KERNEL['revision'])) - info('Kernel sources: ' + color('GOOD', KERNEL['source'] + '-sources')) + info('Kernel sources: ' + color('GOOD', KERNEL['source'])) else: error('No kernel information found!') sys.exit() if GENPATCH: - info('Integrated genpatch: ' + color('GOOD', GENPATCH[2] + ' ' + GENPATCH[3])) + info('Integrated genpatch: ' + color('GOOD', GENPATCH['version'] + ' ' + GENPATCH['want'])) else: warn('No genpatch information found!') diff --git a/kernellib.py b/kernellib.py index 463d77a..317142b 100755 --- a/kernellib.py +++ b/kernellib.py @@ -29,7 +29,7 @@ import re import urllib -regex = { +REGEX = { 'bugzilla' : re.compile(r'(?<=bug.cgi\?id=)\d*'), 'gpatches_v' : re.compile(r'(?<=K_GENPATCHES_VER\=\").+(?=\")'), 'gpatches_w' : re.compile(r'(?<=K_WANT_GENPATCHES\=\").+(?=\")'), @@ -45,11 +45,23 @@ regex = { 'rd' : re.compile(r'^r\d{1,3}$') } -logging.basicConfig(format='%(levelname)-6s[%(asctime)s] : %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) +GENERAL_KERNEL_TYPES = ['aa', 'acpi', 'ac', 'alpha', 'arm', 'as', 'cell', 'ck', 'compaq', 'crypto', + 'development', 'gaming','gentoo-dev', 'gentoo', 'gentoo-test', 'gfs', 'git', 'grsec', 'gs', + 'hardened-dev', 'hardened', 'hppa-dev', 'hppa', 'ia64', 'kurobox', 'linux', 'lolo', + 'mips-prepatch', 'mips', 'mjc', 'mm', 'mosix', 'openblocks', 'openmosix','openvz', 'pac', + 'pegasos-dev', 'pegasos', 'pfeifer', 'planet-ccrma', 'ppc64', 'ppc-development', 'ppc-dev', + 'ppc', 'redhat', 'rsbac-dev', 'rsbac', 'selinux', 'sh', 'sparc-dev', 'sparc', 'suspend2', + 'systrace', 'tuxonice', 'uclinux', 'usermode','vanilla-prepatch', 'vanilla', 'vanilla-tiny', + 'vserver-dev', 'vserver', 'win4lin', 'wolk-dev', 'wolk', 'xbox', 'xen', 'xfs'] + +GENTOO_KERNEL_TYPES = ['cell', 'mips', 'tuxonice', 'mm', 'usermode', 'gentoo', 'vanilla', 'git', + 'openvz', 'vserver', 'hardened', 'sh', 'xbox', 'sparc', 'xen'] VERBOSE = False FORCE = False +logging.basicConfig(format='%(levelname)-6s[%(asctime)s] : %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + def debug(msg): if VERBOSE: @@ -144,12 +156,18 @@ def parse_genpatch_list(directory): content = ebuild_file.read() try: - genpatch_v = regex['gpatches_v'].findall(content)[0] - genpatch_w = regex['gpatches_w'].findall(content)[0] + genpatch_v = REGEX['gpatches_v'].findall(content)[0] + genpatch_w = REGEX['gpatches_w'].findall(content)[0] except: break - genpatch = [pkg[1], pkg[2] + '_' + pkg[3] if pkg[3] != 'r0' else pkg[2], pkg[2] + '-' + genpatch_v, genpatch_w] + genpatch = { + 'source' : pkg[1], + 'pvr' : pkg[2] + '-' + pkg[3] if pkg[3] != 'r0' else pkg[2], + 'version' : pkg[2] + '-' + genpatch_v, + 'base' : True if 'base' in genpatch_w else False, + 'extras' : True if 'extras' in genpatch_w else False + } patches.append(genpatch) return patches @@ -158,26 +176,21 @@ def parse_genpatch_list(directory): def read_genpatch_file(directory): #TODO: Description + patches = list() filename = os.path.join(directory, 'genpatches.xml') with open(filename, 'r+') as xml_data: memory_map = mmap.mmap(xml_data.fileno(), 0) root = et.parse(memory_map).getroot() - patches = list() - for tree in root: - genpatch = [tree.get('source'), tree.get('pvr'), tree.get('version'), ''] - - #FIXME: Can be done easier - if tree.get('base') == 'true': - genpatch[3] = 'base' - if tree.get('extras') == 'true': - genpatch[3] = 'base extras' - else: - if tree.get('extras') == 'true': - genpatch[3] = 'extras' - + genpatch = { + 'source' : tree.get('source'), + 'pvr' : tree.get('pvr'), + 'version' : tree.get('version'), + 'base' : True if tree.get('base') == 'true' else False, + 'extras' : True if tree.get('extras') == 'true' else False + } patches.append(genpatch) return patches @@ -191,28 +204,30 @@ def write_genpatch_file(directory, genpatches): for item in genpatches: genpatch = et.SubElement(root, 'genpatch') - genpatch.set('source', item[0]) - genpatch.set('pvr', item[1]) - genpatch.set('version', item[2]) - if 'base' in item[3]: - genpatch.set('base', 'true') - else: - genpatch.set('base', 'false') - if 'extras' in item[3]: - genpatch.set('extras', 'false') - else: - genpatch.set('extras', 'true') + genpatch.set('source', item['source']) + genpatch.set('pvr', item['pvr']) + genpatch.set('version', item['version']) + genpatch.set('base', str(item['base']).lower()) + genpatch.set('extras', str(item['extras']).lower()) write_xml(root, filename) return + def get_genpatch(patches, kernel): #TODO: Description for item in patches: - if kernel['source'] + '-sources' == item[0]: - if kernel['version'] + '_' + kernel['revision'] == item[1]: + if kernel['source'] == item['source']: + if kernel['version'] + '-' + kernel['revision'] == item['pvr']: + #FIXME: This can be a lot easier + if item['base']: + item['want'] = 'base' + if item['extras']: + item['want'] = 'extras' + if item['base'] and item['extras']: + item['want'] = 'base extras' return item return None @@ -224,7 +239,7 @@ def parse_bugzilla_list(filename): with open(filename, 'r+') as buglist_file: memory_map = mmap.mmap(buglist_file.fileno(), 0) - buglist = regex['bugzilla'].findall(memory_map.read(-1)) + buglist = REGEX['bugzilla'].findall(memory_map.read(-1)) return buglist @@ -321,8 +336,8 @@ def extract_cves(string): cves = list() string = string.replace('CAN', 'CVE') - for (year, split_cves) in regex['groupall'].findall(string): - for cve in regex['groupsplit'].findall(split_cves): + for (year, split_cves) in REGEX['groupall'].findall(string): + for cve in REGEX['groupsplit'].findall(split_cves): cves.append('CVE-%s-%s' % (year, cve)) return cves @@ -483,6 +498,38 @@ class IntervalEntry: return intnode +#TODO: move 'if self.lower' and 'if self.upper' together +def is_in_interval(self, version): + 'Returns True if the given version is inside our specified interval, False otherwise.' + + if not version: + return True + + if self.lower: + if not portage_versions.vercmp(version, self.lower): + error("Could not compare %s and %s" % (self.lower, version, str(self))) + + if not result and not self.lower_inclusive: + return False + if not result and self.lower_inclusive: + return True + if result < 0: + return False + + if self.upper: + if not portage_versions.vercmp(version, self.upper): + error("Could not compare %s and %s" % (self.upper, version, str(self))) + + if not result and not self.upper_inclusive: + return False + if not result and self.upper_inclusive: + return True + if result > 0: + return False + + return True + + def from_whiteboard(whiteboard): 'Returns a list of intervals within a whiteboard string' @@ -500,7 +547,7 @@ def from_whiteboard(whiteboard): affected = list() while len(whiteboard.strip()) > 0: - match = regex['wb_match'].match(whiteboard) + match = REGEX['wb_match'].match(whiteboard) if not match: return False @@ -520,7 +567,7 @@ def from_whiteboard(whiteboard): wb['lower'] = vers1 wb['upper'] = vers1 - if not regex['wb_version'].match(vers1): + if not REGEX['wb_version'].match(vers1): return False elif comp2 or vers2: return False @@ -541,7 +588,7 @@ def from_whiteboard(whiteboard): elif char: return False - if version and not regex['wb_version'].match(version): + if version and not REGEX['wb_version'].match(version): return False affected.append(IntervalEntry(name, wb['lower'], wb['upper'], wb['lower_inc'], wb['upper_inc'], wb['expand'])) @@ -553,16 +600,7 @@ def from_whiteboard(whiteboard): def extract_version(release): 'Extracts revision, source and version out of a release tag' - kernel_types = ['aa', 'acpi', 'ac', 'alpha', 'arm', 'as', 'cell', 'ck', 'compaq', 'crypto', - 'development', 'gaming','gentoo-dev', 'gentoo', 'gentoo-test', 'gfs', 'git', 'grsec', 'gs', - 'hardened-dev', 'hardened', 'hppa-dev', 'hppa', 'ia64', 'kurobox', 'linux', 'lolo', - 'mips-prepatch', 'mips', 'mjc', 'mm', 'mosix', 'openblocks', 'openmosix','openvz', 'pac', - 'pegasos-dev', 'pegasos', 'pfeifer', 'planet-ccrma', 'ppc64', 'ppc-development', 'ppc-dev', - 'ppc', 'redhat', 'rsbac-dev', 'rsbac', 'selinux', 'sh', 'sparc-dev', 'sparc', 'suspend2', - 'systrace', 'tuxonice', 'uclinux', 'usermode','vanilla-prepatch', 'vanilla', 'vanilla-tiny', - 'vserver-dev', 'vserver', 'win4lin', 'wolk-dev', 'wolk', 'xbox', 'xen', 'xfs'] - - match = regex['version'].match(release) + match = REGEX['version'].match(release) if not match: return None @@ -571,22 +609,25 @@ def extract_version(release): revision = 'r0' for elem in (rest or '').split('-'): - if regex['rcd'].match(elem): + if REGEX['rcd'].match(elem): version += '_' + elem - elif regex['gitd'].match(elem): + elif REGEX['gitd'].match(elem): source = 'git' - revision = 'r' + regex['gitd'].match(elem).groups()[0] - elif regex['rd'].match(elem): + revision = 'r' + REGEX['gitd'].match(elem).groups()[0] + elif REGEX['rd'].match(elem): revision = elem - elif elem in kernel_types: - source = elem + elif elem in GENERAL_KERNEL_TYPES: + if elem in GENTOO_KERNEL_TYPES: + source = elem + '-sources' + else: + source = elem elif elem != '': error('Dropping unknown version component \'%s\', probably local tag.' % elem) kernel = { 'revision' : revision, 'source' : source, - 'version' : version, + 'version' : version } return kernel @@ -594,10 +635,10 @@ def extract_version(release): def best_version(source): - cp = 'sys-kernel/' + source + kernel = 'sys-kernel/' + source porttree = portage.db[portage.root]['porttree'] - best = porttree.dep_bestmatch(cp) + best = porttree.dep_bestmatch(kernel) return best[11:] -- cgit v1.2.3-65-gdbad