def process_elf_dependencies(action, pkg_vars, dyn_tok_conv,
    kernel_paths, **kwargs):
        """Produce the elf dependencies for the file delivered in the action
        provided.

        'action' is the file action to analyze.

        'pkg_vars' is the list of variants against which the package delivering
        the action was published.

        'dyn_tok_conv' is the dictionary which maps the dynamic tokens, like
        $PLATFORM, to the values they should be expanded to.

        'kernel_paths' contains the run paths which kernel modules should use.
        """

        if not action.name == "file":
                return [], [], {}

        installed_path = action.attrs[action.key_attr]

        proto_file = action.attrs[PD_LOCAL_PATH]

        if not os.path.exists(proto_file):
                raise base.MissingFile(proto_file)

        if not elf.is_elf_object(proto_file):
                return [], [], {}

        try:
                ei = elf.get_info(proto_file)
                ed = elf.get_dynamic(proto_file)
        except elf.ElfError, e:
                raise BadElfFile(proto_file, e)
Example #2
0
def process_elf_dependencies(action, pkg_vars, dyn_tok_conv, kernel_paths,
                             **kwargs):
    """Produce the elf dependencies for the file delivered in the action
        provided.

        'action' is the file action to analyze.

        'pkg_vars' is the list of variants against which the package delivering
        the action was published.

        'dyn_tok_conv' is the dictionary which maps the dynamic tokens, like
        $PLATFORM, to the values they should be expanded to.

        'kernel_paths' contains the run paths which kernel modules should use.
        """

    if not action.name == "file":
        return [], [], {}

    installed_path = action.attrs[action.key_attr]

    proto_file = action.attrs[PD_LOCAL_PATH]

    if not os.path.exists(proto_file):
        raise base.MissingFile(proto_file)

    if not elf.is_elf_object(proto_file):
        return [], [], {}

    try:
        ei = elf.get_info(proto_file)
        ed = elf.get_dynamic(proto_file)
    except elf.ElfError, e:
        raise BadElfFile(proto_file, e)
Example #3
0
    def test_non_elf(self):
        """Test that elf routines gracefully handle non-elf objects."""

        p = "this-is-not-an-elf-file.so"
        self.make_misc_files({p: "this is only a test"})
        os.chdir(self.test_root)
        self.assertEqual(elf.is_elf_object(p), False)
        self.assertRaises(elf.ElfError, elf.get_dynamic, p)
        self.assertRaises(elf.ElfError, elf.get_info, p)
Example #4
0
        def test_non_elf(self):
                """Test that elf routines gracefully handle non-elf objects."""

                p = "this-is-not-an-elf-file.so"
                self.make_misc_files({p: "this is only a test"})
                os.chdir(self.test_root)
                self.assertEqual(elf.is_elf_object(p), False)
                self.assertRaises(elf.ElfError, elf.get_dynamic, p)
                self.assertRaises(elf.ElfError, elf.get_info, p)
Example #5
0
 def test_valid_elf(self):
     """Test that elf routines work on a small set of objects."""
     arch = pkg.portable.get_isainfo()[0]
     for p in self.elf_paths:
         p = re.sub("__ARCH__", arch, p)
         self.debug("testing elf file {0}".format(p))
         self.assertTrue(os.path.exists(p), "{0} does not exist".format(p))
         self.assertEqual(elf.is_elf_object(p), True)
         elf.get_dynamic(p)
         elf.get_info(p)
Example #6
0
 def test_valid_elf(self):
         """Test that elf routines work on a small set of objects."""
         arch = pkg.portable.get_isainfo()[0]
         for p in self.elf_paths:
                 p = re.sub("__ARCH__", arch, p)
                 self.debug("testing elf file %s" % p)
                 self.assert_(os.path.exists(p))
                 self.assertEqual(elf.is_elf_object(p), True)
                 elf.get_dynamic(p)
                 elf.get_info(p)
Example #7
0
	def file_action(self, action, manifest, engine, pkglint_id="001"):
		"""Checks for existence in the proto area."""

		if action.name not in ["file"]:
			return

		path = action.hash
		if path == None or path == 'NOHASH':
			path = action.attrs["path"]

		# check for writable files without a preserve attribute
		if "mode" in action.attrs:
			mode = action.attrs["mode"]

			if (int(mode, 8) & 0222) != 0 and "preserve" not in action.attrs:
				engine.error(
				_("%(path)s is writable (%(mode)s), but missing a preserve"
				  " attribute") %  {"path": path, "mode": mode},
				msgid="%s%s.0" % (self.name, pkglint_id))
		elif "preserve" in action.attrs:
			if "mode" in action.attrs:
				mode = action.attrs["mode"]
				if (int(mode, 8) & 0222) == 0:
					engine.error(
					_("%(path)s has a preserve action, but is not writable (%(mode)s)") %  {"path": path, "mode": mode},
				msgid="%s%s.4" % (self.name, pkglint_id))
			else:
				engine.error(
				_("%(path)s has a preserve action, but no mode") %  {"path": path, "mode": mode},
				msgid="%s%s.3" % (self.name, pkglint_id))

		# checks that require a physical file to look at
		if self.proto_path is not None:
			for directory in self.proto_path:
				fullpath = directory + "/" + path

				if os.path.exists(fullpath):
					break

			if not os.path.exists(fullpath):
				engine.info(
					_("%s missing from proto area, skipping"
					  " content checks") % path, 
					msgid="%s%s.1" % (self.name, pkglint_id))
			elif elf.is_elf_object(fullpath):
				# 32/64 bit in wrong place
				result = self.__elf_wrong_location_check(fullpath)
				if result != None:
					engine.error(result % path, 
						msgid="%s%s.2" % (self.name, pkglint_id))
				result = self.__elf_runpath_check(fullpath, engine)
				if result != None:
					engine.error(result % path, 
						msgid="%s%s.3" % (self.name, pkglint_id))
				result = self.__elf_aslr_check(fullpath, engine)
