Ejemplo n.º 1
0
std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
    const std::string& exec_path,
    const std::string& extension,
    const std::string& extensions_socket,
    const std::string& extensions_timeout,
    const std::string& extensions_interval,
    const std::string& verbose) {
  auto ext_pid = ::fork();
  if (ext_pid < 0) {
    return std::shared_ptr<PlatformProcess>();
  } else if (ext_pid == 0) {
    setEnvVar("OSQUERY_EXTENSION", std::to_string(::getpid()).c_str());
    ::execle(exec_path.c_str(),
             ("osquery extension: " + extension).c_str(),
             "--socket",
             extensions_socket.c_str(),
             "--timeout",
             extensions_timeout.c_str(),
             "--interval",
             extensions_interval.c_str(),
             (verbose == "true") ? "--verbose" : (char*)nullptr,
             (char*)nullptr,
             ::environ);

    // Code should never reach this point
    VLOG(1) << "Could not start extension process: " << extension;
    Initializer::shutdown(EXIT_FAILURE);
    return std::shared_ptr<PlatformProcess>();
  }

  return std::make_shared<PlatformProcess>(ext_pid);
}
Ejemplo n.º 2
0
void WatcherRunner::createWorker() {
  {
    WatcherLocker locker;
    if (Watcher::getState(Watcher::getWorker()).last_respawn_time >
        getUnixTime() - getWorkerLimit(RESPAWN_LIMIT)) {
      LOG(WARNING) << "osqueryd worker respawning too quickly: "
                   << Watcher::workerRestartCount() << " times";
      Watcher::workerRestarted();
      // The configured automatic delay.
      size_t delay = getWorkerLimit(RESPAWN_DELAY) * 1000;
      // Exponential back off for quickly-respawning clients.
      delay += pow(2, Watcher::workerRestartCount()) * 1000;
      pauseMilli(delay);
    }
  }

  // Get the path of the current process.
  auto qd =
      SQL::selectAllFrom("processes",
                         "pid",
                         EQUALS,
                         INTEGER(PlatformProcess::getCurrentProcess()->pid()));
  if (qd.size() != 1 || qd[0].count("path") == 0 || qd[0]["path"].size() == 0) {
    LOG(ERROR) << "osquery watcher cannot determine process path for worker";
    Initializer::requestShutdown(EXIT_FAILURE);
    return;
  }

  // Set an environment signaling to potential plugin-dependent workers to wait
  // for extensions to broadcast.
  if (Watcher::hasManagedExtensions()) {
    setEnvVar("OSQUERY_EXTENSIONS", "true");
  }

  // Get the complete path of the osquery process binary.
  boost::system::error_code ec;
  auto exec_path = fs::system_complete(fs::path(qd[0]["path"]), ec);
  if (!safePermissions(
          exec_path.parent_path().string(), exec_path.string(), true)) {
    // osqueryd binary has become unsafe.
    LOG(ERROR) << RLOG(1382)
               << "osqueryd has unsafe permissions: " << exec_path.string();
    Initializer::requestShutdown(EXIT_FAILURE);
    return;
  }

  auto worker = PlatformProcess::launchWorker(exec_path.string(), argc_, argv_);
  if (worker == nullptr) {
    // Unrecoverable error, cannot create a worker process.
    LOG(ERROR) << "osqueryd could not create a worker process";
    Initializer::shutdown(EXIT_FAILURE);
    return;
  }

  Watcher::setWorker(worker);
  Watcher::resetWorkerCounters(getUnixTime());
  VLOG(1) << "osqueryd watcher (" << PlatformProcess::getCurrentProcess()->pid()
          << ") executing worker (" << worker->pid() << ")";
}
Ejemplo n.º 3
0
  RpmEnvironmentManager() : config_(getEnvVar("RPM_CONFIGDIR")) {
    // Honor a caller's environment
    if (!config_.is_initialized()) {
      setEnvVar("RPM_CONFIGDIR", "/usr/lib/rpm");
    }

    callback_ = rpmlogSetCallback(&RpmEnvironmentManager::Callback, nullptr);
  }
