// Copyright (c) 2013 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.

#include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"

#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
#include "content/public/common/content_switches.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/services/broker_process.h"
#include "sandbox/linux/services/linux_syscalls.h"

using sandbox::BrokerProcess;
using sandbox::ErrorCode;
using sandbox::SandboxBPF;
using sandbox::SyscallSets;
using sandbox::arch_seccomp_data;

namespace content {

namespace {

inline bool IsChromeOS() {
#if defined(OS_CHROMEOS)
  return true;
#else
  return false;
#endif
}

inline bool IsArchitectureX86_64() {
#if defined(__x86_64__)
  return true;
#else
  return false;
#endif
}

inline bool IsArchitectureI386() {
#if defined(__i386__)
  return true;
#else
  return false;
#endif
}

inline bool IsArchitectureArm() {
#if defined(__arm__)
  return true;
#else
  return false;
#endif
}

bool IsAcceleratedVideoDecodeEnabled() {
  // Accelerated video decode is currently enabled on Chrome OS,
  // but not on Linux: crbug.com/137247.
  bool is_enabled = IsChromeOS();

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  is_enabled &=
      !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode);

  return is_enabled;
}

intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args,
                           void* aux_broker_process) {
  RAW_CHECK(aux_broker_process);
  BrokerProcess* broker_process =
      static_cast<BrokerProcess*>(aux_broker_process);
  switch (args.nr) {
    case __NR_access:
      return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
                                    static_cast<int>(args.args[1]));
    case __NR_open:
      return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
                                  static_cast<int>(args.args[1]));
    case __NR_openat:
      // Allow using openat() as open().
      if (static_cast<int>(args.args[0]) == AT_FDCWD) {
        return
            broker_process->Open(reinterpret_cast<const char*>(args.args[1]),
                                 static_cast<int>(args.args[2]));
      } else {
        return -EPERM;
      }
    default:
      RAW_CHECK(false);
      return -ENOSYS;
  }
}

class GpuBrokerProcessPolicy : public GpuProcessPolicy {
 public:
  GpuBrokerProcessPolicy() {}
  virtual ~GpuBrokerProcessPolicy() {}

  virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
                                    int system_call_number) const OVERRIDE;

 private:
  DISALLOW_COPY_AND_ASSIGN(GpuBrokerProcessPolicy);
};

// x86_64/i386 or desktop ARM.
// A GPU broker policy is the same as a GPU policy with open and
// openat allowed.
ErrorCode GpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
                                                  int sysno) const {
  switch (sysno) {
    case __NR_access:
    case __NR_open:
    case __NR_openat:
      return ErrorCode(ErrorCode::ERR_ALLOWED);
    default:
      return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
  }
}

bool EnableGpuBrokerPolicyCallback() {
  return SandboxSeccompBPF::StartSandboxWithExternalPolicy(
      scoped_ptr<sandbox::SandboxBPFPolicy>(new GpuBrokerProcessPolicy));
}

}  // namespace

GpuProcessPolicy::GpuProcessPolicy() : broker_process_(NULL) {}

GpuProcessPolicy::~GpuProcessPolicy() {}

// Main policy for x86_64/i386. Extended by CrosArmGpuProcessPolicy.
ErrorCode GpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
                                            int sysno) const {
  switch (sysno) {
    case __NR_ioctl:
#if defined(__i386__) || defined(__x86_64__)
    // The Nvidia driver uses flags not in the baseline policy
    // (MAP_LOCKED | MAP_EXECUTABLE | MAP_32BIT)
    case __NR_mmap:
#endif
    // We also hit this on the linux_chromeos bot but don't yet know what
    // weird flags were involved.
    case __NR_mprotect:
    case __NR_sched_getaffinity:
    case __NR_sched_setaffinity:
    case __NR_setpriority:
      return ErrorCode(ErrorCode::ERR_ALLOWED);
    case __NR_access:
    case __NR_open:
    case __NR_openat:
      DCHECK(broker_process_);
      return sandbox->Trap(GpuSIGSYS_Handler, broker_process_);
    default:
      if (SyscallSets::IsEventFd(sysno))
        return ErrorCode(ErrorCode::ERR_ALLOWED);

      // Default on the baseline policy.
      return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
  }
}

bool GpuProcessPolicy::PreSandboxHook() {
  // Warm up resources needed by the policy we're about to enable and
  // eventually start a broker process.
  const bool chromeos_arm_gpu = IsChromeOS() && IsArchitectureArm();
  // This policy is for x86 or Desktop.
  DCHECK(!chromeos_arm_gpu);

  DCHECK(!broker_process());
  // Create a new broker process.
  InitGpuBrokerProcess(
      EnableGpuBrokerPolicyCallback,
      std::vector<std::string>(),  // No extra files in whitelist.
      std::vector<std::string>());

  if (IsArchitectureX86_64() || IsArchitectureI386()) {
    // Accelerated video decode dlopen()'s some shared objects
    // inside the sandbox, so preload them now.
    if (IsAcceleratedVideoDecodeEnabled()) {
      const char* I965DrvVideoPath = NULL;

      if (IsArchitectureX86_64()) {
        I965DrvVideoPath = "/usr/lib64/va/drivers/i965_drv_video.so";
      } else if (IsArchitectureI386()) {
        I965DrvVideoPath = "/usr/lib/va/drivers/i965_drv_video.so";
      }

      dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
      dlopen("libva.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
      dlopen("libva-x11.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
    }
  }

  return true;
}

void GpuProcessPolicy::InitGpuBrokerProcess(
    bool (*broker_sandboxer_callback)(void),
    const std::vector<std::string>& read_whitelist_extra,
    const std::vector<std::string>& write_whitelist_extra) {
  static const char kDriRcPath[] = "/etc/drirc";
  static const char kDriCard0Path[] = "/dev/dri/card0";

  CHECK(broker_process_ == NULL);

  // All GPU process policies need these files brokered out.
  std::vector<std::string> read_whitelist;
  read_whitelist.push_back(kDriCard0Path);
  read_whitelist.push_back(kDriRcPath);
  // Add eventual extra files from read_whitelist_extra.
  read_whitelist.insert(read_whitelist.end(),
                        read_whitelist_extra.begin(),
                        read_whitelist_extra.end());

  std::vector<std::string> write_whitelist;
  write_whitelist.push_back(kDriCard0Path);
  // Add eventual extra files from write_whitelist_extra.
  write_whitelist.insert(write_whitelist.end(),
                         write_whitelist_extra.begin(),
                         write_whitelist_extra.end());

  broker_process_ = new BrokerProcess(GetFSDeniedErrno(),
                                      read_whitelist,
                                      write_whitelist);
  // Initialize the broker process and give it a sandbox callback.
  CHECK(broker_process_->Init(broker_sandboxer_callback));
}

}  // namespace content
