Exemplo n.º 1
0
void WatcherRunner::start() {
  // Set worker performance counters to an initial state.
  Watcher::resetWorkerCounters(0);

  // Enter the watch loop.
  do {
    if (use_worker_ && !watch(Watcher::getWorker())) {
      if (Watcher::fatesBound()) {
        // A signal has interrupted the watcher.
        break;
      }
      // The watcher failed, create a worker.
      createWorker();
    }

    // Loop over every managed extension and check sanity.
    std::vector<std::string> failing_extensions;
    for (const auto& extension : Watcher::extensions()) {
      if (!watch(*extension.second)) {
        if (!createExtension(extension.first)) {
          failing_extensions.push_back(extension.first);
        }
      }
    }
    // If any extension creations failed, stop managing them.
    for (const auto& failed_extension : failing_extensions) {
      Watcher::removeExtensionPath(failed_extension);
    }
    pauseMilli(getWorkerLimit(INTERVAL) * 1000);
  } while (!interrupted() && ok());
}
Exemplo n.º 2
0
void SchedulerRunner::start() {
  // Start the counter at the second.
  auto i = osquery::getUnixTime();
  for (; (timeout_ == 0) || (i <= timeout_); ++i) {
    Config::get().scheduledQueries(
        ([&i](const std::string& name, const ScheduledQuery& query) {
          if (query.splayed_interval > 0 && i % query.splayed_interval == 0) {
            TablePlugin::kCacheInterval = query.splayed_interval;
            TablePlugin::kCacheStep = i;
            launchQuery(name, query);
          }
        }));
    // Configuration decorators run on 60 second intervals only.
    if ((i % 60) == 0) {
      runDecorators(DECORATE_INTERVAL, i);
    }
    if (FLAGS_schedule_reload > 0 && (i % FLAGS_schedule_reload) == 0) {
      if (FLAGS_schedule_reload_sql) {
        SQLiteDBManager::resetPrimary();
      }
      resetDatabase();
    }

    // GLog is not re-entrant, so logs must be flushed in a dedicated thread.
    if ((i % 3) == 0) {
      relayStatusLogs(true);
    }

    // Put the thread into an interruptible sleep without a config instance.
    pauseMilli(interval_ * 1000);
    if (interrupted()) {
      break;
    }
  }
}
Exemplo n.º 3
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() << ")";
}
Exemplo n.º 4
0
void TLSLogForwarderRunner::start() {
  while (!interrupted()) {
    check();

    // Cool off and time wait the configured period.
    pauseMilli(FLAGS_logger_tls_period * 1000);
  }
}
Exemplo n.º 5
0
void BufferedLogForwarder::start() {
  while (!interrupted()) {
    check();

    // Cool off and time wait the configured period.
    pauseMilli(log_period_);
  }
}
Exemplo n.º 6
0
Status INotifyEventPublisher::run() {
  // Get a while wrapper for free.
  char buffer[kINotifyBufferSize];
  fd_set set;

  FD_ZERO(&set);
  FD_SET(getHandle(), &set);

  struct timeval timeout = {1, 0};
  int selector = ::select(getHandle() + 1, &set, nullptr, nullptr, &timeout);
  if (selector == -1) {
    LOG(WARNING) << "Could not read inotify handle";
    return Status(1, "INotify handle failed");
  }

  if (selector == 0) {
    // Read timeout.
    return Status(0, "Continue");
  }
  ssize_t record_num = ::read(getHandle(), buffer, kINotifyBufferSize);
  if (record_num == 0 || record_num == -1) {
    return Status(1, "INotify read failed");
  }

  for (char* p = buffer; p < buffer + record_num;) {
    // Cast the inotify struct, make shared pointer, and append to contexts.
    auto event = reinterpret_cast<struct inotify_event*>(p);
    if (event->mask & IN_Q_OVERFLOW) {
      // The inotify queue was overflown (remove all paths).
      Status stat = restartMonitoring();
      if (!stat.ok()) {
        return stat;
      }
    }

    if (event->mask & IN_IGNORED) {
      // This inotify watch was removed.
      removeMonitor(event->wd, false);
    } else if (event->mask & IN_MOVE_SELF) {
      // This inotify path was moved, but is still watched.
      removeMonitor(event->wd, true);
    } else if (event->mask & IN_DELETE_SELF) {
      // A file was moved to replace the watched path.
      removeMonitor(event->wd, false);
    } else {
      auto ec = createEventContextFrom(event);
      if (!ec->action.empty()) {
        fire(ec);
      }
    }
    // Continue to iterate
    p += (sizeof(struct inotify_event)) + event->len;
  }

  pauseMilli(kINotifyMLatency);
  return Status(0, "OK");
}
Exemplo n.º 7
0
void WatcherWatcherRunner::start() {
  while (!interrupted()) {
    if (isLauncherProcessDead(*watcher_)) {
      // Watcher died, the worker must follow.
      VLOG(1) << "osqueryd worker ("
              << PlatformProcess::getCurrentProcess()->pid()
              << ") detected killed watcher (" << watcher_->pid() << ")";
      // The watcher watcher is a thread. Do not join services after removing.
      Initializer::requestShutdown();
      break;
    }
    pauseMilli(getWorkerLimit(INTERVAL) * 1000);
  }
}
Exemplo n.º 8
0
Status UdevEventPublisher::run() {
  int fd = 0;

  {
    WriteLock lock(mutex_);
    if (monitor_ == nullptr) {
      return Status(1);
    }
    fd = udev_monitor_get_fd(monitor_);
  }

  struct pollfd fds[1];
  fds[0].fd = fd;
  fds[0].events = POLLIN;

  int selector = ::poll(fds, 1, 1000);
  if (selector == -1 && errno != EINTR && errno != EAGAIN) {
    LOG(ERROR) << "Could not read udev monitor";
    return Status(1, "udev monitor failed.");
  }

  if (selector == 0 || !(fds[0].revents & POLLIN)) {
    // Read timeout.
    return Status(0, "Finished");
  }

  {
    WriteLock lock(mutex_);
    struct udev_device* device = udev_monitor_receive_device(monitor_);
    if (device == nullptr) {
      LOG(ERROR) << "udev monitor returned invalid device";
      return Status(1, "udev monitor failed.");
    }

    auto ec = createEventContextFrom(device);
    fire(ec);

    udev_device_unref(device);
  }

  pauseMilli(kUdevMLatency);
  return Status(0, "OK");
}
Exemplo n.º 9
0
void TLSConfigRefreshRunner::start() {
  while (!interrupted()) {
    // Cool off and time wait the configured period.
    // Apply this interruption initially as at t=0 the config was read.
    pauseMilli(FLAGS_config_tls_refresh * 1000);

    // Access the configuration.
    auto plugin = Registry::get("config", "tls");
    if (plugin != nullptr) {
      auto config_plugin = std::dynamic_pointer_cast<ConfigPlugin>(plugin);

      // The config instance knows the TLS plugin is selected.
      std::map<std::string, std::string> config;
      if (config_plugin->genConfig(config)) {
        Config::getInstance().update(config);
      }
    }
  }
}
Exemplo n.º 10
0
void SchedulerRunner::start() {
  // Start the counter at the second.
  auto i = osquery::getUnixTime();
  for (; (timeout_ == 0) || (i <= timeout_); ++i) {
    Config::getInstance().scheduledQueries(
        ([&i](const std::string& name, const ScheduledQuery& query) {
          if (query.splayed_interval > 0 && i % query.splayed_interval == 0) {
            TablePlugin::kCacheInterval = query.splayed_interval;
            TablePlugin::kCacheStep = i;
            launchQuery(name, query);
          }
        }));
    // Configuration decorators run on 60 second intervals only.
    if (i % 60 == 0) {
      runDecorators(DECORATE_INTERVAL, i);
    }
    // Put the thread into an interruptible sleep without a config instance.
    pauseMilli(interval_ * 1000);
    if (interrupted()) {
      break;
    }
  }
}
Exemplo n.º 11
0
Status KernelEventPublisher::run() {
  {
    WriteLock lock(mutex_);
    if (queue_ == nullptr) {
      return Status(1, "No kernel communication");
    }
  }

  // Perform queue read min/max synchronization.
  try {
    int drops = 0;
    WriteLock lock(mutex_);
    if ((drops = queue_->kernelSync(OSQUERY_OPTIONS_NO_BLOCK)) > 0 &&
        kToolType == ToolType::DAEMON) {
      LOG(WARNING) << "Dropping " << drops << " kernel events";
    }
  } catch (const CQueueException &e) {
    LOG(WARNING) << "Queue synchronization error: " << e.what();
  }

  auto dequeueEvents = [this]() {
    // Dequeue several events while holding the lock.
    int max_before_lock = kKernelEventsIterate;
    while (max_before_lock > 0) {
      // Request an event from the synchronized, safe, portion of the queue.
      CQueue::event *event = nullptr;
      auto event_type = queue_->dequeue(&event);
      if (event_type == OSQUERY_NULL_EVENT) {
        return false;
      }

      // Each event type may use a specific event type structure.
      KernelEventContextRef ec = nullptr;
      switch (event_type) {
      case OSQUERY_PROCESS_EVENT:
        ec = createEventContextFrom<osquery_process_event_t>(event_type, event);
        fire(ec);
        break;
      case OSQUERY_FILE_EVENT:
        ec = createEventContextFrom<osquery_file_event_t>(event_type, event);
        fire(ec);
        break;
      default:
        LOG(WARNING) << "Unknown kernel event received: " << event_type;
        break;
      }
      max_before_lock--;
    }
    return true;
  };

  // Iterate over each event type in the queue and appropriately fire each.
  int max_before_sync = kKernelEventsSyncMax;
  while (max_before_sync > 0) {
    WriteLock lock(mutex_);
    // The kernel publisher may have been torn down.
    if (queue_ == nullptr) {
      break;
    }
    // A NULL event occurred, stop dequeuing.
    if (!dequeueEvents()) {
      break;
    }
    // Append the number of dequeue events to the synchronization counter.
    max_before_sync -= kKernelEventsIterate;
  }

  // Pause for a cool-off since we implement comms in a no-blocking mode.
  pauseMilli(1000);
  return Status(0, "Continue");
}