• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2021 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Module for dealing with docker."""
15import logging
16import os
17import sys
18
19# pylint: disable=wrong-import-position,import-error
20sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
21
22import constants
23import utils
24
25BASE_BUILDER_TAG = 'gcr.io/oss-fuzz-base/base-builder'
26PROJECT_TAG_PREFIX = 'gcr.io/oss-fuzz/'
27
28# Default fuzz configuration.
29_DEFAULT_DOCKER_RUN_ARGS = [
30    '--cap-add', 'SYS_PTRACE', '-e',
31    'FUZZING_ENGINE=' + constants.DEFAULT_ENGINE, '-e',
32    'ARCHITECTURE=' + constants.DEFAULT_ARCHITECTURE, '-e', 'CIFUZZ=True'
33]
34
35EXTERNAL_PROJECT_IMAGE = 'external-project'
36
37_DEFAULT_DOCKER_RUN_COMMAND = [
38    'docker',
39    'run',
40    '--rm',
41    '--privileged',
42]
43
44
45def get_docker_env_vars(env_mapping):
46  """Returns a list of docker arguments that sets each key in |env_mapping| as
47  an env var and the value of that key in |env_mapping| as the value."""
48  env_var_args = []
49  for env_var, env_var_val in env_mapping.items():
50    env_var_args.extend(['-e', f'{env_var}={env_var_val}'])
51  return env_var_args
52
53
54def get_project_image_name(project):
55  """Returns the name of the project builder image for |project_name|."""
56  # TODO(ochang): We may need unique names to support parallel fuzzing.
57  if project:
58    return PROJECT_TAG_PREFIX + project
59
60  return EXTERNAL_PROJECT_IMAGE
61
62
63def delete_images(images):
64  """Deletes |images|."""
65  command = ['docker', 'rmi', '-f'] + images
66  utils.execute(command)
67  utils.execute(['docker', 'builder', 'prune', '-f'])
68
69
70def get_base_docker_run_args(workspace,
71                             sanitizer=constants.DEFAULT_SANITIZER,
72                             language=constants.DEFAULT_LANGUAGE,
73                             docker_in_docker=False):
74  """Returns arguments that should be passed to every invocation of 'docker
75  run'."""
76  docker_args = _DEFAULT_DOCKER_RUN_ARGS.copy()
77  env_mapping = {
78      'SANITIZER': sanitizer,
79      'FUZZING_LANGUAGE': language,
80      'OUT': workspace.out
81  }
82  docker_args += get_docker_env_vars(env_mapping)
83  docker_container = utils.get_container_name()
84  logging.info('Docker container: %s.', docker_container)
85  if docker_container and not docker_in_docker:
86    # Don't map specific volumes if in a docker container, it breaks when
87    # running a sibling container.
88    docker_args += ['--volumes-from', docker_container]
89  else:
90    docker_args += _get_args_mapping_host_path_to_container(workspace.workspace)
91  return docker_args, docker_container
92
93
94def get_base_docker_run_command(workspace,
95                                sanitizer=constants.DEFAULT_SANITIZER,
96                                language=constants.DEFAULT_LANGUAGE,
97                                docker_in_docker=False):
98  """Returns part of the command that should be used everytime 'docker run' is
99  invoked."""
100  docker_args, docker_container = get_base_docker_run_args(
101      workspace, sanitizer, language, docker_in_docker=docker_in_docker)
102  command = _DEFAULT_DOCKER_RUN_COMMAND.copy() + docker_args
103  return command, docker_container
104
105
106def _get_args_mapping_host_path_to_container(host_path, container_path=None):
107  """Get arguments to docker run that will map |host_path| a path on the host to
108  a path in the container. If |container_path| is specified, that path is mapped
109  to. If not, then |host_path| is mapped to itself in the container."""
110  # WARNING: Do not use this function when running in production (and
111  # --volumes-from) is used for mapping volumes. It will break production.
112  container_path = host_path if container_path is None else container_path
113  return ['-v', f'{host_path}:{container_path}']
114