/*
 * Copyright (C) 2017 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 <linux/futex.h>
#include <pthread.h>
#include <sys/stat.h>
#include <unistd.h>

#include <atomic>
#include <chrono>
#include <string>
#include <thread>
#include <vector>

#include <android-base/file.h>
#include <android-base/scopeguard.h>
#include <gtest/gtest.h>
#include <selinux/android.h>
#include <selinux/label.h>
#include <selinux/selinux.h>

using namespace std::chrono_literals;
using namespace std::string_literals;

template <typename T, typename F>
void WriteFromMultipleThreads(std::vector<std::pair<std::string, T>>& files_and_parameters,
                              F function) {
    auto num_threads = files_and_parameters.size();
    pthread_barrier_t barrier;
    pthread_barrier_init(&barrier, nullptr, num_threads);
    auto barrier_destroy =
        android::base::make_scope_guard([&barrier]() { pthread_barrier_destroy(&barrier); });

    auto make_thread_function = [&function, &barrier](const auto& file, const auto& parameter) {
        return [&]() {
            function(parameter);
            pthread_barrier_wait(&barrier);
            android::base::WriteStringToFile("<empty>", file);
        };
    };

    std::vector<std::thread> threads;
    // TODO(b/63712782): Structured bindings + templated containers are broken in clang :(
    // for (const auto& [file, parameter] : files_and_parameters) {
    for (const auto& pair : files_and_parameters) {
        const auto& file = pair.first;
        const auto& parameter = pair.second;
        threads.emplace_back(std::thread(make_thread_function(file, parameter)));
    }

    for (auto& thread : threads) {
        thread.join();
    }
}

TEST(ueventd, setegid_IsPerThread) {
    if (getuid() != 0) {
        GTEST_SKIP() << "Skipping test, must be run as root.";
        return;
    }

    TemporaryDir dir;

    gid_t gid = 0;
    std::vector<std::pair<std::string, gid_t>> files_and_gids;
    std::generate_n(std::back_inserter(files_and_gids), 100, [&gid, &dir]() {
        gid++;
        return std::pair(dir.path + "/gid_"s + std::to_string(gid), gid);
    });

    WriteFromMultipleThreads(files_and_gids, [](gid_t gid) { EXPECT_EQ(0, setegid(gid)); });

    for (const auto& [file, expected_gid] : files_and_gids) {
        struct stat info;
        ASSERT_EQ(0, stat(file.c_str(), &info));
        EXPECT_EQ(expected_gid, info.st_gid);
    }
}

TEST(ueventd, setfscreatecon_IsPerThread) {
    if (getuid() != 0) {
        GTEST_SKIP() << "Skipping test, must be run as root.";
        return;
    }
    if (!is_selinux_enabled() || security_getenforce() == 1) {
        GTEST_SKIP() << "Skipping test, SELinux must be enabled and in permissive mode.";
        return;
    }

    const char* const contexts[] = {
        "u:object_r:audio_device:s0",
        "u:object_r:sensors_device:s0",
        "u:object_r:video_device:s0"
        "u:object_r:zero_device:s0",
    };

    TemporaryDir dir;
    std::vector<std::pair<std::string, std::string>> files_and_contexts;
    for (const char* context : contexts) {
        files_and_contexts.emplace_back(dir.path + "/context_"s + context, context);
    }

    WriteFromMultipleThreads(files_and_contexts, [](const std::string& context) {
        EXPECT_EQ(0, setfscreatecon(context.c_str()));
    });

    for (const auto& [file, expected_context] : files_and_contexts) {
        char* file_context;
        ASSERT_GT(getfilecon(file.c_str(), &file_context), 0);
        EXPECT_EQ(expected_context, file_context);
        freecon(file_context);
    }
}

TEST(ueventd, selabel_lookup_MultiThreaded) {
    if (getuid() != 0) {
        GTEST_SKIP() << "Skipping test, must be run as root.";
        return;
    }

    // Test parameters
    constexpr auto num_threads = 10;
    constexpr auto run_time = 200ms;

    std::unique_ptr<selabel_handle, decltype(&selabel_close)> sehandle(
        selinux_android_file_context_handle(), &selabel_close);

    ASSERT_TRUE(sehandle);

    struct {
        const char* file;
        int mode;
        std::string expected_context;
    } files_and_modes[] = {
        {"/dev/zero", 020666, ""},
        {"/dev/null", 020666, ""},
        {"/dev/random", 020666, ""},
        {"/dev/urandom", 020666, ""},
    };

    // Precondition, ensure that we can lookup all of these from a single thread, and store the
    // expected context for each.
    for (size_t i = 0; i < arraysize(files_and_modes); ++i) {
        char* secontext;
        ASSERT_EQ(0, selabel_lookup(sehandle.get(), &secontext, files_and_modes[i].file,
                                    files_and_modes[i].mode));
        files_and_modes[i].expected_context = secontext;
        freecon(secontext);
    }

    // Now that we know we can access them, and what their context should be, run in parallel.
    std::atomic_bool stopped = false;
    std::atomic_uint num_api_failures = 0;
    std::atomic_uint num_context_check_failures = 0;
    std::atomic_uint num_successes = 0;

    auto thread_function = [&]() {
        while (!stopped) {
            for (size_t i = 0; i < arraysize(files_and_modes); ++i) {
                char* secontext;
                int result = selabel_lookup(sehandle.get(), &secontext, files_and_modes[i].file,
                                            files_and_modes[i].mode);
                if (result != 0) {
                    num_api_failures++;
                } else {
                    if (files_and_modes[i].expected_context != secontext) {
                        num_context_check_failures++;
                    } else {
                        num_successes++;
                    }
                    freecon(secontext);
                }
            }
        }
    };

    std::vector<std::thread> threads;
    std::generate_n(back_inserter(threads), num_threads,
                    [&]() { return std::thread(thread_function); });

    std::this_thread::sleep_for(run_time);
    stopped = true;
    for (auto& thread : threads) {
        thread.join();
    }

    EXPECT_EQ(0U, num_api_failures);
    EXPECT_EQ(0U, num_context_check_failures);
    EXPECT_GT(num_successes, 0U);
}