Example #8
0
	def file_action(self, action, manifest, engine, pkglint_id="001"):
		"""Checks for existence in the proto area."""

		if action.name not in ["file"]:
			return

		path = action.hash
		if path == None or path == 'NOHASH':
			path = action.attrs["path"]

		# check for writable files without a preserve attribute
		if "mode" in action.attrs:
			mode = action.attrs["mode"]

			if (int(mode, 8) & 0222) != 0 and "preserve" not in action.attrs:
				engine.error(
				_("%(path)s is writable (%(mode)s), but missing a preserve"
				  " attribute") %  {"path": path, "mode": mode},
				msgid="%s%s.0" % (self.name, pkglint_id))
		elif "preserve" in action.attrs:
			if "mode" in action.attrs:
				mode = action.attrs["mode"]
				if (int(mode, 8) & 0222) == 0:
					engine.error(
					_("%(path)s has a preserve action, but is not writable (%(mode)s)") %  {"path": path, "mode": mode},
				msgid="%s%s.4" % (self.name, pkglint_id))
			else:
				engine.error(
				_("%(path)s has a preserve action, but no mode") %  {"path": path, "mode": mode},
				msgid="%s%s.3" % (self.name, pkglint_id))

		# checks that require a physical file to look at
		if self.proto_path is not None:
			for directory in self.proto_path:
				fullpath = directory + "/" + path

				if os.path.exists(fullpath):
					break

			if not os.path.exists(fullpath):
				engine.info(
					_("%s missing from proto area, skipping"
					  " content checks") % path, 
					msgid="%s%s.1" % (self.name, pkglint_id))
			elif elf.is_elf_object(fullpath):
				# 32/64 bit in wrong place
				result = self.__elf_wrong_location_check(fullpath)
				if result != None:
					engine.error(result % path, 
						msgid="%s%s.2" % (self.name, pkglint_id))
				result = self.__elf_runpath_check(fullpath, engine)
				if result != None:
					engine.error(result % path, 
						msgid="%s%s.3" % (self.name, pkglint_id))
Example #9
0
    def file_action(self, action, manifest, engine, pkglint_id="001"):
        """Various file checks."""

        if action.name not in ["file"]:
            return

        # path to the delivered file
        inspath = action.attrs["path"]

        # path to the file within the prototype area
        path = action.hash
        if path is None or path == "NOHASH":
            path = inspath

        # verify that preserve attribute is correctly used when
        # file is writable and not in other cases
        if "mode" in action.attrs:
            mode = action.attrs["mode"]
            writable = bool(int(mode, 8) & 0o222)

            if writable and "preserve" not in action.attrs:
                engine.error(
                    f"{path} is writable ({mode}), but missing a preserve attribute",
                    msgid=f"{self.name}{pkglint_id}.0")
            elif not writable and "preserve" in action.attrs:
                engine.error(
                    f"{path} has a preserve action, but is not writable ({mode})",
                    msgid=f"{self.name}{pkglint_id}.4")

        elif "preserve" in action.attrs:
            engine.error(f"{path} has a preserve action, but no mode",
                         msgid=f"{self.name}{pkglint_id}.3")

        # checks that require a physical file to look at
        if self.proto_path is not None:
            for directory in self.proto_path:
                fullpath = directory + "/" + path

                if os.path.exists(fullpath):
                    break

            if not os.path.exists(fullpath):
                engine.info(
                    f"{path} missing from proto area, skipping content checks",
                    msgid=f"{self.name}{pkglint_id}.1")
            elif elf.is_elf_object(fullpath):
                # 32/64 bit in wrong place
                self.__elf_location_check(fullpath, inspath, engine,
                                          pkglint_id)
                # verify that correct RUNPATH is present
                self.__elf_runpath_check(fullpath, engine, pkglint_id)
                # verify that ASLR is enabled when appropriate
                self.__elf_aslr_check(fullpath, engine, pkglint_id)
