Logo Search packages:      
Sourcecode: schroot version File versions  Download package

void session::run_child ( chroot::ptr session_chroot  )  [private]

Run a command or login shell as a child process in the specified chroot. This method is only ever to be run in a child process, and will never return.

Parameters:
session_chroot the chroot to setup. This must be present in the chroot list and the chroot configuration object.

Definition at line 625 of file sbuild-session.cc.

References sbuild::auth::command, exec(), sbuild::auth::get_command(), sbuild::auth::get_environment(), sbuild::auth::get_gid(), sbuild::auth::get_pam_environment(), sbuild::auth::get_ruid(), sbuild::auth::get_ruser(), sbuild::auth::get_shell(), sbuild::auth::get_uid(), sbuild::auth::get_user(), sbuild::auth::get_verbosity(), sbuild::auth::open_session(), sbuild::auth::pam, and sbuild::auth::VERBOSITY_QUIET.

Referenced by run_chroot().

{
  assert(!session_chroot->get_name().empty());

  assert(!get_user().empty());
  assert(!get_shell().empty());
  assert(auth::pam != NULL); // PAM must be initialised

  std::string location(session_chroot->get_path());
  std::string cwd;
  {
    char *raw_cwd = getcwd (NULL, 0);
    if (raw_cwd)
      cwd = raw_cwd;
    else
      cwd = "/";
    free(raw_cwd);
  }

  /* Child errors result in immediate exit().  Errors are not
     propagated back via an exception, because there is no longer any
     higher-level handler to catch them. */
  try
    {
      open_session();
    }
  catch (auth::error const& e)
    {
      log_error() << format(_("PAM error: %1%")) % e.what()
              << endl;
      exit (EXIT_FAILURE);
    }

  /* Set group ID and supplementary groups */
  if (setgid (get_gid()))
    {
      log_error() << format(_("Could not set gid to '%1%'")) % get_gid()
              << endl;
      exit (EXIT_FAILURE);
    }
  if (initgroups (get_user().c_str(), get_gid()))
    {
      log_error() << _("Could not set supplementary group IDs") << endl;
      exit (EXIT_FAILURE);
    }

  /* Enter the chroot */
  if (chdir (location.c_str()))
    {
      log_error() << format(_("Could not chdir to '%1%': %2%"))
      % location % strerror(errno)
              << endl;
      exit (EXIT_FAILURE);
    }
  if (::chroot (location.c_str()))
    {
      log_error() << format(_("Could not chroot to '%1%': %2%"))
      % location % strerror(errno)
              << endl;
      exit (EXIT_FAILURE);
    }

  /* Set uid and check we are not still root */
  if (setuid (get_uid()))
    {
      log_error() << format(_("Could not set uid to '%1%'")) % get_uid()
              << endl;
      exit (EXIT_FAILURE);
    }
  if (!setuid (0) && get_uid())
    {
      log_error() << _("Failed to drop root permissions.")
              << endl;
      exit (EXIT_FAILURE);
    }

  /* chdir to current directory */
  if (chdir (cwd.c_str()))
    {
      log_warning() << format(_("Could not chdir to '%1%': %2%"))
      % cwd % strerror(errno)
             << endl;
    }

  /* Set up environment */
  environment env = get_pam_environment();
    log_debug(DEBUG_INFO)
      << "Set environment:\n" << env;

  /* Run login shell */
  std::string file;

  string_list command(get_command());

  if (command.empty() ||
      command[0].empty()) // No command
    {
      assert (!get_shell().empty());

      file = get_shell();
      if (get_environment().empty() &&
        session_chroot->get_command_prefix().empty())
      // Not keeping environment and can setup argv correctly; login shell
      {
        std::string shellbase = basename(get_shell(), '/');
        std::string loginshell = "-" + shellbase;
        command.push_back(loginshell);
        log_debug(DEBUG_INFO)
          << format("Login shell: %1%") % command[0] << endl;
      }
      else
      {
        command.push_back(get_shell());
      }

      if (get_environment().empty() &&
        session_chroot->get_command_prefix().empty())
      {
        log_debug(DEBUG_NOTICE)
          << format("Running login shell: %1%") % get_shell() << endl;
        syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running login shell: \"%s\"",
             session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), get_shell().c_str());
      }
      else
      {
        log_debug(DEBUG_NOTICE)
          << format("Running shell: %1%") % get_shell() << endl;
        syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running shell: \"%s\"",
             session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), get_shell().c_str());
      }

      if (get_verbosity() != auth::VERBOSITY_QUIET)
      {
        if (get_ruid() == get_uid())
          log_info()
            << format((get_environment().empty() &&
                   session_chroot->get_command_prefix().empty() ?
                   _("[%1% chroot] Running login shell: \"%2%\"") :
                   _("[%1% chroot] Running shell: \"%2%\"")))
            % session_chroot->get_name() % get_shell()
            << endl;
        else
          log_info()
            << format((get_environment().empty() &&
                   session_chroot->get_command_prefix().empty() ?
                   _("[%1% chroot] (%2%->%3%) Running login shell: \"%4%\"") :
                   _("[%1% chroot] (%2%->%3%) Running shell: \"%4%\"")))
            % session_chroot->get_name()
            % get_ruser() % get_user()
            % get_shell()
            << endl;
      }
    }
  else
    {
      /* Search for program in path. */
      file = find_program_in_path(command[0], getenv("PATH"), "");
      if (file.empty())
      file = command[0];
      std::string commandstring = string_list_to_string(command, " ");
      log_debug(DEBUG_NOTICE)
      << format("Running command: %1%") % commandstring << endl;
      syslog(LOG_USER|LOG_NOTICE, "[%s chroot] (%s->%s) Running command: \"%s\"",
           session_chroot->get_name().c_str(), get_ruser().c_str(), get_user().c_str(), commandstring.c_str());
      if (get_verbosity() != auth::VERBOSITY_QUIET)
      {
        if (get_ruid() == get_uid())
          log_info() << format(_("[%1% chroot] Running command: \"%2%\""))
            % session_chroot->get_name() % commandstring
                   << endl;
        else
          log_info() << format(_("[%1% chroot] (%2%->%3%) Running command: \"%4%\""))
            % session_chroot->get_name()
            % get_ruser() % get_user()
            % commandstring
                   << endl;
      }
    }

  // The user's command does not use our syslog fd.
  closelog();

  // Add command prefix.
  string_list full_command(session_chroot->get_command_prefix());
  if (full_command.size() > 0)
    file = full_command[0];
  for (string_list::const_iterator pos = command.begin();
       pos != command.end();
       ++pos)
    full_command.push_back(*pos);

  /* Execute */
  if (exec (file, full_command, env))
    {
      log_error() << format(_("Could not exec \"%1%\": %2%"))
      % command[0] % strerror(errno)
              << endl;
      exit (EXIT_FAILURE);
    }
  /* This should never be reached */
  exit(EXIT_FAILURE);
}


Generated by  Doxygen 1.6.0   Back to index