Ejemplo n.º 4
0
std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
    const std::string& exec_path,
    const std::string& extensions_socket,
    const std::string& extensions_timeout,
    const std::string& extensions_interval,
    bool verbose) {
  auto ext_pid = ::fork();
  if (ext_pid < 0) {
    return std::shared_ptr<PlatformProcess>();
  } else if (ext_pid == 0) {
    setEnvVar("OSQUERY_EXTENSION", std::to_string(::getpid()).c_str());

    struct sigaction sig_action;
    sig_action.sa_handler = SIG_DFL;
    sig_action.sa_flags = 0;
    sigemptyset(&sig_action.sa_mask);

    for (auto i = NSIG; i >= 0; i--) {
      sigaction(i, &sig_action, nullptr);
    }

    std::vector<const char*> arguments;
    arguments.push_back(exec_path.c_str());
    arguments.push_back(exec_path.c_str());

    std::string arg_verbose("--verbose");
    if (verbose) {
      arguments.push_back(arg_verbose.c_str());
    }

    std::string arg_socket("--socket");
    arguments.push_back(arg_socket.c_str());
    arguments.push_back(extensions_socket.c_str());

    std::string arg_timeout("--timeout");
    arguments.push_back(arg_timeout.c_str());
    arguments.push_back(extensions_timeout.c_str());

    std::string arg_interval("--interval");
    arguments.push_back(arg_interval.c_str());
    arguments.push_back(extensions_interval.c_str());
    arguments.push_back(nullptr);

    char* const* argv = const_cast<char* const*>(&arguments[1]);
    ::execve(arguments[0], argv, ::environ);

    // Code should never reach this point
    VLOG(1) << "Could not start extension process: " << exec_path;
    Initializer::shutdown(EXIT_FAILURE);
    return std::shared_ptr<PlatformProcess>();
  }

  return std::make_shared<PlatformProcess>(ext_pid);
}
Ejemplo n.º 5
0
std::shared_ptr<PlatformProcess> PlatformProcess::launchWorker(
    const std::string& exec_path, int argc /* unused */, char** argv) {
  auto worker_pid = ::fork();
  if (worker_pid < 0) {
    return std::shared_ptr<PlatformProcess>();
  } else if (worker_pid == 0) {
    setEnvVar("OSQUERY_WORKER", std::to_string(::getpid()).c_str());
    ::execve(exec_path.c_str(), argv, ::environ);

    // Code should never reach this point
    LOG(ERROR) << "osqueryd could not start worker process";
    Initializer::shutdown(EXIT_CATASTROPHIC);
    return std::shared_ptr<PlatformProcess>();
  }
  return std::make_shared<PlatformProcess>(worker_pid);
}
Ejemplo n.º 6
0
TEST_F(ProcessTests, test_envVar) {
  auto val = getEnvVar("GTEST_OSQUERY");
  EXPECT_FALSE(val);
  EXPECT_FALSE(val.is_initialized());

  EXPECT_TRUE(setEnvVar("GTEST_OSQUERY", "true"));

  val = getEnvVar("GTEST_OSQUERY");
  EXPECT_FALSE(!val);
  EXPECT_TRUE(val.is_initialized());
  EXPECT_EQ(*val, "true");

  EXPECT_TRUE(unsetEnvVar("GTEST_OSQUERY"));

  val = getEnvVar("GTEST_OSQUERY");
  EXPECT_FALSE(val);
  EXPECT_FALSE(val.is_initialized());
}
Ejemplo n.º 7
0
/* Takes the command struct and takes approproate action.
 * Will either execute a shell command, program, or output an error message.
 * @params: command - a struct representing the command
 * @return: false is the command was note found, true otherwise.
 */
