# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/config/features.gni")

declare_args() {
  compile_suid_client = is_linux

  compile_credentials = is_linux

  compile_seccomp_bpf_demo =
    (is_linux && (cpu_arch == "x86" || cpu_arch == "x64"))
}

# We have two principal targets: sandbox and sandbox_linux_unittests
# All other targets are listed as dependencies.
# There is one notable exception: for historical reasons, chrome_sandbox is
# the setuid sandbox and is its own target.

group("sandbox") {
  deps = [
    ":sandbox_services",
  ]

  if (compile_suid_client) {
    deps += [ ":suid_sandbox_client" ]
  }
  if (use_seccomp_bpf) {
    deps += [
      ":seccomp_bpf",
      ":seccomp_bpf_helpers",
    ]
  }
}

source_set("sandbox_linux_test_utils") {
  sources = [
    "tests/sandbox_test_runner.cc",
    "tests/sandbox_test_runner.h",
    "tests/sandbox_test_runner_function_pointer.cc",
    "tests/sandbox_test_runner_function_pointer.h",
    "tests/test_utils.cc",
    "tests/test_utils.h",
    "tests/unit_tests.cc",
    "tests/unit_tests.h",
  ]

  deps = [
    "//testing/gtest",
  ]

  if (use_seccomp_bpf) {
    sources += [
      "seccomp-bpf/bpf_tester_compatibility_delegate.h",
      "seccomp-bpf/bpf_tests.h",
      "seccomp-bpf/sandbox_bpf_test_runner.cc",
      "seccomp-bpf/sandbox_bpf_test_runner.h",
    ]
    deps += [
      ":seccomp_bpf",
    ]
  }
}

# The main sandboxing test target.
test("sandbox_linux_unittests") {
  sources = [
    "tests/main.cc",
    "tests/unit_tests_unittest.cc",
    "services/broker_process_unittest.cc",
    "services/scoped_process_unittest.cc",
    "services/thread_helpers_unittests.cc",
    "services/yama_unittests.cc",
  ]

  deps = [
    ":sandbox",
    ":sandbox_linux_test_utils",
    "//base",
    "//base/test:test_support",
    "//testing/gtest",
  ]

  if (compile_suid_client) {
    sources += [
      "suid/client/setuid_sandbox_client_unittest.cc",
    ]
  }
  if (use_seccomp_bpf) {
    sources += [
      "seccomp-bpf-helpers/baseline_policy_unittest.cc",
      "seccomp-bpf/bpf_tests_unittest.cc",
      "seccomp-bpf/codegen_unittest.cc",
      "seccomp-bpf/errorcode_unittest.cc",
      "seccomp-bpf/sandbox_bpf_unittest.cc",
      "seccomp-bpf/syscall_iterator_unittest.cc",
      "seccomp-bpf/syscall_unittest.cc",
    ]
  }
  if (compile_credentials) {
    sources += [
      "services/credentials_unittest.cc",
      "services/unix_domain_socket_unittest.cc",
    ]
  }
}

# TODO(GYP) Android version of this test.
#    {
#      # This target is the shared library used by Android APK (i.e.
#      # JNI-friendly) tests.
#      "target_name": "sandbox_linux_jni_unittests",
#      "includes": [
#        "sandbox_linux_test_sources.gypi",
#      ],
#      "type": "shared_library",
#      "conditions": [
#        [ "OS == "android"", {
#          "dependencies": [
#            "../testing/android/native_test.gyp:native_test_native_code",
#          ],
#        }],
#      ],
#    },

component("seccomp_bpf") {
  sources = [
    "seccomp-bpf/basicblock.cc",
    "seccomp-bpf/basicblock.h",
    "seccomp-bpf/codegen.cc",
    "seccomp-bpf/codegen.h",
    "seccomp-bpf/die.cc",
    "seccomp-bpf/die.h",
    "seccomp-bpf/errorcode.cc",
    "seccomp-bpf/errorcode.h",
    "seccomp-bpf/instruction.h",
    "seccomp-bpf/linux_seccomp.h",
    "seccomp-bpf/sandbox_bpf.cc",
    "seccomp-bpf/sandbox_bpf.h",
    "seccomp-bpf/sandbox_bpf_compatibility_policy.h",
    "seccomp-bpf/sandbox_bpf_policy.cc",
    "seccomp-bpf/sandbox_bpf_policy.h",
    "seccomp-bpf/syscall.cc",
    "seccomp-bpf/syscall.h",
    "seccomp-bpf/syscall_iterator.cc",
    "seccomp-bpf/syscall_iterator.h",
    "seccomp-bpf/trap.cc",
    "seccomp-bpf/trap.h",
    "seccomp-bpf/verifier.cc",
    "seccomp-bpf/verifier.h",
  ]
  defines = [ "SANDBOX_IMPLEMENTATION" ]

  deps = [
    ":sandbox_services_headers",
    "//base",
  ]
}

