// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "handler/linux/exception_handler_server.h"

#include <sys/types.h>
#include <unistd.h>

#include "build/build_config.h"
#include "gtest/gtest.h"
#include "snapshot/linux/process_snapshot_linux.h"
#include "test/errors.h"
#include "test/multiprocess.h"
#include "util/linux/direct_ptrace_connection.h"
#include "util/linux/exception_handler_client.h"
#include "util/linux/ptrace_client.h"
#include "util/linux/scoped_pr_set_ptracer.h"
#include "util/misc/uuid.h"
#include "util/synchronization/semaphore.h"
#include "util/thread/thread.h"

#if defined(OS_ANDROID)
#include <android/api-level.h>
#endif

namespace crashpad {
namespace test {
namespace {

// Runs the ExceptionHandlerServer on a background thread.
class RunServerThread : public Thread {
 public:
  RunServerThread(ExceptionHandlerServer* server,
                  ExceptionHandlerServer::Delegate* delegate)
      : server_(server), delegate_(delegate), join_sem_(0) {}

  ~RunServerThread() override {}

  bool JoinWithTimeout(double timeout) {
    if (!join_sem_.TimedWait(timeout)) {
      return false;
    }
    Join();
    return true;
  }

 private:
  // Thread:
  void ThreadMain() override {
    server_->Run(delegate_);
    join_sem_.Signal();
  }

  ExceptionHandlerServer* server_;
  ExceptionHandlerServer::Delegate* delegate_;
  Semaphore join_sem_;

  DISALLOW_COPY_AND_ASSIGN(RunServerThread);
};

class ScopedStopServerAndJoinThread {
 public:
  ScopedStopServerAndJoinThread(ExceptionHandlerServer* server,
                                RunServerThread* thread)
      : server_(server), thread_(thread) {}

  ~ScopedStopServerAndJoinThread() {
    server_->Stop();
    EXPECT_TRUE(thread_->JoinWithTimeout(5.0));
  }

 private:
  ExceptionHandlerServer* server_;
  RunServerThread* thread_;

  DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread);
};

class TestDelegate : public ExceptionHandlerServer::Delegate {
 public:
  TestDelegate()
      : Delegate(), last_exception_address_(0), last_client_(-1), sem_(0) {}

  ~TestDelegate() {}

  bool WaitForException(double timeout_seconds,
                        pid_t* last_client,
                        VMAddress* last_address) {
    if (sem_.TimedWait(timeout_seconds)) {
      *last_client = last_client_;
      *last_address = last_exception_address_;
      return true;
    }

    return false;
  }

  bool HandleException(pid_t client_process_id,
                       uid_t client_uid,
                       const ExceptionHandlerProtocol::ClientInformation& info,
                       VMAddress requesting_thread_stack_address,
                       pid_t* requesting_thread_id = nullptr,
                       UUID* local_report_id = nullptr) override {
    DirectPtraceConnection connection;
    bool connected = connection.Initialize(client_process_id);
    EXPECT_TRUE(connected);

    last_exception_address_ = info.exception_information_address;
    last_client_ = client_process_id;
    sem_.Signal();
    if (!connected) {
      return false;
    }

    if (requesting_thread_id) {
      if (requesting_thread_stack_address) {
        ProcessSnapshotLinux process_snapshot;
        if (!process_snapshot.Initialize(&connection)) {
          ADD_FAILURE();
          return false;
        }
        *requesting_thread_id = process_snapshot.FindThreadWithStackAddress(
            requesting_thread_stack_address);
      } else {
        *requesting_thread_id = -1;
      }
    }
    return true;
  }

  bool HandleExceptionWithBroker(
      pid_t client_process_id,
      uid_t client_uid,
      const ExceptionHandlerProtocol::ClientInformation& info,
      int broker_sock,
      UUID* local_report_id = nullptr) override {
    PtraceClient client;
    bool connected = client.Initialize(broker_sock, client_process_id);
    EXPECT_TRUE(connected);

    last_exception_address_ = info.exception_information_address,
    last_client_ = client_process_id;
    sem_.Signal();
    return connected;
  }

 private:
  VMAddress last_exception_address_;
  pid_t last_client_;
  Semaphore sem_;

  DISALLOW_COPY_AND_ASSIGN(TestDelegate);
};

class MockPtraceStrategyDecider : public PtraceStrategyDecider {
 public:
  MockPtraceStrategyDecider(PtraceStrategyDecider::Strategy strategy)
      : PtraceStrategyDecider(), strategy_(strategy) {}

  ~MockPtraceStrategyDecider() {}

  Strategy ChooseStrategy(int sock,
                          bool multiple_clients,
                          const ucred& client_credentials) override {
    if (strategy_ == Strategy::kUseBroker) {
      ExceptionHandlerProtocol::ServerToClientMessage message = {};
      message.type =
          ExceptionHandlerProtocol::ServerToClientMessage::kTypeForkBroker;

      ExceptionHandlerProtocol::Errno status;
      bool result = LoggingWriteFile(sock, &message, sizeof(message)) &&
                    LoggingReadFileExactly(sock, &status, sizeof(status));
      EXPECT_TRUE(result);

      if (!result) {
        return Strategy::kError;
      }

      if (status != 0) {
        errno = status;
        ADD_FAILURE() << ErrnoMessage("Handler Client ForkBroker");
        return Strategy::kNoPtrace;
      }
    }
    return strategy_;
  }

 private:
  Strategy strategy_;

