Пример #1
0
	def analyze(self, pkginfo, tar):
		invalid_elffiles = []
		questionable_elffiles = []

		for entry in tar:
			# is it a regular file ?
			if not entry.isfile():
				continue
			# is it outside standard binary dirs ?
			in_std_dirs = any(entry.name.startswith(d) for d in valid_dirs)
			in_que_dirs = any(entry.name.startswith(d) for d in questionable_dirs)

			if in_std_dirs:
				continue
			# is it an ELF file ?
			f = tar.extractfile(entry)
			if is_elf(f):
				if in_que_dirs:
					questionable_elffiles.append(entry.name)
				else:
					invalid_elffiles.append(entry.name)

		que_elfdirs = [d for d in questionable_dirs if any(f.startswith(d) for f in questionable_elffiles)]
		self.errors = [("elffile-not-in-allowed-dirs %s", i)
				for i in invalid_elffiles]
		self.errors.extend(("elffile-in-questionable-dirs %s", i)
				for i in que_elfdirs)
		self.infos = [("elffile-not-in-allowed-dirs %s", i)
				for i in questionable_elffiles]
Пример #2
0
def scanlibs(fileobj, filename, custom_libs):
	"""
	Find shared libraries in a file-like binary object

	If it depends on a library, store that library's path.

	returns: a dictionary { library => set(ELF files using that library) }
	"""

	if not is_elf(fileobj):
		return {}

	elffile = ELFFile(fileobj)
	sharedlibs = defaultdict(set)
	for section in elffile.iter_sections():
		if not isinstance(section, DynamicSection):
			continue
		for tag in section.iter_tags():
			# DT_NEEDED means shared library
			if tag.entry.d_tag != 'DT_NEEDED':
				continue
			bitsize = elffile.elfclass
			architecture = {32:'i686', 64:'x86-64'}[bitsize]
			libname = tag.needed
			if libname in custom_libs:
				sharedlibs[custom_libs[libname][1:]].add(filename)
				continue
			try:
				libpath = os.path.abspath(
						libcache[architecture][libname])[1:]
				sharedlibs[libpath].add(filename)
			except KeyError:
				# We didn't know about the library, so add it for fail later
				sharedlibs[libname].add(filename)
	return sharedlibs
Пример #3
0
    def analyze(self, pkginfo, tar):
        print("inside")
        gettime()

        for entry in tar:
            if not entry.isfile():
                continue

            # is it an ELF file ?
            fileobj = tar.extractfile(entry)
            if not is_elf(fileobj):
                continue

            for path in get_rpaths(fileobj):
                path_ok = path in allowed
                for allowed_toplevel in allowed_toplevels:
                    if path.startswith(allowed_toplevel):
                        path_ok = True

                if not path_ok:
                    self.errors.append(
                        ("insecure-rpath %s %s", (path, entry.name)))
                    break
                if path in warn and entry.name not in insecure_rpaths:
                    self.warnings.append(
                        ("insecure-rpath %s %s", (path, entry.name)))
Пример #4
0
    def analyze(self, pkginfo, tar):
        liblist = {}
        dependlist = {}
        filllibcache()
        os.environ['LC_ALL'] = 'C'
        pkg_so_files = ['/' + n for n in tar.getnames() if '.so' in n]

        print("has # files", len(tar.getnames()))
        for entry in tar:
            print(gettime(), "tar entry - ", entry.name)
            if not entry.isfile():
                continue
            f = tar.extractfile(entry)
            # find anything that could be rpath related
            rpath_files = {}
            if is_elf(f):
                rpaths = list(get_rpaths(f))
                f.seek(0)
                print(gettime(), "rpaths - ", rpaths)
                for n in pkg_so_files:
                    if any(n.startswith(rp) for rp in rpaths):
                        rpath_files[os.path.basename(n)] = n
            liblist.update(scanlibs(f, entry.name, rpath_files))
            f.close()

        print(gettime(), "DONE tar entries")

        # Ldd all the files and find all the link and script dependencies
        dependlist, orphans = finddepends(liblist)

        # Handle "no package associated" errors
        self.warnings.extend([("library-no-package-associated %s", i)
                              for i in orphans])

        print(gettime(), "link level deps")

        # Print link-level deps
        for pkg, libraries in dependlist.items():
            if isinstance(libraries, set):
                files = list(libraries)
                needing = set().union(*[liblist[lib] for lib in libraries])
                reasons = pkginfo.detected_deps.setdefault(pkg, [])
                reasons.append(("libraries-needed %s %s",
                                (str(files), str(list(needing)))))
                self.infos.append(
                    ("link-level-dependence %s in %s", (pkg, str(files))))

        print(gettime(), "link level deps 2")

        # Check for packages in testing
        for i in dependlist.keys():
            p = Namcap.package.load_testing_package(i)
            q = Namcap.package.load_from_db(i)
            if p is not None and q is not None and p["version"] == q["version"]:
                self.warnings.append(("dependency-is-testing-release %s", i))
