// Copyright 2026 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 <fcntl.h>
#include <sys/fsuid.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string>

#include "src/lib/files/file.h"
#include "src/lib/files/path.h"
#include "src/starnix/tests/syscalls/cpp/test_helper.h"

namespace {

constexpr int kOutputFd = 100;
constexpr uid_t kTestUid = 65533;
constexpr gid_t kTestGid = 65534;

std::string GetCredsBinaryPath() {
  std::string test_binary = "data/tests/deps/print_uid_gid_exec_child";
  if (!files::IsFile(test_binary)) {
    // We're running on host
    char self_path[PATH_MAX];
    realpath("/proc/self/exe", self_path);

    test_binary = files::JoinPath(files::GetDirectoryName(self_path), "print_uid_gid_exec_child");
  }
  return test_binary;
}

}  // namespace

TEST(ExecTest, FsuidFsgidResetOnExec) {
  if (!test_helper::HasSysAdmin()) {
    GTEST_SKIP() << "Not running with sysadmin capabilities, skipping.";
  }

  std::string creds_binary = GetCredsBinaryPath();

  int fd = SAFE_SYSCALL(test_helper::MemFdCreate("creds", O_RDWR));

  test_helper::ForkHelper helper;
  helper.RunInForkedProcess([&] {
    SAFE_SYSCALL(dup2(fd, kOutputFd));

    // We start as root (ruid=0, euid=0, fsuid=0).
    // We want to set euid to kTestUid, but keep fsuid as 0.
    // This allows us to execute the root-owned (700) helper binary,
    // while still testing that fsuid is reset to euid (kTestUid) on exec.

    SAFE_SYSCALL(setegid(kTestGid));
    SAFE_SYSCALL(seteuid(kTestUid));

    // seteuid/setegid also set fsuid/fsgid to the new euid/egid.
    // We explicitly set them back to 0 (root).
    // This is allowed because our real UID/GID are still 0.
    ASSERT_EQ(setfsuid(0), static_cast<int>(kTestUid));
    ASSERT_EQ(setfsgid(0), static_cast<int>(kTestGid));

    // Verify the state before exec.
    uid_t ruid, euid, suid;
    SAFE_SYSCALL(getresuid(&ruid, &euid, &suid));
    ASSERT_EQ(ruid, 0U);
    ASSERT_EQ(euid, kTestUid);

    gid_t rgid, egid, sgid;
    SAFE_SYSCALL(getresgid(&rgid, &egid, &sgid));
    ASSERT_EQ(rgid, 0U);
    ASSERT_EQ(egid, kTestGid);

    ASSERT_EQ(setfsuid(-1), 0);
    ASSERT_EQ(setfsgid(-1), 0);

    char *const argv[] = {const_cast<char *>(creds_binary.c_str()), nullptr};
    execve(creds_binary.c_str(), argv, nullptr);
    perror("execve");
    _exit(EXIT_FAILURE);
  });

  ASSERT_TRUE(helper.WaitForChildren());

  SAFE_SYSCALL(lseek(fd, 0, SEEK_SET));
  FILE *fp = fdopen(fd, "r");
  ASSERT_NE(fp, nullptr);

  uid_t ruid, euid, suid;
  EXPECT_EQ(fscanf(fp, "ruid: %u euid: %u suid: %u\n", &ruid, &euid, &suid), 3);
  EXPECT_EQ(ruid, 0U);
  EXPECT_EQ(euid, kTestUid);

  gid_t rgid, egid, sgid;
  EXPECT_EQ(fscanf(fp, "rgid: %u egid: %u sgid: %u\n", &rgid, &egid, &sgid), 3);
  EXPECT_EQ(rgid, 0U);
  EXPECT_EQ(egid, kTestGid);

  int fsuid, fsgid;
  EXPECT_EQ(fscanf(fp, "fsuid: %d fsgid: %d\n", &fsuid, &fsgid), 2);
  // fsuid/fsgid should have been reset to euid/egid (kTestUid/kTestGid) on exec,
  // even though they were 0 before exec.
  EXPECT_EQ(fsuid, static_cast<int>(kTestUid));
  EXPECT_EQ(fsgid, static_cast<int>(kTestGid));

  fclose(fp);
}