  DISALLOW_COPY_AND_ASSIGN(MockPtraceStrategyDecider);
};

class ExceptionHandlerServerTest : public testing::TestWithParam<bool> {
 public:
  ExceptionHandlerServerTest()
      : server_(),
        delegate_(),
        server_thread_(&server_, &delegate_),
        sock_to_handler_(),
        use_multi_client_socket_(GetParam()) {}

  ~ExceptionHandlerServerTest() = default;

  int SockToHandler() { return sock_to_handler_.get(); }

  TestDelegate* Delegate() { return &delegate_; }

  void Hangup() { sock_to_handler_.reset(); }

  RunServerThread* ServerThread() { return &server_thread_; }

  ExceptionHandlerServer* Server() { return &server_; }

  class CrashDumpTest : public Multiprocess {
   public:
    CrashDumpTest(ExceptionHandlerServerTest* server_test, bool succeeds)
        : Multiprocess(), server_test_(server_test), succeeds_(succeeds) {}

    ~CrashDumpTest() = default;

    void MultiprocessParent() override {
      ExceptionHandlerProtocol::ClientInformation info;
      ASSERT_TRUE(
          LoggingReadFileExactly(ReadPipeHandle(), &info, sizeof(info)));

      if (succeeds_) {
        VMAddress last_address;
        pid_t last_client;
        ASSERT_TRUE(server_test_->Delegate()->WaitForException(
            5.0, &last_client, &last_address));
        EXPECT_EQ(last_address, info.exception_information_address);
        EXPECT_EQ(last_client, ChildPID());
      } else {
        CheckedReadFileAtEOF(ReadPipeHandle());
      }
    }

    void MultiprocessChild() override {
      ASSERT_EQ(close(server_test_->sock_to_client_), 0);

      ExceptionHandlerProtocol::ClientInformation info;
      info.exception_information_address = 42;
      ASSERT_TRUE(LoggingWriteFile(WritePipeHandle(), &info, sizeof(info)));

      // If the current ptrace_scope is restricted, the broker needs to be set
      // as the ptracer for this process. Setting this process as its own
      // ptracer allows the broker to inherit this condition.
      ScopedPrSetPtracer set_ptracer(getpid(), /* may_log= */ true);

      ExceptionHandlerClient client(server_test_->SockToHandler(),
                                    server_test_->use_multi_client_socket_);
      ASSERT_EQ(client.RequestCrashDump(info), 0);
    }

   private:
    ExceptionHandlerServerTest* server_test_;
    bool succeeds_;

    DISALLOW_COPY_AND_ASSIGN(CrashDumpTest);
  };

  void ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy strategy,
                                    bool succeeds) {
    Server()->SetPtraceStrategyDecider(
        std::make_unique<MockPtraceStrategyDecider>(strategy));

    ScopedStopServerAndJoinThread stop_server(Server(), ServerThread());
    ServerThread()->Start();

    CrashDumpTest test(this, succeeds);
    test.Run();
  }

  bool UsingMultiClientSocket() const { return use_multi_client_socket_; }

 protected:
  void SetUp() override {
    int socks[2];
    ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, socks), 0);
    sock_to_handler_.reset(socks[0]);
    sock_to_client_ = socks[1];

    ASSERT_TRUE(server_.InitializeWithClient(ScopedFileHandle(socks[1]),
                                             use_multi_client_socket_));
  }

 private:
  ExceptionHandlerServer server_;
  TestDelegate delegate_;
  RunServerThread server_thread_;
  ScopedFileHandle sock_to_handler_;
  int sock_to_client_;
  bool use_multi_client_socket_;

  DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServerTest);
};

TEST_P(ExceptionHandlerServerTest, ShutdownWithNoClients) {
  ServerThread()->Start();
  Hangup();
  ASSERT_TRUE(ServerThread()->JoinWithTimeout(5.0));
}

TEST_P(ExceptionHandlerServerTest, StopWithClients) {
  ServerThread()->Start();
  Server()->Stop();
  ASSERT_TRUE(ServerThread()->JoinWithTimeout(5.0));
}

TEST_P(ExceptionHandlerServerTest, StopBeforeRun) {
  Server()->Stop();
  ServerThread()->Start();
  ASSERT_TRUE(ServerThread()->JoinWithTimeout(5.0));
}

TEST_P(ExceptionHandlerServerTest, MultipleStops) {
  ServerThread()->Start();
  Server()->Stop();
  Server()->Stop();
  ASSERT_TRUE(ServerThread()->JoinWithTimeout(5.0));
}

TEST_P(ExceptionHandlerServerTest, RequestCrashDumpDefault) {
  ScopedStopServerAndJoinThread stop_server(Server(), ServerThread());
  ServerThread()->Start();

  CrashDumpTest test(this, true);
  test.Run();
}

TEST_P(ExceptionHandlerServerTest, RequestCrashDumpNoPtrace) {
  ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy::kNoPtrace,
                               false);
}

TEST_P(ExceptionHandlerServerTest, RequestCrashDumpForkBroker) {
  if (UsingMultiClientSocket()) {
    // The broker is not supported with multiple clients connected on a single
    // socket.
    return;
  }
  ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy::kUseBroker,
                               true);
}

TEST_P(ExceptionHandlerServerTest, RequestCrashDumpDirectPtrace) {
  ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy::kDirectPtrace,
                               true);
}

TEST_P(ExceptionHandlerServerTest, RequestCrashDumpError) {
  ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy::kError, false);
}

INSTANTIATE_TEST_SUITE_P(ExceptionHandlerServerTestSuite,
                         ExceptionHandlerServerTest,
                         testing::Bool()
);

}  // namespace
}  // namespace test
}  // namespace crashpad
