/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <chrono>
#include <iostream>
#include <string>

#include <android-base/properties.h>
#include <gtest/gtest.h>
#include <log/log_time.h>  // for MS_PER_SEC and US_PER_SEC

#include "llkd.h"

using namespace std::chrono;
using namespace std::chrono_literals;

namespace {

milliseconds GetUintProperty(const std::string& key, milliseconds def) {
    return milliseconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
                                                       static_cast<uint64_t>(def.max().count())));
}

seconds GetUintProperty(const std::string& key, seconds def) {
    return seconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
                                                  static_cast<uint64_t>(def.max().count())));
}

// GTEST_LOG_(WARNING) output is fugly, this has much less noise
// ToDo: look into fixing googletest to produce output that matches style of
//       all the other status messages, and can switch off __line__ and
//       __function__ noise
#define GTEST_LOG_WARNING std::cerr << "[ WARNING  ] "
#define GTEST_LOG_INFO std::cerr << "[   INFO   ] "

// Properties is _not_ a high performance ABI!
void rest() {
    usleep(200000);
}

void execute(const char* command) {
    if (getuid() || system(command)) {
        system((std::string("su root ") + command).c_str());
    }
}

seconds llkdSleepPeriod(char state) {
    auto default_eng = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
    auto default_enable = LLK_ENABLE_DEFAULT;
    if (!LLK_ENABLE_DEFAULT && default_eng &&
        android::base::GetBoolProperty("ro.debuggable", false)) {
        default_enable = true;
    }
    default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
    if (default_eng) {
        GTEST_LOG_INFO << LLK_ENABLE_PROPERTY " defaults to \"eng\" thus "
                       << (default_enable ? "true" : "false") << "\n";
    }
    // Hail Mary hope is unconfigured.
    if ((GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, LLK_TIMEOUT_MS_DEFAULT) !=
         duration_cast<milliseconds>(120s)) ||
        (GetUintProperty(LLK_CHECK_MS_PROPERTY,
                         LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
         duration_cast<milliseconds>(10s))) {
        execute("stop llkd-0");
        execute("stop llkd-1");
        rest();
        std::string setprop("setprop ");
        // Manually check that SyS_openat is _added_ to the list when restarted
        execute((setprop + LLK_CHECK_STACK_PROPERTY + " ,SyS_openat").c_str());
        rest();
        execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
        rest();
        execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
        rest();
        execute((setprop + KHT_TIMEOUT_PROPERTY + " 130").c_str());
        rest();
        execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
        rest();
        if (!default_enable) {
            execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
            rest();
        }
        execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
        rest();
    }
    default_enable = LLK_ENABLE_DEFAULT;
    if (!LLK_ENABLE_DEFAULT && (android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng") &&
        android::base::GetBoolProperty("ro.debuggable", false)) {
        default_enable = true;
    }
    default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
    if (default_enable) {
        execute("start llkd-1");
        rest();
        GTEST_LOG_INFO << "llkd enabled\n";
    } else {
        GTEST_LOG_WARNING << "llkd disabled\n";
    }

    /* KISS follows llk_init() */
    milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
    seconds khtTimeout = duration_cast<seconds>(
        llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) / LLK_CHECKS_PER_TIMEOUT_DEFAULT);
    khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
    llkTimeoutMs =
        khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
    llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
    if (llkTimeoutMs < LLK_TIMEOUT_MS_MINIMUM) {
        llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
    }
    milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
    auto timeout = GetUintProperty((state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY
                                                  : (state == 'S') ? LLK_STACK_TIMEOUT_MS_PROPERTY
                                                                   : LLK_D_TIMEOUT_MS_PROPERTY,
                                   llkTimeoutMs);
    if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
        timeout = LLK_TIMEOUT_MS_MINIMUM;
    }

    if (llkCheckMs > timeout) {
        llkCheckMs = timeout;
    }
    llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
    timeout += llkCheckMs;
    auto sec = duration_cast<seconds>(timeout);
    if (sec == 0s) {
        ++sec;
    } else if (sec > 59s) {
        GTEST_LOG_WARNING << "llkd is configured for about " << duration_cast<minutes>(sec).count()
                          << " minutes to react\n";
    }

    // 33% margin for the test to naturally timeout waiting for llkd to respond
    return (sec * 4 + 2s) / 3;
}

inline void waitForPid(pid_t child_pid) {
    int wstatus;
    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
    EXPECT_FALSE(WIFEXITED(wstatus)) << "[   INFO   ] exit=" << WEXITSTATUS(wstatus);
    ASSERT_TRUE(WIFSIGNALED(wstatus));
    ASSERT_EQ(WTERMSIG(wstatus), SIGKILL);
}

bool checkKill(const char* reason) {
    if (android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, LLK_KILLTEST_DEFAULT)) {
        return false;
    }
    auto bootreason = android::base::GetProperty("sys.boot.reason", "nothing");
    if (bootreason == reason) {
        GTEST_LOG_INFO << "Expected test result confirmed " << reason << "\n";
        return true;
    }
    GTEST_LOG_WARNING << "Expected test result is " << reason << "\n";

    // apct adjustment if needed (set LLK_KILLTEST_PROPERTY to "off" to allow test)
    //
    // if (android::base::GetProperty(LLK_KILLTEST_PROPERTY, "") == "false") {
    //     GTEST_LOG_WARNING << "Bypassing test\n";
    //     return true;
    // }

    return false;
}

}  // namespace

