// Copyright (c) 2011 The Chromium OS 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 <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/callback.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/message_loop/message_pump_type.h>
#include <base/optional.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/system/sys_info.h>
#include <base/task/single_thread_task_executor.h>
#include <base/time/time.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/namespaces/mount_namespace.h>
#include <brillo/namespaces/platform.h>
#include <brillo/syslog_logging.h>
#include <chromeos/constants/cryptohome.h>
#include <chromeos-config/libcros_config/cros_config.h>
#include <linux/limits.h>
#include <rootdev/rootdev.h>

#include "login_manager/browser_job.h"
#include "login_manager/chrome_setup.h"
#include "login_manager/file_checker.h"
#include "login_manager/login_metrics.h"
#include "login_manager/regen_mitigator.h"
#include "login_manager/session_manager_service.h"
#include "login_manager/system_utils_impl.h"

using std::map;
using std::string;
using std::vector;

// Watches a Chrome binary and restarts it when it crashes. Also watches
// window manager binary as well. Actually supports watching several
// processes specified as command line arguments separated with --.
// Also listens over D-Bus for the commands specified in
// dbus_bindings/org.chromium.SessionManagerInterface.xml.

namespace switches {

// Name of the flag that contains the command for running Chrome.
static const char kChromeCommand[] = "chrome-command";
static const char kChromeCommandDefault[] = "/opt/google/chrome/chrome";

// Name of the flag that contains the path to the file which disables restart of
// managed jobs upon exit or crash if the file is present.
static const char kDisableChromeRestartFile[] = "disable-chrome-restart-file";
// The default path to this file.
static const char kDisableChromeRestartFileDefault[] =
    "/run/disable_chrome_restart";

// Flag that causes session manager to show the help message and exit.
static const char kHelp[] = "help";
// The help message shown if help flag is passed to the program.
static const char kHelpMessage[] =
    "\nAvailable Switches: \n"
    "  --chrome-command=</path/to/executable>\n"
    "    Path to the Chrome executable. Split along whitespace into arguments\n"
    "    (to which standard Chrome arguments will be appended); a value like\n"
    "    \"/usr/local/bin/strace /path/to/chrome\" may be used to wrap Chrome "
    "in\n"
    "    another program. (default: /opt/google/chrome/chrome)\n"
    "  --disable-chrome-restart-file=</path/to/file>\n"
    "    Magic file that causes this program to stop restarting the\n"
    "    chrome binary and exit. (default: /run/disable_chrome_restart)\n";
}  // namespace switches

using login_manager::BrowserJob;
using login_manager::BrowserJobInterface;
using login_manager::FileChecker;
using login_manager::LoginMetrics;
using login_manager::PerformChromeSetup;
using login_manager::SessionManagerService;
using login_manager::SystemUtilsImpl;

namespace {
// Directory in which per-boot metrics flag files will be stored.
constexpr char kFlagFileDir[] = "/run/session_manager";

// File to create the test mount namespace.
constexpr char kChromeTestNamespacePath[] = "/run/namespaces/test_ns";

// Hang-detection magic file and constants.
constexpr char kHangDetectionFlagFile[] = "enable_hang_detection";
constexpr base::TimeDelta kHangDetectionIntervalStable =
    base::TimeDelta::FromSeconds(60);
constexpr base::TimeDelta kHangDetectionIntervalDev =
    base::TimeDelta::FromSeconds(15);
constexpr base::TimeDelta kHangDetectionIntervalTest =
    base::TimeDelta::FromSeconds(5);

// Time to wait for children to exit gracefully before killing them
// with a SIGABRT.
constexpr int kKillTimeoutDefaultSeconds = 3;
constexpr int kKillTimeoutLongSeconds = 12;

bool BootDeviceIsRotationalDisk() {
  char full_rootdev_path[PATH_MAX];
  if (rootdev(full_rootdev_path, PATH_MAX - 1, true, true) != 0) {
    PLOG(WARNING) << "Couldn't find root device. Guessing it's not rotational.";
    return false;
  }
  CHECK(base::StartsWith(full_rootdev_path, "/dev/",
                         base::CompareCase::SENSITIVE));
  string device_only(full_rootdev_path + 5, PATH_MAX - 5);
  base::FilePath sysfs_path(base::StringPrintf("/sys/block/%s/queue/rotational",
                                               device_only.c_str()));
  string rotational_contents;
  if (!base::ReadFileToString(sysfs_path, &rotational_contents))
    PLOG(WARNING) << "Couldn't read from " << sysfs_path.value();
  return rotational_contents == "1";
}

// Enable further isolation of the user session (including the browser process
// tree), beyond merely running as user 'chronos'.
bool __attribute__((unused)) IsolateUserSession() {
#if USE_USER_SESSION_ISOLATION
  return true;
#else
  return false;
#endif
}
}  // namespace