bool processCommand(command_t* command, char* pEnv[]){

   char* defaultDir = getenv("HOME");

   if( strcmp(command->name, "cd") == CMP_OK) {
       if( command->argc == 1 ) {
	   changeDirectory(defaultDir);
       } else {
	   changeDirectory(command->argv[1]);
       }
   } else if( strcmp(command->name,"help") == CMP_OK) {
       help();
   } else if( strcmp(command->name, "senv") == CMP_OK) {
       char* envName = NULL;
       char* envVal = NULL;

       if( command->argc > 1) {
           envName = command->argv[1];
       } 

       if( command->argc > 2) {
           envVal = command->argv[2];
       }

       setEnvVar(envName,envVal);

   } else if( strcmp(command->name, "usenv") == CMP_OK) {
       char* envName = NULL;
       if( command->argc > 1) {
	       envName = command->argv[1];
       }
       unsetEnvVar(envName);

   } else if( strcmp(command->name, "genv") == CMP_OK) {
       char* envName = NULL;
       if( command-> argc > 1) {
	       envName = command->argv[1];
       }
       getEnvVar(envName);
   } else {
       char* filePath = getFilePath(command->name);
       if(filePath != NULL) {
	   pid_t pid_command = fork();

           if(pid_command < CHILD) { // ERROR
	       fprintf(stderr, "Fork failure!\n");
  	   } else if ( pid_command == CHILD) {
	       if(command->isBg) {
		   freopen("/dev/null","w",stdout);
	           freopen("/dev/null","w",stderr);
	       }

	       execve(filePath, command->argv, pEnv);
	   } else {
	       if(!command->isBg) {
		   int stat;
		   waitpid(pid_command, &stat, 0);
	       } else {
			   printf("Process ID: %d\n", pid_command);
		   }
           }
       } else if(strcmp(command->name, "quit") == CMP_OK ||
		 strcmp(command->name, "exit") == CMP_OK ||
		 strcmp(command->name, "q") == CMP_OK ) {
	   return false;
       } else {
   	   printf("%s: Command not found\n", command->name);
	   return false;
       }
   }  
   return true;
}
Ejemplo n.º 8
0
std::shared_ptr<PlatformProcess> PlatformProcess::launchExtension(
    const std::string &exec_path,
    const std::string &extension,
    const std::string &extensions_socket,
    const std::string &extensions_timeout,
    const std::string &extensions_interval,
    const std::string &verbose) {
  ::STARTUPINFOA si = {0};
  ::PROCESS_INFORMATION pi = {0};

  si.cb = sizeof(si);

  // To prevent errant double quotes from altering the intended arguments for
  // argv, we strip them out completely.
  std::stringstream argv_stream;
  argv_stream << "\"osquery extension: "
              << boost::replace_all_copy(extension, "\"", "") << "\" ";
  argv_stream << "--socket \"" << extensions_socket << "\" ";
  argv_stream << "--timeout " << extensions_timeout << " ";
  argv_stream << "--interval " << extensions_interval << " ";

  if (verbose == "true") {
    argv_stream << "--verbose";
  }

  // We don't directly use argv.c_str() as the value for lpCommandLine in
  // CreateProcess since that argument requires a modifiable buffer. So,
  // instead, we off-load the contents of argv into a vector which will have its
  // backing memory as modifiable.
  std::string argv = argv_stream.str();
  std::vector<char> mutable_argv(argv.begin(), argv.end());
  mutable_argv.push_back('\0');

  // In POSIX, this environment variable is set to the child's process ID. But
  // that is not easily accomplishable on Windows and provides no value since
  // this is never used elsewhere in the core.
  if (!setEnvVar("OSQUERY_EXTENSION", "1")) {
    return std::shared_ptr<PlatformProcess>();
  }

  BOOL status = ::CreateProcessA(exec_path.c_str(),
                                 &mutable_argv[0],
                                 NULL,
                                 NULL,
                                 TRUE,
                                 0,
                                 NULL,
                                 NULL,
                                 &si,
                                 &pi);
  unsetEnvVar("OSQUERY_EXTENSION");

  if (!status) {
    return std::shared_ptr<PlatformProcess>();
  }

  auto process = std::make_shared<PlatformProcess>(pi.hProcess);
  ::CloseHandle(pi.hThread);
  ::CloseHandle(pi.hProcess);

  return process;
}
Ejemplo n.º 9
0
std::shared_ptr<PlatformProcess> PlatformProcess::launchWorker(
    const std::string &exec_path, int argc, char **argv) {
  ::STARTUPINFOA si = {0};
  ::PROCESS_INFORMATION pi = {0};

  si.cb = sizeof(si);

  std::stringstream argv_stream;
  std::stringstream handle_stream;

  // The HANDLE exposed to the child process is currently limited to only having
  // SYNCHRONIZE and PROCESS_QUERY_LIMITED_INFORMATION capabilities. The
  // SYNCHRONIZE permissions allows for WaitForSingleObject.
  // PROCESS_QUERY_LIMITED_INFORMATION allows for the ability to use the
  // GetProcessId and GetExitCodeProcess API functions.
  HANDLE hLauncherProcess =
      ::OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION,
                    TRUE,
                    GetCurrentProcessId());
  if (hLauncherProcess == NULL) {
    return std::shared_ptr<PlatformProcess>();
  }

  handle_stream << hLauncherProcess;
  std::string handle = handle_stream.str();

  // In the POSIX version, the environment variable OSQUERY_WORKER is set to the
  // string form of the child process' process ID. However, this is not easily
  // doable on Windows. Since the value does not appear to be used by the rest
  // of osquery, we currently just set it to '1'.
  //
  // For the worker case, we also set another environment variable,
  // OSQUERY_LAUNCHER. OSQUERY_LAUNCHER stores the string form of a HANDLE to
  // the current process. This is mostly used for detecting the death of the
  // launcher process in WatcherWatcherRunner::start
  if (!setEnvVar("OSQUERY_WORKER", "1") ||
      !setEnvVar("OSQUERY_LAUNCHER", handle.c_str())) {
    ::CloseHandle(hLauncherProcess);

    return std::shared_ptr<PlatformProcess>();
  }

  // Since Windows does not accept a char * array for arguments, we have to
  // build one as a string. Therefore, we need to make sure that special
  // characters are not present that would obstruct the parsing of arguments.
  // For now, we strip out all double quotes. If the an entry in argv has
  // spaces, we will put double-quotes around the entry.
  //
  // NOTE: This is extremely naive and will break the moment complexities are
  //       involved... Windows command line argument parsing is extremely
  //       nitpicky and is different in behavior than POSIX argv parsing.
  //
  // We don't directly use argv.c_str() as the value for lpCommandLine in
  // CreateProcess since that argument requires a modifiable buffer. So,
  // instead, we off-load the contents of argv into a vector which will have its
  // backing memory as modifiable.
  for (size_t i = 0; i < argc; i++) {
    std::string component(argv[i]);
    if (component.find(" ") != std::string::npos) {
      boost::replace_all(component, "\"", "\\\"");
      argv_stream << "\"" << component << "\" ";
    } else {
      argv_stream << component << " ";
    }
  }

  std::string cmdline = argv_stream.str();
  std::vector<char> mutable_argv(cmdline.begin(), cmdline.end());
  mutable_argv.push_back('\0');

  BOOL status = ::CreateProcessA(exec_path.c_str(),
                                 &mutable_argv[0],
                                 NULL,
                                 NULL,
                                 TRUE,
                                 0,
                                 NULL,
                                 NULL,
                                 &si,
                                 &pi);
  unsetEnvVar("OSQUERY_WORKER");
  unsetEnvVar("OSQUERY_LAUNCHER");
  ::CloseHandle(hLauncherProcess);

  if (!status) {
    return std::shared_ptr<PlatformProcess>();
  }

  auto process = std::make_shared<PlatformProcess>(pi.hProcess);
  ::CloseHandle(pi.hThread);
  ::CloseHandle(pi.hProcess);

  return process;
}