Example #10
0
def process_elf_dependencies(action, proto_dir, pkg_vars, **kwargs):
    """Given a file action and proto directory, produce the elf dependencies
        for that file."""

    if not action.name == "file":
        return []

    installed_path = action.attrs[action.key_attr]

    proto_file = os.path.join(proto_dir, installed_path)

    if not os.path.exists(proto_file):
        raise base.MissingFile(proto_file)

    if not elf.is_elf_object(proto_file):
        return []

    try:
        ei = elf.get_info(proto_file)
        ed = elf.get_dynamic(proto_file)
    except elf.ElfError, e:
        raise BadElfFile(proto_file, e)
Example #11
0
def process_elf_dependencies(action, proto_dir, pkg_vars, **kwargs):
        """Given a file action and proto directory, produce the elf dependencies
        for that file."""

        if not action.name == "file":
                return []

        installed_path = action.attrs[action.key_attr]
        
        proto_file = os.path.join(proto_dir, installed_path)

        if not os.path.exists(proto_file):
                raise base.MissingFile(proto_file)

        if not elf.is_elf_object(proto_file):
                return []

        try:
                ei = elf.get_info(proto_file)
                ed = elf.get_dynamic(proto_file)
        except elf.ElfError, e:
                raise BadElfFile(proto_file, e)
Example #12
0
def process_elf_dependencies(action, pkg_vars, dyn_tok_conv, run_paths,
    **kwargs):
        """Produce the elf dependencies for the file delivered in the action
        provided.

        'action' is the file action to analyze.

        'pkg_vars' is the list of variants against which the package delivering
        the action was published.

        'dyn_tok_conv' is the dictionary which maps the dynamic tokens, like
        $PLATFORM, to the values they should be expanded to.

        'run_paths' contains the run paths which elf binaries should use.
        """

        if not action.name == "file":
                return [], [], {}

        installed_path = action.attrs[action.key_attr]

        proto_file = action.attrs[PD_LOCAL_PATH]

        if not os.path.exists(proto_file):
                raise base.MissingFile(proto_file)

        if not elf.is_elf_object(proto_file):
                return [], [], {}

        try:
                ei = elf.get_info(proto_file)
                ed = elf.get_dynamic(proto_file)
        except elf.ElfError as e:
                raise BadElfFile(proto_file, e)
        deps = [
            d[0]
            for d in ed.get("deps", [])
        ]
        rp = ed.get("runpath", "").split(":")
        if len(rp) == 1 and rp[0] == "":
                rp = []

        dyn_tok_conv["$ORIGIN"] = [os.path.join("/",
            os.path.dirname(installed_path))]

        kernel64 = None

        # For kernel modules, default path resolution is /platform/<platform>,
        # /kernel, /usr/kernel.  But how do we know what <platform> would be for
        # a given module?  Does it do fallbacks to, say, sun4u?
        if installed_path.startswith("kernel") or \
            installed_path.startswith("usr/kernel") or \
            (installed_path.startswith("platform") and \
            installed_path.split("/")[2] == "kernel"):
                if rp and (len(rp) > 1 or
                    not re.match(r'^/usr/gcc/\d/lib$', rp[0])):
                        raise RuntimeError("RUNPATH set for kernel module "
                            "({0}): {1}".format(installed_path, rp))
                # Add this platform to the search path.
                if installed_path.startswith("platform"):
                        rp.append("/platform/{0}/kernel".format(
                            installed_path.split("/")[1]))
                else:
                        for p in dyn_tok_conv.get("$PLATFORM", []):
                                rp.append("/platform/{0}/kernel".format(p))
                # Default kernel search path
                rp.extend(["/kernel", "/usr/kernel"])
                # What subdirectory should we look in for 64-bit kernel modules?
                if ei["bits"] == 64:
                        if ei["arch"] == "i386":
                                kernel64 = "amd64"
                        elif ei["arch"] == "sparc":
                                kernel64 = "sparcv9"
                        else:
                                raise RuntimeError("Unknown arch:{0}".format(
                                    ei["arch"]))
        else:
                for p in default_run_paths:
                        if ei["bits"] == 64:
                                p += "/64"
                        if p not in rp:
                                rp.append(p)

        elist = []
        if run_paths:
                # add our detected runpaths into the user-supplied one (if any)
                rp = base.insert_default_runpath(rp, run_paths)

        rp, errs = expand_variables(rp, dyn_tok_conv)

        elist.extend([
            UnsupportedDynamicToken(proto_file, installed_path, p, tok)
            for p, tok in errs
        ])

        res = []

        for d in deps:
                pn, fn = os.path.split(d)
                pathlist = []
                for p in rp:
                        if kernel64:
                                # Find 64-bit modules the way krtld does.
                                # XXX We don't resolve dependencies found in
                                # /platform, since we don't know where under
                                # /platform to look.
                                deppath = \
                                    os.path.join(p, pn, kernel64, fn).lstrip(
                                    os.path.sep)
                        else:
                                deppath = os.path.join(p, d).lstrip(os.path.sep)
                        # deppath includes filename; remove that.
                        head, tail = os.path.split(deppath)
                        if head:
                                pathlist.append(head)
                res.append(ElfDependency(action, fn, pathlist, pkg_vars,
                    action.attrs[PD_PROTO_DIR]))
        del dyn_tok_conv["$ORIGIN"]
        return res, elist, {}