def install(cls, db, logger=None): if logger is None: logger = log.getChildLogger(cls.__name__) for flag, (char, nice_name) in cls.tainted_flags.items(): if get_taint_flag_by_ureport_name(db, flag) is None: logger.info("Adding kernel taint flag '{0}': {1}" .format(char, nice_name)) new = KernelTaintFlag() new.character = char new.ureport_name = flag new.nice_name = nice_name db.session.add(new) db.session.flush()
def save_ureport(self, db, db_report, ureport, flush=False, count=1): bthash1 = self._hash_koops(ureport["frames"], skip_unreliable=False) bthash2 = self._hash_koops(ureport["frames"], skip_unreliable=True) if len(db_report.backtraces) < 1: db_backtrace = ReportBacktrace() db_backtrace.report = db_report db.session.add(db_backtrace) db_thread = ReportBtThread() db_thread.backtrace = db_backtrace db_thread.crashthread = True db.session.add(db_thread) db_bthash1 = ReportBtHash() db_bthash1.backtrace = db_backtrace db_bthash1.hash = bthash1 db_bthash1.type = "NAMES" db.session.add(db_bthash1) if bthash2 is not None and bthash1 != bthash2: db_bthash2 = ReportBtHash() db_bthash2.backtrace = db_backtrace db_bthash2.hash = bthash2 db_bthash2.type = "NAMES" db.session.add(db_bthash2) new_symbols = {} new_symbolsources = {} i = 0 for frame in ureport["frames"]: # OK, this is totally ugly. # Frames may contain inlined functions, that would normally # require shifting all frames by 1 and inserting a new one. # There is no way to do this efficiently with SQL Alchemy # (you need to go one by one and flush after each) so # creating a space for additional frames is a huge speed # optimization. i += 10 # nah, another hack, deals with wrong parsing if frame["function_name"].startswith("0x"): continue if not "module_name" in frame: module = "vmlinux" else: module = frame["module_name"] db_symbol = get_symbol_by_name_path(db, frame["function_name"], module) if db_symbol is None: key = (frame["function_name"], module) if key in new_symbols: db_symbol = new_symbols[key] else: db_symbol = Symbol() db_symbol.name = frame["function_name"] db_symbol.normalized_path = module db.session.add(db_symbol) new_symbols[key] = db_symbol # this doesn't work well. on 64bit, kernel maps to # the end of address space (64bit unsigned), but in # postgres bigint is 64bit signed and can't save # the value - let's just map it to signed if frame["address"] >= (1 << 63): address = frame["address"] - (1 << 64) else: address = frame["address"] db_symbolsource = get_ssource_by_bpo(db, ureport["version"], module, address) if db_symbolsource is None: key = (ureport["version"], module, address) if key in new_symbolsources: db_symbolsource = new_symbolsources[key] else: db_symbolsource = SymbolSource() db_symbolsource.path = module db_symbolsource.offset = address db_symbolsource.func_offset = frame["function_offset"] db_symbolsource.symbol = db_symbol db_symbolsource.build_id = ureport["version"] db.session.add(db_symbolsource) new_symbolsources[key] = db_symbolsource db_frame = ReportBtFrame() db_frame.thread = db_thread db_frame.order = i db_frame.symbolsource = db_symbolsource db_frame.inlined = False db_frame.reliable = frame["reliable"] db.session.add(db_frame) for taintflag in ureport["taint_flags"]: db_taintflag = get_taint_flag_by_ureport_name(db, taintflag) if db_taintflag is None: self.log_warn("Skipping unsupported taint flag '{0}'" .format(taintflag)) continue db_bttaintflag = ReportBtTaintFlag() db_bttaintflag.backtrace = db_backtrace db_bttaintflag.taintflag = db_taintflag db.session.add(db_bttaintflag) if "modules" in ureport: new_modules = {} # use set() to remove duplicates for module in set(ureport["modules"]): idx = module.find("(") if idx >= 0: module = module[:idx] db_module = get_kernelmodule_by_name(db, module) if db_module is None: if module in new_modules: db_module = new_modules[module] else: db_module = KernelModule() db_module.name = module db.session.add(db_module) new_modules[module] = db_module db_btmodule = ReportBtKernelModule() db_btmodule.kernelmodule = db_module db_btmodule.backtrace = db_backtrace db.session.add(db_btmodule) # do not overwrite an existing oops if not db_report.has_lob("oops"): # do not append here, but create a new dict # we only want save_ureport_post_flush process the most # recently saved report self.add_lob = {db_report: ureport["raw_oops"].encode("utf-8")} if flush: db.session.flush()
def installed(cls, db): for flag in cls.tainted_flags.keys(): if get_taint_flag_by_ureport_name(db, flag) is None: return False return True