How to use the benchexec.container function in BenchExec

To help you get started, we’ve selected a few BenchExec examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
        @param dir_modes: Dict that specifies which directories should be accessible
            and how in the container.
        @param container_system_config: Whether to use a special system configuration in
            the container that disables all remote host and user lookups, sets a custom
            hostname, etc.
        """
        super(ContainerExecutor, self).__init__(*args, **kwargs)
        self._use_namespaces = use_namespaces
        if not use_namespaces:
            return
        self._container_tmpfs = container_tmpfs
        self._container_system_config = container_system_config
        self._uid = (
            uid
            if uid is not None
            else container.CONTAINER_UID
            if container_system_config
            else os.getuid()
        )
        self._gid = (
            gid
            if gid is not None
            else container.CONTAINER_GID
            if container_system_config
            else os.getgid()
        )
        self._allow_network = network_access
        self._env_override = {}

        if container_system_config:
            self._env_override["HOME"] = container.CONTAINER_HOME
            if container.CONTAINER_HOME not in dir_modes:
github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
def is_accessible(path):
            mode = container.determine_directory_mode(self._dir_modes, path)
            return os.access(path, os.R_OK) and mode not in [None, container.DIR_HIDDEN]
github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
def child():
            """Setup everything inside the container,
            start the tool, and wait for result."""
            try:
                logging.debug(
                    "Child: child process of RunExecutor with PID %d started",
                    container.get_my_pid_from_procfs(),
                )

                # Put all received signals on hold until we handle them later.
                container.block_all_signals()

                # We want to avoid leaking file descriptors to the executed child.
                # It is also nice if the child has only the minimal necessary file
                # descriptors, to avoid keeping other pipes and files open, e.g.,
                # those that the parent uses to communicate with other containers
                # (if containers are started in parallel).
                # Thus we do not use the close_fds feature of subprocess.Popen,
                # but do the same here manually. We keep the relevant ends of our pipes,
                # and stdin/out/err of child and grandchild.
                necessary_fds = {
                    sys.stdin,
                    sys.stdout,
                    sys.stderr,
                    to_parent,
                    from_parent,
                    stdin,
github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
necessary_capabilities = (
                    [libc.CAP_SYS_ADMIN] if result_files_patterns else []
                )
                container.drop_capabilities(keep=necessary_capabilities)

                # Close other fds that were still necessary above.
                container.close_open_fds(
                    keep_files={sys.stdout, sys.stderr, to_parent, from_parent}
                )

                # Set up signal handlers to forward signals to grandchild
                # (because we are PID 1, there is a special signal handling otherwise).
                # cf. dumb-init project: https://github.com/Yelp/dumb-init
                # Also wait for grandchild and return its result.
                if _HAS_SIGWAIT:
                    grandchild_result = container.wait_for_child_and_forward_signals(
                        grandchild_proc.pid, args[0]
                    )
                else:
                    container.forward_all_signals_async(grandchild_proc.pid, args[0])
                    grandchild_result = self._wait_for_process(
                        grandchild_proc.pid, args[0]
                    )

                logging.debug(
                    "Child: process %s terminated with exit code %d.",
                    args[0],
                    grandchild_result[0],
                )

                if result_files_patterns:
                    # Remove the bind mount that _setup_container_filesystem added
github sosy-lab / benchexec / benchexec / containerized_tool.py View on Github external
def _init_container(
    temp_dir,
    network_access,
    dir_modes,
    container_system_config,
    container_tmpfs,  # ignored, tmpfs is always used
):
    """
    Create a fork of this process in a container. This method only returns in the fork,
    so calling it seems like moving the current process into a container.
    """
    # Prepare for private home directory, some tools write there
    if container_system_config:
        dir_modes.setdefault(container.CONTAINER_HOME, container.DIR_HIDDEN)
        os.environ["HOME"] = container.CONTAINER_HOME

    # Preparations
    temp_dir = temp_dir.encode()
    dir_modes = collections.OrderedDict(
        sorted(
            ((path.encode(), kind) for (path, kind) in dir_modes.items()),
            key=lambda tupl: len(tupl[0]),
        )
    )
    uid = container.CONTAINER_UID if container_system_config else os.getuid()
    gid = container.CONTAINER_GID if container_system_config else os.getgid()

    # Create container.
    # Contrary to ContainerExecutor, which uses clone to start a new process in new
    # namespaces, we use unshare, which puts the current process (the multiprocessing
github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
# via a socket (but Python < 3.3 lacks a convenient API for sendmsg),
                # and reading /proc/self in the outer procfs instance
                # (that's what we do).
                my_outer_pid = container.get_my_pid_from_procfs()

                container.mount_proc(self._container_system_config)
                container.reset_signal_handling()
                child_setup_fn()  # Do some other setup the caller wants.

                # Signal readiness to parent by sending our PID
                # and wait until parent is also ready
                os.write(to_parent, str(my_outer_pid).encode())
                received = os.read(from_parent, 1)
                assert received == MARKER_PARENT_COMPLETED, received
                libc.unshare(libc.CLONE_NEWCGROUP)
                container.drop_capabilities()
            finally:
                # close remaining ends of pipe
                os.close(from_parent)
                os.close(to_parent)
            # here Python will exec() the tool for us
github sosy-lab / benchexec / benchexec / containerized_tool.py View on Github external
def make_tmpfs_dir(path):
        """Ensure that a tmpfs is mounted on path, if the path exists"""
        if path in dir_modes:
            return  # explicitly configured by user
        mount_tmpfs = mount_base + path
        if os.path.isdir(mount_tmpfs):
            temp_tmpfs = temp_base + path
            util.makedirs(temp_tmpfs, exist_ok=True)
            container.make_bind_mount(temp_tmpfs, mount_tmpfs)
github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
# those that the parent uses to communicate with other containers
                # (if containers are started in parallel).
                # Thus we do not use the close_fds feature of subprocess.Popen,
                # but do the same here manually. We keep the relevant ends of our pipes,
                # and stdin/out/err of child and grandchild.
                necessary_fds = {
                    sys.stdin,
                    sys.stdout,
                    sys.stderr,
                    to_parent,
                    from_parent,
                    stdin,
                    stdout,
                    stderr,
                } - {None}
                container.close_open_fds(keep_files=necessary_fds)

                try:
                    if self._container_system_config:
                        # A standard hostname increases reproducibility.
                        libc.sethostname(container.CONTAINER_HOSTNAME)

                    if not self._allow_network:
                        container.activate_network_interface("lo")

                    # Wait until user mapping is finished,
                    # this is necessary for filesystem writes
                    received = os.read(from_parent, len(MARKER_USER_MAPPING_COMPLETED))
                    assert received == MARKER_USER_MAPPING_COMPLETED, received

                    if root_dir is not None:
                        self._setup_root_filesystem(root_dir)
github sosy-lab / benchexec / benchexec / containerexecutor.py View on Github external
if container_system_config
            else os.getuid()
        )
        self._gid = (
            gid
            if gid is not None
            else container.CONTAINER_GID
            if container_system_config
            else os.getgid()
        )
        self._allow_network = network_access
        self._env_override = {}

        if container_system_config:
            self._env_override["HOME"] = container.CONTAINER_HOME
            if container.CONTAINER_HOME not in dir_modes:
                dir_modes[container.CONTAINER_HOME] = DIR_HIDDEN

        if "/" not in dir_modes:
            raise ValueError("Need directory mode for '/'.")
        for path, kind in dir_modes.items():
            if kind not in DIR_MODES:
                raise ValueError(
                    "Invalid value '{}' for directory '{}'.".format(kind, path)
                )
            if not os.path.isabs(path):
                raise ValueError("Invalid non-absolute directory '{}'.".format(path))
            if path == "/proc":
                raise ValueError("Cannot specify directory mode for /proc.")
        # All dir_modes in dir_modes are sorted by length
        # to ensure parent directories come before child directories
        # All directories are bytes to avoid issues if existing mountpoints are invalid