Пример #5
0
    def analyze(self, pkginfo, tar):
        nopie_binaries = []

        for entry in tar:
            if not entry.isfile():
                continue
            fp = tar.extractfile(entry)
            if not is_elf(fp):
                continue
            elffile = ELFFile(fp)
            if elffile.header['e_type'] != 'ET_DYN' or not self.has_dt_debug(
                    elffile):
                nopie_binaries.append(entry.name)

        if nopie_binaries:
            self.warnings = [("elffile-nopie %s", i) for i in nopie_binaries]
Пример #6
0
	def analyze(self, pkginfo, tar):
		missing_relro = []

		for entry in tar:
			if not entry.isfile():
				continue
			fp = tar.extractfile(entry)
			if not is_elf(fp):
				continue
			elffile = ELFFile(fp)
			if any(seg['p_type'] == 'PT_GNU_RELRO' for seg in elffile.iter_segments()):
				if self.has_bind_now(elffile):
					continue

			missing_relro.append(entry.name)

		if missing_relro:
			self.warnings = [("elffile-without-relro %s", i)
					for i in missing_relro]
Пример #7
0
    def analyze(self, pkginfo, tar):
        files_with_textrel = []

        for entry in tar:
            if not entry.isfile():
                continue
            fp = tar.extractfile(entry)
            if not is_elf(fp):
                continue
            elffile = ELFFile(fp)
            for section in elffile.iter_sections():
                if not isinstance(section, DynamicSection):
                    continue
                for tag in section.iter_tags('DT_TEXTREL'):
                    files_with_textrel.append(entry.name)

        if files_with_textrel:
            self.warnings = [("elffile-with-textrel %s", i)
                             for i in files_with_textrel]
Пример #8
0
	def analyze(self, pkginfo, tar):
		exec_stacks = []

		for entry in tar:
			if not entry.isfile():
				continue
			fp = tar.extractfile(entry)
			if not is_elf(fp):
				continue
			elffile = ELFFile(fp)
			for segment in elffile.iter_segments():
				if segment['p_type'] != 'PT_GNU_STACK':
					continue

				mode = segment['p_flags']
				if mode & 1:
					exec_stacks.append(entry.name)

		if exec_stacks:
			self.warnings = [("elffile-with-execstack %s", i)
					for i in exec_stacks]
Пример #9
0
    def analyze(self, pkginfo, tar):
        supress_name = ['^mingw-']
        if any(re.search(s, pkginfo['name']) for s in supress_name):
            return
        found_elffiles = []

        for entry in tar.getmembers():
            if not entry.isfile():
                continue
            f = tar.extractfile(entry)
            # Ar files (static libs) are also architecture specific (FS#24854)
            if is_elf(f) or is_static(f):
                found_elffiles.append(entry.name)
            f.close()

        if pkginfo["arch"] and pkginfo["arch"][0] == 'any':
            self.errors = [("elffile-in-any-package %s", i)
                           for i in found_elffiles]
        else:
            if len(found_elffiles) == 0:
                self.warnings.append(("no-elffiles-not-any-package", ()))
Пример #10
0
	def analyze(self, pkginfo, tar):
		unstripped_binaries = []

		for entry in tar:
			if not entry.isfile():
				continue
			fp = tar.extractfile(entry)
			if not is_elf(fp):
				continue
			elffile = ELFFile(fp)
			for section in elffile.iter_sections():
				if not isinstance(section, SymbolTableSection):
					continue

				if section['sh_entsize'] == 0:
					continue

				if section.name == '.symtab':
					unstripped_binaries.append(entry.name)
		if unstripped_binaries:
			self.warnings = [("elffile-unstripped %s", i)
					for i in unstripped_binaries]
Пример #11
0
    def analyze(self, pkginfo, tar):
        for entry in tar:
            if not entry.isfile():
                continue

            fileobj = tar.extractfile(entry)
            if not is_elf(fileobj):
                continue

            for path in get_runpaths(fileobj):
                path_ok = path in allowed
                if any(path.startswith(tl) for tl in allowed_toplevels):
                    path_ok = True

                if not path_ok:
                    self.errors.append(
                        ("insecure-runpath %s %s", (path, entry.name)))
                    break

                if path in warn and entry.name not in insecure_rpaths:
                    self.warnings.append(
                        ("insecure-runpath %s %s", (path, entry.name)))
Пример #12
0
	def analyze(self, pkginfo, tar):
		for entry in tar:
			if not entry.isfile():
				continue

			# is it an ELF file ?
			f = tar.extractfile(entry)
			if not is_elf(f):
				f.close()
				continue
			elf = f.read()
			f.close()

			# write it to a temporary file
			f = tempfile.NamedTemporaryFile(delete = False)
			f.write(elf)
			f.close()

			os.chmod(f.name, 0o755)

			for lib in get_unused_sodepends(f.name):
				self.warnings.append(("unused-sodepend %s %s", (lib, entry.name)))

			os.unlink(f.name)