int main(int argc, char* argv[]) {
  base::AtExitManager exit_manager;
  base::CommandLine::Init(argc, argv);
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader);

  // Allow waiting for all descendants, not just immediate children.
  if (::prctl(PR_SET_CHILD_SUBREAPER, 1))
    PLOG(ERROR) << "Couldn't set child subreaper";

  if (cl->HasSwitch(switches::kHelp)) {
    LOG(INFO) << switches::kHelpMessage;
    return 0;
  }

  // Parse the base Chrome command.
  string command_flag(switches::kChromeCommandDefault);
  if (cl->HasSwitch(switches::kChromeCommand))
    command_flag = cl->GetSwitchValueASCII(switches::kChromeCommand);
  vector<string> command =
      base::SplitString(command_flag, base::kWhitespaceASCII,
                        base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  // Set things up for running Chrome.
  std::unique_ptr<brillo::CrosConfig> cros_config =
      std::make_unique<brillo::CrosConfig>();
  if (!cros_config->Init())
    cros_config = nullptr;
  bool is_developer_end_user = false;
  map<string, string> env_var_map;
  vector<string> args, env_vars;
  uid_t uid = 0;
  PerformChromeSetup(cros_config.get(), &is_developer_end_user, &env_var_map,
                     &args, &uid);
  command.insert(command.end(), args.begin(), args.end());
  for (const auto& it : env_var_map)
    env_vars.push_back(it.first + "=" + it.second);

  // Shim that wraps system calls, file system ops, etc.
  SystemUtilsImpl system;

  // Checks magic file that causes the session_manager to stop managing the
  // browser process. Devs and tests can use this to keep the session_manager
  // running while stopping and starting the browser manaually.
  string magic_chrome_file =
      cl->GetSwitchValueASCII(switches::kDisableChromeRestartFile);
  if (magic_chrome_file.empty())
    magic_chrome_file.assign(switches::kDisableChromeRestartFileDefault);
  FileChecker checker((base::FilePath(magic_chrome_file)));  // So vexing!

  // Used to report various metrics around user type (guest vs non), dev-mode,
  // and policy/key file status.
  base::FilePath flag_file_dir(kFlagFileDir);
  if (!base::CreateDirectory(flag_file_dir))
    PLOG(FATAL) << "Cannot create flag file directory at " << kFlagFileDir;
  LoginMetrics metrics(flag_file_dir);

  // The session_manager supports pinging the browser periodically to check that
  // it is still alive. On developer systems, this would be a problem, as
  // debugging the browser would cause it to be aborted. desktopui_HangDetector
  // autotest uses the flag file to indicate that an abort is expected. We
  // tolerate shorter intervals for all non-stable channels.
  const bool hang_detection_file_exists =
      base::PathExists(flag_file_dir.Append(kHangDetectionFlagFile));
  const bool enable_hang_detection =
      !is_developer_end_user || hang_detection_file_exists;

  base::TimeDelta hang_detection_interval = kHangDetectionIntervalStable;
  std::string channel_string;
  if (base::SysInfo::GetLsbReleaseValue("CHROMEOS_RELEASE_TRACK",
                                        &channel_string) &&
      channel_string != "stable-channel") {
    hang_detection_interval = kHangDetectionIntervalDev;
  }
  if (hang_detection_file_exists)
    hang_detection_interval = kHangDetectionIntervalTest;

  // On platforms with rotational disks, Chrome takes longer to shut down. As
  // such, we need to change our baseline assumption about what "taking too long
  // to shutdown" means and wait for longer before killing Chrome and triggering
  // a report.
  int kill_timeout = kKillTimeoutDefaultSeconds;
  if (BootDeviceIsRotationalDisk())
    kill_timeout = kKillTimeoutLongSeconds;

  // Job configuration.
  BrowserJob::Config config;
  base::Optional<base::FilePath> ns_path;
  // TODO(crbug.com/188605, crbug.com/216789): Extend user session isolation and
  // make it stricter.
  // Back when the above bugs were filed, the interaction between
  // session_manager and Chrome was a lot simpler: Chrome would display the
  // login screen, the user would log in, and then session_manager would
  // relaunch Chrome after cryptohomed had mounted the user's encrypted home
  // directory.
  // Nowadays, big features like ARC and Crostini have added a lot of complexity
  // to the runtime environment of a logged-in Chrome OS user: there are nested
  // namespaces, bind mounts between them, and complex propagation of mount
  // points. Blindly putting the user session (i.e. the Chrome browser process
  // tree) in a bunch of namespaces is bound to subtly break things.
  // Start shaving this yak by isolating Guest mode sessions, which don't
  // support many of the above features. Put Guest mode process trees in a
  // non-root mount namespace to test the waters.
  // Extending the feature for regular user sessions is developed behind
  // the USE flag 'user_session_isolation'. If the flag is set Chrome will
  // be launched in a non-root mount namespace for regular sessions as well.
  config.isolate_guest_session = true;
  config.isolate_regular_session = IsolateUserSession();

  if (config.isolate_guest_session || config.isolate_regular_session) {
    // Instead of having Chrome unshare a new mount namespace on launch, have
    // Chrome enter the mount namespace where the user data directory exists.
    ns_path = base::FilePath(cryptohome::kUserSessionMountNamespacePath);
    config.chrome_mount_ns_path = ns_path;
  }

  brillo::Platform platform;
  std::unique_ptr<brillo::MountNamespace> chrome_mnt_ns;
  if (config.isolate_regular_session) {
    chrome_mnt_ns =
        std::make_unique<brillo::MountNamespace>(ns_path.value(), &platform);
    if (chrome_mnt_ns->Create()) {
      LOG(INFO) << "Mount namespace created at " << ns_path.value();
    } else {
      LOG(WARNING) << "Failed to create mount namespace at " << ns_path.value();
    }
  }

  // Chrome mount namespace is created by Cryptohome for Guest sessions. To
  // report the namespace creation metrics a mount namespace different from the
  // Chrome mount namespace is created. Therefore there is no possibility of
  // remounting on top of the Chrome mount namespace created by Cryptohome.
  // TODO(betuls): Change namespace metrics reporting to report the status of
  // the chrome_mnt_ns->Create() call above once USE flag is removed and user
  // session isolation is enabled by default.
  base::FilePath test_ns_path(kChromeTestNamespacePath);
  if (base::CreateTemporaryFile(&test_ns_path)) {
    brillo::MountNamespace test_mnt_ns(test_ns_path, &platform);
    bool status = test_mnt_ns.Create();
    metrics.SendNamespaceCreationResult(status);
  }

  // This job encapsulates the command specified on the command line, and the
  // runtime options for it.
  auto browser_job = std::make_unique<BrowserJob>(
      command, env_vars, &checker, &metrics, &system, config,
      std::make_unique<login_manager::Subprocess>(uid, &system));
  bool should_run_browser = browser_job->ShouldRunBrowser();

  base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::IO);
  brillo::BaseMessageLoop brillo_loop(task_executor.task_runner());
  brillo_loop.SetAsCurrent();

  scoped_refptr<SessionManagerService> manager = new SessionManagerService(
      std::move(browser_job), uid, ns_path, kill_timeout, enable_hang_detection,
      hang_detection_interval, &metrics, &system);

  if (manager->Initialize()) {
    // Allows devs to start/stop browser manually.
    if (should_run_browser) {
      brillo_loop.PostTask(
          FROM_HERE, base::Bind(&SessionManagerService::RunBrowser, manager));
    }
    // Returns when brillo_loop.BreakLoop() is called.
    brillo_loop.Run();
  }
  manager->Finalize();

  LOG_IF(WARNING, manager->exit_code() != SessionManagerService::SUCCESS)
      << "session_manager exiting with code " << manager->exit_code();
  return manager->exit_code();
}