component("seccomp_bpf_helpers") {
  sources = [
    "seccomp-bpf-helpers/baseline_policy.cc",
    "seccomp-bpf-helpers/baseline_policy.h",
    "seccomp-bpf-helpers/sigsys_handlers.cc",
    "seccomp-bpf-helpers/sigsys_handlers.h",
    "seccomp-bpf-helpers/syscall_parameters_restrictions.cc",
    "seccomp-bpf-helpers/syscall_parameters_restrictions.h",
    "seccomp-bpf-helpers/syscall_sets.cc",
    "seccomp-bpf-helpers/syscall_sets.h",
  ]
  defines = [ "SANDBOX_IMPLEMENTATION" ]

  deps = [
    "//base",
    ":seccomp_bpf",
  ]
}

if (compile_seccomp_bpf_demo) {
  # A demonstration program for the seccomp-bpf sandbox.
  executable("seccomp_bpf_demo") {
    sources = [
      "seccomp-bpf/demo.cc",
    ]
    deps = [
      ":seccomp_bpf",
    ]
  }
}

# The setuid sandbox for Linux.
executable("chrome_sandbox") {
  sources = [
    "suid/common/sandbox.h",
    "suid/common/suid_unsafe_environment_variables.h",
    "suid/linux_util.c",
    "suid/linux_util.h",
    "suid/process_util.h",
    "suid/process_util_linux.c",
    "suid/sandbox.c",
  ]

  cflags = [
    # For ULLONG_MAX
    "-std=gnu99",
    # These files have a suspicious comparison.
    # TODO fix this and re-enable this warning.
    "-Wno-sign-compare",
  ]
}

component("sandbox_services") {
  sources = [
    "services/broker_process.cc",
    "services/broker_process.h",
    "services/init_process_reaper.cc",
    "services/init_process_reaper.h",
    "services/scoped_process.cc",
    "services/scoped_process.h",
    "services/thread_helpers.cc",
    "services/thread_helpers.h",
    "services/yama.h",
    "services/yama.cc",
  ]

  defines = [ "SANDBOX_IMPLEMENTATION" ]

  if (compile_credentials) {
    sources += [
      "services/credentials.cc",
      "services/credentials.h",
    ]
    # For capabilities.cc.
    configs += [ "//build/config/linux:libcap" ]
  }

  deps = [
    "//base",
  ]
}

source_set("sandbox_services_headers") {
  sources = [
    "services/android_arm_ucontext.h",
    "services/android_futex.h",
    "services/android_ucontext.h",
    "services/android_i386_ucontext.h",
    "services/arm_linux_syscalls.h",
    "services/linux_syscalls.h",
    "services/x86_32_linux_syscalls.h",
    "services/x86_64_linux_syscalls.h",
  ]
}

# We make this its own target so that it does not interfere with our tests.
source_set("libc_urandom_override") {
  sources = [
    "services/libc_urandom_override.cc",
    "services/libc_urandom_override.h",
  ]
  deps = [
    "//base",
  ]
}

component("suid_sandbox_client") {
  sources = [
    "suid/common/sandbox.h",
    "suid/common/suid_unsafe_environment_variables.h",
    "suid/client/setuid_sandbox_client.cc",
    "suid/client/setuid_sandbox_client.h",
  ]
  defines = [ "SANDBOX_IMPLEMENTATION" ]

  deps = [
    ":sandbox_services",
    "//base",
  ]
}

if (is_android) {
  # TODO(GYP) enable this. Needs an android_strip wrapper python script.
  #action("sandbox_linux_unittests_stripped") {
  #  script = "android_stip.py"
  #
  #  in_file = "$root_out_dir/sandbox_linux_unittests"
  #
  #  out_file = "$root_out_dir/sandbox_linux_unittests_stripped"
  #  outputs = [ out_file ]
  #
  #  args = [
  #    rebase_path(in_file, root_build_dir),
  #    "-o", rebase_path(out_file, root_build_dir),
  #  ]
  #
  #  deps = [
  #    ":sandbox_linux_unittests",
  #  ]
  #}

  # TODO(GYP) convert this.
  #      {
  #      'target_name': 'sandbox_linux_jni_unittests_apk',
  #      'type': 'none',
  #      'variables': {
  #        'test_suite_name': 'sandbox_linux_jni_unittests',
  #      },
  #      'dependencies': [
  #        'sandbox_linux_jni_unittests',
  #      ],
  #      'includes': [ '../../build/apk_test.gypi' ],
  #      }
}