// The tests that use this helper are to simulate processes stuck in 'D'
// state that are experiencing forward scheduled progress. As such the
// expectation is that llkd will _not_ perform any mitigations. The sleepfor
// argument helps us set the amount of forward scheduler progress.
static void llkd_driver_ABA(const microseconds sleepfor) {
    const auto period = llkdSleepPeriod('D');
    if (period <= sleepfor) {
        GTEST_LOG_WARNING << "llkd configuration too short for "
                          << duration_cast<milliseconds>(sleepfor).count() << "ms work cycle\n";
        return;
    }

    auto child_pid = fork();
    ASSERT_LE(0, child_pid);
    int wstatus;
    if (!child_pid) {
        auto ratio = period / sleepfor;
        ASSERT_LT(0, ratio);
        // vfork() parent is uninterruptable D state waiting for child to exec()
        while (--ratio > 0) {
            auto driver_pid = vfork();
            ASSERT_LE(0, driver_pid);
            if (driver_pid) {  // parent
                waitpid(driver_pid, &wstatus, 0);
                if (!WIFEXITED(wstatus)) {
                    exit(42);
                }
                if (WEXITSTATUS(wstatus) != 42) {
                    exit(42);
                }
            } else {
                usleep(sleepfor.count());
                exit(42);
            }
        }
        exit(0);
    }
    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
    EXPECT_TRUE(WIFEXITED(wstatus));
    if (WIFEXITED(wstatus)) {
        EXPECT_EQ(0, WEXITSTATUS(wstatus));
    }
    ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[   INFO   ] signo=" << WTERMSIG(wstatus);
}

TEST(llkd, driver_ABA_fast) {
    llkd_driver_ABA(5ms);
}

TEST(llkd, driver_ABA_slow) {
    llkd_driver_ABA(1s);
}

TEST(llkd, driver_ABA_glacial) {
    llkd_driver_ABA(1min);
}

// Following tests must be last in this file to capture possible errant
// kernel_panic mitigation failure.

// The following tests simulate processes stick in 'Z' or 'D' state with
// no forward scheduling progress, but interruptible. As such the expectation
// is that llkd will perform kill mitigation and not progress to kernel_panic.

TEST(llkd, zombie) {
    if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
        return;
    }

    const auto period = llkdSleepPeriod('Z');

    /* Create a Persistent Zombie Process */
    pid_t child_pid = fork();
    ASSERT_LE(0, child_pid);
    if (!child_pid) {
        auto zombie_pid = fork();
        ASSERT_LE(0, zombie_pid);
        if (!zombie_pid) {
            sleep(1);
            exit(0);
        }
        sleep(period.count());
        exit(42);
    }

    waitForPid(child_pid);
}

TEST(llkd, driver) {
    if (checkKill("kernel_panic,sysrq,livelock,driver")) {
        return;
    }

    const auto period = llkdSleepPeriod('D');

    /* Create a Persistent Device Process */
    auto child_pid = fork();
    ASSERT_LE(0, child_pid);
    if (!child_pid) {
        // vfork() parent is uninterruptable D state waiting for child to exec()
        auto driver_pid = vfork();
        ASSERT_LE(0, driver_pid);
        sleep(period.count());
        exit(driver_pid ? 42 : 0);
    }

    waitForPid(child_pid);
}

TEST(llkd, sleep) {
    if (checkKill("kernel_panic,sysrq,livelock,sleeping")) {
        return;
    }
    if (!android::base::GetBoolProperty("ro.debuggable", false)) {
        GTEST_LOG_WARNING << "Features not available on user builds\n";
    }

    const auto period = llkdSleepPeriod('S');

    /* Create a Persistent SyS_openat for single-ended pipe */
    static constexpr char stack_pipe_file[] = "/dev/stack_pipe_file";
    unlink(stack_pipe_file);
    auto pipe_ret = mknod(stack_pipe_file, S_IFIFO | 0666, 0);
    ASSERT_LE(0, pipe_ret);

    auto child_pid = fork();
    ASSERT_LE(0, child_pid);
    if (!child_pid) {
        child_pid = fork();
        ASSERT_LE(0, child_pid);
        if (!child_pid) {
            sleep(period.count());
            auto fd = open(stack_pipe_file, O_RDONLY | O_CLOEXEC);
            close(fd);
            exit(0);
        } else {
            auto fd = open(stack_pipe_file, O_WRONLY | O_CLOEXEC);
            close(fd);
            exit(42);
        }
    }

    waitForPid(child_pid);

    unlink(stack_pipe_file);
}

// b/120983740
TEST(llkd, adbd_and_setsid) {
    if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
        return;
    }
    const auto period = llkdSleepPeriod('S');

    // expect llkd.zombie to trigger, but not for adbd&[setsid]
    // Create a Persistent Zombie setsid Process
    pid_t child_pid = fork();
    ASSERT_LE(0, child_pid);
    if (!child_pid) {
        prctl(PR_SET_NAME, "adbd");
        auto zombie_pid = fork();
        ASSERT_LE(0, zombie_pid);
        if (!zombie_pid) {
            prctl(PR_SET_NAME, "setsid");
            sleep(1);
            exit(0);
        }
        sleep(period.count());
        exit(42);
    }

    // Reverse of waitForPid, do _not_ expect kill
    int wstatus;
    ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
    EXPECT_TRUE(WIFEXITED(wstatus));
    if (WIFEXITED(wstatus)) {
        EXPECT_EQ(42, WEXITSTATUS(wstatus));
    }
    ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[   INFO   ] signo=" << WTERMSIG(wstatus);
}
