summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Buchholz <rbu@goodpoint.de>2008-08-29 20:40:54 +0200
committerRobert Buchholz <rbu@goodpoint.de>2008-08-29 20:40:54 +0200
commit00ce1e9495bab0d5009b834082235f0f2bc361da (patch)
tree96097bc031ea97295c62ad81d39521c0799b84d9
downloadkernel-check-00ce1e9495bab0d5009b834082235f0f2bc361da.tar.gz
kernel-check-00ce1e9495bab0d5009b834082235f0f2bc361da.tar.bz2
kernel-check-00ce1e9495bab0d5009b834082235f0f2bc361da.zip
Initial version of KISS2
-rw-r--r--example.xml19
l---------gentoo_sources_web.pm1
-rwxr-xr-xkiss2.py474
-rw-r--r--kiss_xml.py16
-rw-r--r--kissoutput.py156
-rw-r--r--kissoutput_new.py74
-rwxr-xr-xmake_kernels.pl29
-rw-r--r--out.xml17
-rwxr-xr-xupdatesite6
9 files changed, 792 insertions, 0 deletions
diff --git a/example.xml b/example.xml
new file mode 100644
index 0000000..f0b0a92
--- /dev/null
+++ b/example.xml
@@ -0,0 +1,19 @@
+
+
+<bug>
+ <id>221123</id>
+ <title><![CDATA[ Linux Kernels 2.6.22->2.6.25.2 - utimensat() file time modification bypass vulnerability (CVE-2008-2148) ]]></title>
+ <cve>
+ <id>CVE-2008-2148</id>
+ <desc><![CDATA[ The utimensat system call (sys_utimensat) in Linux kernel 2.6.22 and other versions before 2.6.25.3 does not check file permissions when certain UTIME_NOW and UTIME_OMIT combinations are used, which allows local users to modify file times of arbitrary files, possibly leading to a denial of service. ]]></desc>
+ </cve>
+ <url>http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git;a=blob;f=review-2.6.25/vfs-fix-permission-checking-in-sys_utimensat.patch;h=1da0b9bf9f078e3eb147a6799e5a74af2484014a;hb=cbe22288b271b4e4e51f5573281662f53466e41a</url>
+ <arch>All</arch>
+ <severity>normal</severity>
+ <affected>
+ <interval source="linux">
+ <lower inclusive="true">2.6.22</lower>
+ <upper inclusive="false">2.6.25.2</upper>
+ </interval>
+ </affected>
+</bug>
diff --git a/gentoo_sources_web.pm b/gentoo_sources_web.pm
new file mode 120000
index 0000000..e6886e5
--- /dev/null
+++ b/gentoo_sources_web.pm
@@ -0,0 +1 @@
+../gentoo_sources_web.pm \ No newline at end of file
diff --git a/kiss2.py b/kiss2.py
new file mode 100755
index 0000000..9ede7b6
--- /dev/null
+++ b/kiss2.py
@@ -0,0 +1,474 @@
+#!/usr/bin/python
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# Written by Robert Buchholz <rbu@gentoo.org>
+
+import string
+import sys
+import os
+import portage
+import portage_versions
+import re
+
+genpatcheslist="./output/genpversions.txt"
+
+"""
+Bugzilla Kernel Version specification
+
+The whiteboard field on the bug should be used to specify the vulnerable
+versions of all kernel sources for this bug. A bug can affect a package in three
+ways (and can therefore be fixed in three ways):
+ (1) by affecting the kernel.org release ("linux"),
+ (2) by affecting a certian set of Gentoo Patchsets ("gp")
+ (3) by affecting a specific set of Gentoo kernel sources ("*-sources").
+
+The priorities of these levels override each other with 3 having the highest
+priority (2 second and 1 lowest). Note that priority does not mean severity of
+the bug. Rather, the priority level is a scale of generality with 1 having the
+highest generality. A whiteboard entry of the type [linux] affects all kernels
+based off that version until a higher priority entry is added.
+
+Higher levels (2, 3) should normally only mark unaffected versions that are
+affected in lower levels. To override this and expand the "affected" interval
+over the boundaries giving by lower levels, version specifiers should be
+prefixed with a "+".
+
+Intervals specify the affected versions and can, for each level, be specified
+open (with upper or lower boundary only), or closed, either inclusive or not.
+Spaces are discarded.
+
+The order in which interval are specified is irrelevant.
+
+Examples:
+ [linux > 2.6] -- means all Linux releases since 2.6 are affected
+ [linux < 2.6.24.3] -- means all Linux versions prior to 2.6.24.3 are affected.
+ [linux >= 2.6.24 < 2.6.24.3] -- means all Linux versions greater than, and
+ including, 2.6.24, except if they are equal or greater than .3
+
+
+Complex examples:
+ [linux >= 2.6.18 < 2.6.24.3] [gp < 2.6.23-8]
+ This means: affected is every kernel based on a linux release higher/equal than
+ 2.6.18, but not those based on 2.6.24.3 or later. Kernels using a genpatches
+ version 2.6.23-8 or later are also not affected. 2.6.17 or earlier kernels
+ using genpatches are not affected.
+
+ [linux >= 2.6.18 < 2.6.24.3] [gp +< 2.6.23-8]
+ Same as before, except even 2.6.17 and earlier genpatched kernerls are also
+ affected (because of the +).
+
+ [linux >= 2.6.18 < 2.6.24.3] [gp >= 2.6.15 +<= 2.6.23-8]
+ Similar to the previous example, except kernels using genpatches are
+ affected from versions 2.6.15 (inclusive) up to 2.6.23-8 (inclusive).
+
+ [linux >= 2.6.18] [gp >= 2.6.23 < 2.6.23-8] [gp < 2.6.22-10]
+ All Linuxes since 2.6.18, unaffected are all Genpatched kernels between
+ 2.6.22-10 and (not including) 2.6.23, plus those after 2.6.23-8.
+
+ [linux >= 2.6.18 < 2.6.24.3] [gp < 2.6.23-8] [xen < 2.6.18-r9] [xen >= 2.6.19]
+ Same as the first example, except the 2.6.18 series of xen-kernels was fixed in 2.6.18-r9.
+
+
+"""
+
+class BugError(Exception):
+ def __init__(self, message, bug = None):
+ self.message = message
+ self.bug = bug
+ def __str__(self):
+ return repr(self.message)
+
+class SourcesError(Exception):
+ def __init__(self, message, ebuild):
+ self.message = message
+ self.ebuild = ebuild
+ def __str__(self):
+ return repr(self.message)
+
+class KernelAtom:
+ def __init__(self, name, version, release, gpver = None, has_base = None, has_extra = None, keywords = ""):
+ self.name = name
+ self.version = version
+ self.release = release
+ self.gpver = gpver
+ self.has_base = has_base
+ self.has_extra = has_extra
+ self.keywords = keywords
+
+ self.affected_by = []
+
+ def __repr__(self):
+ if self.gpver:
+ return "%s-%s,\tRelease: %s,\tGenpatches: %s\t(Base: %s,\tExtra: %s) " % (self.name, self.version, self.release, self.gpver, self.has_base, self.has_extra)
+ else:
+ return "%s-%s,\tRelease: %s,\tGenpatches: No" % (self.name, self.version, self.release)
+
+class SecurityMatrix:
+ def __init__(self):
+ self.localtree = portage.portagetree()
+
+ self.fill_genpatches()
+ self.kernel_atoms = []
+ self.fill_kernel_atoms()
+
+ supported_kernels=( "gentoo-sources",
+ "hardened-sources",
+ "tuxonice-sources",
+ "openvz-sources",
+ "usermode-sources",
+ "xen-sources",
+ "cell-sources",
+ "hppa-sources",
+ "mips-sources",
+ "rsbac-sources",
+ "sparc-sources")
+ # "vserver-sources",
+
+ unsupported_kernels=("git-sources",
+ "mm-sources",
+ "sh-sources",
+ "xbox-sources",
+ "vanilla-sources")
+
+
+
+
+ def fill_genpatches(self):
+ """ Read the genpatch'd kernels from a file and prepare KernelAtom objects for them. """
+ file = open(genpatcheslist)
+ kernelatoms = {}
+ for line in file:
+ splitline = line.strip().split(':')
+ if len(splitline) != 4:
+ print "Error reading line: %s" % (line)
+ else:
+ name = splitline[0]
+ version = splitline[1]
+ release = release_for_version(splitline[1])
+ gpver = splitline[2]
+ has_base = splitline[3].find("base") != -1
+ has_extra = splitline[3].find("extra") != -1
+ cpv = "sys-kernel/%s-%s" % (name, version)
+ atom = KernelAtom(name, version, release, gpver, has_base, has_extra, self.get_keywords_for(cpv))
+ kernelatoms[cpv] = atom
+ file.close()
+ self.genpatches = kernelatoms
+
+ def fill_kernel_atoms(self):
+ """ Fills the kernel atoms list will all kernel CPV's in the tree """
+ for source in self.supported_kernels:
+ cp = "sys-kernel/%s" % (source)
+ all_cpvs = self.localtree.dbapi.cp_list(cp)
+ for cpv in all_cpvs:
+ self.build_and_add_kernelatom(cpv)
+ for source in self.unsupported_kernels:
+ cp = "sys-kernel/%s" % (source)
+ all_cpvs = self.localtree.dbapi.cp_list(cp)
+ for cpv in all_cpvs:
+ self.build_and_add_kernelatom(cpv)
+
+ def build_and_add_kernelatom(self, cpv):
+ """ Build a KernelAtom object with the given cpv string and add it to our list of atoms """
+ if self.genpatches.has_key(cpv):
+ self.kernel_atoms.append(self.genpatches[cpv])
+ else:
+ cpvr = portage_versions.catpkgsplit(cpv)
+ if len(cpvr) != 4:
+ return
+ v = cpvr[2]
+ if cpvr[3] != "r0":
+ v = "%s-%s" % (cpvr[2], cpvr[3])
+ cpv = "%s/%s-%s" % (cpvr[0], cpvr[1], v)
+ new_atom = KernelAtom(cpvr[1], v, release_for_version(cpvr[2]), keywords = self.get_keywords_for(cpv))
+ self.kernel_atoms.append(new_atom)
+
+ def get_keywords_for(self, cpv):
+ try:
+ result = self.localtree.dbapi.aux_get(cpv, ("KEYWORDS",))
+ if result != None and len(result) == 1:
+ return result[0]
+ except:
+ pass
+ #TODO: raise SourcesError here
+ return ""
+
+ def check_bug(self, bug):
+ if len(bug.affected) == 0:
+ raise BugError("No intervals for affected kernel versions were found.", bug)
+ for ka in self.kernel_atoms:
+ if bug.affects(ka):
+ ka.affected_by.append(bug)
+
+
+def release_for_version(version):
+ """ Given an ebuild version, gives the Kernel release it is probably based upon.
+ Examples: 2.6.23-r3 -> 2.6.23
+ 2.6.23.12 -> 2.6.23.12
+ 2.6.23 -> 2.6.23
+ 2.6.25_rc5 -> 2.6.25_rc5
+ moo -> None """
+ matcher = re.compile("(\d\.\d+\.\d+(:?\.\d+)?(:?_rc\d+)?)")
+ match = matcher.match(version)
+ if not match:
+ # TODO: raise SourcesError in caller
+ return None
+ else:
+ return match.group(1)
+
+
+class IntervalEntry:
+ """ Defines """
+ def __init__(self, name, lower_inclusive, upper_inclusive, lower, upper, expand, bug):
+ if name == "gp":
+ name = "genpatches"
+ elif name != "linux" and name != "genpatches" and name[-7:] != "sources":
+ name = "%s-sources" % (name)
+ self.name = name # string, describing the package
+ self.lower_inclusive = lower_inclusive # Defines whether the lower boundary is inclusive
+ self.upper_inclusive = upper_inclusive # Defines whether the upper boundary is inclusive
+ if name == "genpatches":
+ self.lower = dashdot(lower) # Lower boundary
+ self.upper = dashdot(upper) # Upper boundary
+ else:
+ self.lower = lower # Lower boundary
+ self.upper = upper # Upper boundary
+
+ self.expand = expand # Defines whether the entry is expanding "lower" entries
+ self.bug = bug
+
+ def __repr__(self):
+ val = "%s " % (self.name)
+ if self.expand:
+ val += "+"
+ if self.lower and self.lower_inclusive:
+ val += ">=%s " % (self.lower)
+ if self.lower and not self.lower_inclusive:
+ val += ">%s " % (self.lower)
+ if self.upper and self.upper_inclusive:
+ val += "<=%s" % (self.upper)
+ if self.upper and not self.upper_inclusive:
+ val += "<%s" % (self.upper)
+ return val
+
+ 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 # TODO: why?
+
+ 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, on %s" % (self.lower, version, str(self)), self.bug)
+
+ """" 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, on %s" % (self.upper, version, str(self)), self.bug)
+
+ """" 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
+
+
+class Bug:
+ def __init__(self, bugno, title = "", severity = "normal", affected = ()):
+ self.bugno = bugno
+ self.title = title
+ self.severity = severity
+ self.affected = affected #(Entry("linux", "<", "2.6.23"),Entry("gp", "<", "2.6.20-14"),Entry("hardened", ">", "2.6"))
+
+ def affects(self, kernelatom):
+ """ Returns True if this bug affects the given KernelAtom, False otherwise. """
+ affected = False
+ linux_empty = True
+ for entry in self.affected:
+ if entry.name == "linux":
+ linux_empty = False
+ # Our linux base version is affected if it falls into any of the intervals
+ affected = affected or entry.is_in_interval(dashdot(kernelatom.release))
+
+ if kernelatom.gpver:
+ genpatches_affected = False
+ genpatches_exist = False
+ for entry in self.affected:
+ if entry.name == "gp" or entry.name == "genpatches":
+ genpatches_exist = True
+ if entry.is_in_interval(dashdot(kernelatom.gpver)):
+ # Our genpatches version is within the affected Genpatches.
+ genpatches_affected = True
+ if linux_empty:
+ affected = True
+ #elif affected:
+ # affected = True
+ elif not affected and entry.expand:
+ affected = True
+ #elif not affected and not entry.expand:
+ # affected = False
+ if affected and genpatches_exist and not genpatches_affected:
+ # We went through all the genpatches entries, but none marked this affected
+ affected = False
+
+ entry_affected = False
+ entry_exist = False
+ for entry in self.affected:
+ if entry.name == kernelatom.name:
+ entry_exist = True
+ if entry.is_in_interval(kernelatom.version):
+ # Our entry version is within the affected entry range.
+ entry_affected = True
+ if linux_empty:
+ affected = True
+ #elif affected:
+ # affected = True
+ elif not affected and entry.expand:
+ affected = True
+ #elif not affected and not entry.expand:
+ # affected = False
+ if affected and entry_exist and not entry_affected:
+ # We went through all the entries, but none marked this affected
+ affected = False
+ return affected
+
+ def set_from_whiteboard(self, whiteboard):
+ """ Set the Bug's values given reading a Status Whiteboard string from a Bug. """
+ if whiteboard == None:
+ raise BugError("Whiteboard empty")
+ rest = whiteboard
+ affected = []
+ matcher = re.compile("\s*\[\s*([^ +<=>]+)\s*(\+?[<=>]{1,2})\s*([^ +<=>\]]+)\s*(?:(\+?[<=>]{1,2})\s*([^ \]]+))?\s*\]\s*(.*)")
+
+ while len(rest.strip()) > 0:
+ match = matcher.match(rest)
+ if not match:
+ raise Exception("Illegal whiteboard: '%s'" % (rest))
+
+ name = match.group(1)
+ comp1 = match.group(2)
+ vers1 = match.group(3)
+ comp2 = match.group(4)
+ vers2 = match.group(5)
+ rest = match.group(6)
+
+ # calculate entry values
+ expand = False
+ upper_inclusive = None
+ upper = None
+ lower_inclusive = None
+ lower = None
+
+ if comp1[0] == "+":
+ comp1 = comp1[1:]
+ expand = True
+ if comp2 != None and comp2[0] == "+":
+ comp2 = comp2[1:]
+ expand = True
+
+ if comp1 == "=" or comp1 == "==":
+ lower_inclusive = True
+ upper_inclusive = True
+ lower = vers1
+ upper = vers1
+ for (c, v) in ((comp1, vers1), (comp2, vers2)):
+ if c == "<":
+ upper_inclusive = False
+ upper = v
+ elif c == "<=" or c == "=<" :
+ upper_inclusive = True
+ upper = v
+ elif c == ">":
+ lower_inclusive = False
+ lower = v
+ elif c == ">=" or c == "=>" :
+ lower_inclusive = True
+ lower = v
+ affected.append(IntervalEntry(name, lower_inclusive, upper_inclusive, lower, upper, expand, self))
+ self.affected = affected
+
+
+ def __repr__(self):
+ return str(self.bugno)
+
+class Bugzilla:
+ def __init__(self):
+ import bugz
+ self.bz = bugz.Bugz(base = "https://bugs.gentoo.org")
+
+ # search bugzilla for kernel bugs
+ self.bugs_raw = self.bz.search("", product = ("Gentoo Security",),
+ component = ("Kernel",),
+ status = ('NEW', 'ASSIGNED', 'REOPENED'))
+
+ self.bugs = []
+ self.failed_bugs = []
+ for bug_raw in self.bugs_raw:
+ bugid = bug_raw['bugid']
+
+ bug_xml = self.bz.get(bugid)
+ bug = Bug(bugid, bug_raw['desc'], bug_raw['severity'])
+ try:
+ bug.set_from_whiteboard(bug_xml.find('//status_whiteboard').text)
+ self.bugs.append(bug)
+ except:
+ #print sys.exc_value
+ self.failed_bugs.append(bug)
+
+
+def dashdot(s):
+ if s == None:
+ return None
+ return s.replace("-",".")
+
+
+
+def main():
+ m = SecurityMatrix()
+ b = Bugzilla()
+
+ bug_errors = []
+ for bug in b.failed_bugs:
+ bug_errors.append(BugError("No whiteboard status set.", bug))
+ succeeded_bugs = []
+
+ for bug in b.bugs:
+ try:
+ m.check_bug(bug)
+ succeeded_bugs.append(bug)
+ except BugError, b_ex:
+ bug_errors.append(b_ex)
+
+ import kissoutput
+ kissoutput.write_xml("./out.xml", m, bug_errors, succeeded_bugs)
+
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ print '\n ! Exiting.'
+
diff --git a/kiss_xml.py b/kiss_xml.py
new file mode 100644
index 0000000..9cc3857
--- /dev/null
+++ b/kiss_xml.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# Written by Robert Buchholz <rbu@gentoo.org>
+import elementtree.ElementTree as ET
+
+
+
+tree = ET.parse("example.xml")
+root = tree.getroot()
+
+print root.getchildren()
+
+tree.write("out.xml")
+
diff --git a/kissoutput.py b/kissoutput.py
new file mode 100644
index 0000000..bd738ea
--- /dev/null
+++ b/kissoutput.py
@@ -0,0 +1,156 @@
+#!/usr/bin/python
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# Written by Robert Buchholz <rbu@gentoo.org>
+
+import string
+import sys
+import os
+import re
+import cgi
+
+def buglink(bugno):
+ return "<uri link='https://bugs.gentoo.org/%s'>%s</uri>" % (bugno, bugno)
+
+def cvelink(text):
+ import re
+ return re.sub("(CVE-\d{4}-\d{4})", "<uri link='http://cve.mitre.org/cgi-bin/cvename.cgi?name=\\1'>\\1</uri>", text)
+
+
+def write_xml(filename, matrix, failures = (), successes = ()):
+ import datetime
+ file = open(filename, 'w+')
+ file.write('''<?xml version='1.0' encoding="UTF-8"?>
+<!DOCTYPE guide SYSTEM "/dtd/guide.dtd">
+<guide link="proj/en/security/kernel.xml">
+<title>Security - Kernel Bug Status</title>
+<author title="Author">
+ <mail link="kern-sec@gentoo.org">Kernel Security Team</mail>
+</author>
+
+<abstract>
+Display Kernel security.
+</abstract>
+
+<!-- The content of this document is licensed under the CC-BY-SA license -->
+<!-- See http://creativecommons.org/licenses/by-sa/1.0 -->
+<license/>
+
+<version>0.1</version>
+''')
+ file.write("<date>%s</date>" % (datetime.date.today()))
+
+ file.write('''
+<chapter>
+<title>Supported Kernel Sources</title>
+''')
+
+ for source in matrix.supported_kernels:
+ file.write("<section><title>%s</title>" % (source))
+ file.write('''
+<body>
+<table>
+<tr>
+<th>Version</th>
+<th>Genpatches</th>
+<th>Keywords</th>
+<th>Unfixed Bugs</th>
+</tr>
+''')
+
+ for kernel in matrix.kernel_atoms:
+ if kernel.name == source:
+ file.write("<tr><ti>%s</ti><ti>%s</ti><ti>%s</ti><ti>%s</ti></tr>" % (kernel.version, kernel.gpver, kernel.keywords, kernel.affected_by))
+ file.write('''
+</table>
+</body>
+</section>
+''')
+ file.write('''
+</chapter>''')
+
+ file.write('''
+<chapter>
+<title>Unsupported Kernel Sources</title>
+''')
+
+ for source in matrix.unsupported_kernels:
+ file.write("<section><title>%s</title>" % (source))
+ file.write('''
+<body>
+<table>
+<tr>
+<th>Version</th>
+<th>Genpatches</th>
+<th>Keywords</th>
+<th>Unfixed Bugs</th>
+</tr>
+''')
+
+ for kernel in matrix.kernel_atoms:
+ if kernel.name == source:
+ file.write("<tr><ti>%s</ti><ti>%s</ti><ti>%s</ti><ti>%s</ti></tr>" % (kernel.version, kernel.gpver, kernel.keywords, kernel.affected_by))
+ file.write('''
+</table>
+</body>
+</section>
+''')
+ file.write('''
+</chapter>''')
+
+
+ file.write('''
+<chapter>
+<title>Unparseable bugs</title>
+<section>
+<body>
+<table>
+<tr>
+<th>Bug #</th>
+<th>Title</th>
+<th>Error</th>
+</tr>
+''')
+
+ for ex in failures:
+ file.write("<tr><ti>%s</ti><ti>%s</ti><ti>%s</ti></tr>" % (buglink(ex.bug.bugno), cvelink(cgi.escape(ex.bug.title)), cgi.escape(str(ex.message))))
+ file.write('''
+</table>
+</body>
+</section>
+''')
+ file.write('''
+</chapter>''')
+
+ file.write('''
+
+<chapter>
+<title>Parsed bugs</title>
+<section>
+<body>
+<table>
+<tr>
+<th>Bug #</th>
+<th>Title</th>
+<th>Affected Kernels</th>
+</tr>
+''')
+
+ for bug in successes:
+ file.write("<tr><ti>%s</ti><ti>%s</ti><ti>%s</ti></tr>" % (buglink(bug.bugno), cvelink(cgi.escape(bug.title)), cgi.escape(str(bug.affected))))
+ file.write('''
+</table>
+</body>
+</section>
+''')
+
+ file.write('''
+</chapter>''')
+
+ file.write('''</guide>
+''')
+ file.close()
+# http://cve.mitre.org/cgi-bin/cvename.cgi?name=moo
+
+
diff --git a/kissoutput_new.py b/kissoutput_new.py
new file mode 100644
index 0000000..3a6316e
--- /dev/null
+++ b/kissoutput_new.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# Written by Robert Buchholz <rbu@gentoo.org>
+
+import string
+import sys
+import os
+import re
+import cgi
+
+def buglink(bugno):
+ return "<uri link='https://bugs.gentoo.org/%s'>%s</uri>" % (bugno, bugno)
+
+def cvelink(text):
+ import re
+ return re.sub("(CVE-\d{4}-\d{4})", "<uri link='http://cve.mitre.org/cgi-bin/cvename.cgi?name=\\1'>\\1</uri>", text)
+
+
+class SplitWriter:
+ def write_xml(self, filename, matrix, failures = (), successes = ()):
+ self.fd = open(filename, 'w+')
+ self.write_header("moo")
+
+ self.write_footer("moo")
+ self.fd.close()
+
+ def write_bugs(matrix, bugs):
+ for bug in bugs:
+ self.fs.write("<tr><ti>%s</ti><ti>%s</ti><ti>%s</ti></tr>" %
+ (buglink(bug.bugno), cvelink(cgi.escape(bug.title)), cgi.escape(str(bug.affected))))
+ file.write('''
+</table>
+</body>
+</section>
+''')
+
+ def write_header(self, title):
+ import datetime
+ self.fd.write('''<?xml version='1.0' encoding="UTF-8"?>
+<!DOCTYPE guide SYSTEM "/dtd/guide.dtd">
+<guide link="proj/en/security/kernel.xml">
+<title>Gentoo Kernel Security Tracker: %s</title>
+<author title="Author">
+ <mail link="kern-sec@gentoo.org">Kernel Security Team</mail>
+</author>
+
+<abstract>
+Display Kernel security status.
+</abstract>
+
+<!-- The content of this document is licensed under the CC-BY-SA license -->
+<!-- See http://creativecommons.org/licenses/by-sa/1.0 -->
+<license/>
+
+<version>0.1</version>
+''' % (title))
+ self.fd.write("<date>%s</date>" % (datetime.date.today()))
+
+ self.fd.write('''
+<chapter>
+<title>Kernel Security Tracker: %s</title>
+''' % (title))
+
+
+ file.write('''
+<chapter>
+<title>Unsupported Kernel Sources</title>
+''')
+
+ def write_footer(self):
+ self.fd.write("</guide>\n")
+
diff --git a/make_kernels.pl b/make_kernels.pl
new file mode 100755
index 0000000..7f09338
--- /dev/null
+++ b/make_kernels.pl
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+# Copyright 2004-2005 Gentoo Foundation; Distributed under the GPL v2
+#
+# Scripts to automatically generate the gentoo-sources-2.6 information pages
+#
+# Disclaimer: This code is really ugly, I'm really good at writing horrible perl
+# But it works (to an extent) :)
+
+# use File::Basename;
+# use File::Copy;
+# use URI::Escape;
+use gentoo_sources_web;
+
+
+local *FD;
+my $kernel;
+print ">> Making kernels page\n";
+my %kernels = _get_genpatches_kernels();
+
+open(FD, '> '.$output_path.'/genpversions.txt');
+foreach $kernel (values %kernels) {
+ #print FD '<tr>';
+ print FD $kernel->{'pkg'}.':';
+ print FD $kernel->{'ver'}.':';
+ print FD $kernel->{'gprev'}.':';
+ print FD $kernel->{'wanted'}."\n";
+}
+close(FD);
+
diff --git a/out.xml b/out.xml
new file mode 100644
index 0000000..1e6d2cc
--- /dev/null
+++ b/out.xml
@@ -0,0 +1,17 @@
+<bug>
+ <id>221123</id>
+ <title> Linux Kernels 2.6.22-&gt;2.6.25.2 - utimensat() file time modification bypass vulnerability (CVE-2008-2148) </title>
+ <cve>
+ <id>CVE-2008-2148</id>
+ <desc> The utimensat system call (sys_utimensat) in Linux kernel 2.6.22 and other versions before 2.6.25.3 does not check file permissions when certain UTIME_NOW and UTIME_OMIT combinations are used, which allows local users to modify file times of arbitrary files, possibly leading to a denial of service. </desc>
+ </cve>
+ <url>http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git;a=blob;f=review-2.6.25/vfs-fix-permission-checking-in-sys_utimensat.patch;h=1da0b9bf9f078e3eb147a6799e5a74af2484014a;hb=cbe22288b271b4e4e51f5573281662f53466e41a</url>
+ <arch>All</arch>
+ <severity>normal</severity>
+ <affected>
+ <interval source="linux">
+ <lower inclusive="true">2.6.22</lower>
+ <upper inclusive="false">2.6.25.2</upper>
+ </interval>
+ </affected>
+</bug> \ No newline at end of file
diff --git a/updatesite b/updatesite
new file mode 100755
index 0000000..755d1a4
--- /dev/null
+++ b/updatesite
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+./make_kernels.pl
+
+python kiss2.py
+scp out.xml dev.gentoo.org:public_html/kernsecout.xml