// Copyright 2018 The Fuchsia 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 <lib/fzl/memory-probe.h>

#include <limits.h>
#include <stdio.h>
#include <zircon/assert.h>
#include <zircon/syscalls/exception.h>
#include <zircon/syscalls/port.h>
#include <lib/zx/port.h>
#include <lib/zx/process.h>
#include <lib/zx/thread.h>

namespace {

enum class ProbeOperation {
    kRead,
    kWrite
};

#if __has_feature(address_sanitizer)
[[clang::no_sanitize("address")]]
#endif
void except_thread_func(uintptr_t op, uintptr_t address) {
    volatile char* ch_address = reinterpret_cast<char*>(address);

    char ch = *ch_address;
    if (static_cast<ProbeOperation>(op) == ProbeOperation::kWrite)
        *ch_address = ch;

    zx_thread_exit();
}

bool do_probe(ProbeOperation op, const void* addr) {
    // This function starts a new thread to perform the read/write test, and catches any exceptions
    // in this thread to see if it failed or not.
    zx::thread thread;
    zx_status_t status = zx::thread::create(*zx::process::self(), "memory_probe", 12u, 0u, &thread);
    if (status != ZX_OK)
        return false;

    alignas(16) static uint8_t thread_stack[128];
    void* stack = thread_stack + sizeof(thread_stack);

    zx::port port;
    status = zx::port::create(0, &port);
    if (status != ZX_OK)
        return false;

    // Cause the port to be signaled with kThreadKey when the background thread crashes or teminates without crashing.
    constexpr uint64_t kThreadKey = 0x42;
    if (thread.wait_async(port, kThreadKey, ZX_THREAD_TERMINATED, ZX_WAIT_ASYNC_ONCE) != ZX_OK) {
        return false;
    }
    if (zx_task_bind_exception_port(thread.get(), port.get(), kThreadKey, 0) != ZX_OK) {
        return false;
    }

    thread.start(&except_thread_func, stack, static_cast<uintptr_t>(op), reinterpret_cast<uintptr_t>(addr));

    // Wait for crash or thread completion.
    zx_port_packet_t packet;
    if (port.wait(zx::time::infinite(), &packet) == ZX_OK) {
        if (ZX_PKT_IS_EXCEPTION(packet.type)) {
            // Thread crashed so the operation failed. The thread is now in a suspended state and
            // needs to be explicitly terminated.
            thread.kill();

            // Wait for the kill operation to complete so we don't
            // interrupt exception handling by closing port.
            // TODO(ZX-4105): Reexamine once killing and exceptions have defined interactions.
            zx_status_t status = port.wait(zx::time::infinite(), &packet);
            ZX_DEBUG_ASSERT(status == ZX_OK
                    && ZX_PKT_IS_SIGNAL_ONE(packet.type)
                    && packet.key == kThreadKey
                    && (packet.signal.observed & ZX_THREAD_TERMINATED));

            return false;
        }
        if (ZX_PKT_IS_SIGNAL_ONE(packet.type)) {
            if (packet.key == kThreadKey && (packet.signal.observed & ZX_THREAD_TERMINATED)) {
                // Thread terminated normally so the memory is readable/writable.
                return true;
            }
        }
    }

    return false;
}

} // namespace

bool probe_for_read(const void* addr) {
    return do_probe(ProbeOperation::kRead, addr);
}

bool probe_for_write(void* addr) {
    return do_probe(ProbeOperation::kWrite, addr);
}
