osquery-1/osquery/events/linux/inotify.h

149 lines
4.9 KiB
C
Raw Normal View History

/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
2014-09-19 08:54:33 +00:00
#pragma once
#include <map>
#include <vector>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <osquery/events.h>
#include <osquery/status.h>
2014-09-19 08:54:33 +00:00
namespace osquery {
extern std::map<int, std::string> kMaskActions;
2014-09-30 19:50:14 +00:00
/**
* @brief Subscriptioning details for INotifyEventPublisher events.
2014-09-30 19:50:14 +00:00
*
2014-10-06 21:23:26 +00:00
* This context is specific to INotifyEventPublisher. It allows the
*subscriptioning
* EventSubscriber to set a path (file or directory) and a limited action mask.
2014-10-06 21:23:26 +00:00
* Events are passed to the subscriptioning EventSubscriber if they match the
*context
2014-09-30 19:50:14 +00:00
* path (or anything within a directory if the path is a directory) and if the
2014-10-06 21:23:26 +00:00
* event action is part of the mask. If the mask is 0 then all actions are
* passed to the EventSubscriber.
2014-09-30 19:50:14 +00:00
*/
struct INotifySubscriptionContext : public SubscriptionContext {
/// Subscription the following filesystem path.
2014-09-19 08:54:33 +00:00
std::string path;
/// Limit the `inotify` actions to the subscriptioned mask (if not 0).
2014-09-23 03:33:58 +00:00
uint32_t mask;
/// Treat this path as a directory and subscription recursively.
2014-09-23 03:33:58 +00:00
bool recursive;
INotifySubscriptionContext() : mask(0), recursive(false) {}
2014-09-30 19:50:14 +00:00
/**
* @brief Helper method to map a string action to `inotify` action mask bit.
*
2014-10-06 21:23:26 +00:00
* This helper method will set the `mask` value for this SubscriptionContext.
2014-09-30 19:50:14 +00:00
*
* @param action The string action, a value in kMaskAction%s.
*/
2014-12-15 18:17:56 +00:00
void requireAction(const std::string& action) {
for (const auto& bit : kMaskActions) {
if (action == bit.second) {
mask = mask | bit.first;
}
}
}
2014-09-19 08:54:33 +00:00
};
2014-09-30 19:50:14 +00:00
/**
* @brief Event details for INotifyEventPublisher events.
2014-09-30 19:50:14 +00:00
*/
struct INotifyEventContext : public EventContext {
/// The inotify_event structure if the EventSubscriber want to interact.
2014-09-24 18:25:05 +00:00
std::shared_ptr<struct inotify_event> event;
2014-09-30 19:50:14 +00:00
/// A string path parsed from the inotify_event.
2014-09-23 03:33:58 +00:00
std::string path;
2014-09-30 19:50:14 +00:00
/// A string action representing the event action `inotify` bit.
2014-09-23 03:33:58 +00:00
std::string action;
2015-04-01 04:18:56 +00:00
/// A no-op event transaction id.
uint32_t transaction_id;
INotifyEventContext() : event(nullptr), transaction_id(0) {}
2014-09-19 08:54:33 +00:00
};
2014-09-24 18:25:05 +00:00
typedef std::shared_ptr<INotifyEventContext> INotifyEventContextRef;
2014-10-06 21:23:26 +00:00
typedef std::shared_ptr<INotifySubscriptionContext>
2014-10-28 00:37:36 +00:00
INotifySubscriptionContextRef;
2014-09-19 08:54:33 +00:00
// Thread-safe containers
typedef std::vector<int> DescriptorVector;
typedef std::map<std::string, int> PathDescriptorMap;
typedef std::map<int, std::string> DescriptorPathMap;
2014-09-30 19:50:14 +00:00
/**
* @brief A Linux `inotify` EventPublisher.
2014-09-30 19:50:14 +00:00
*
2014-10-06 21:23:26 +00:00
* This EventPublisher allows EventSubscriber%s to subscription for Linux
*`inotify` events.
* Since these events are limited this EventPublisher will optimize the watch
2014-09-30 19:50:14 +00:00
* descriptors, keep track of the usage, implement optimizations/priority
* where possible, and abstract file system events to a path/action context.
*
2014-10-06 21:23:26 +00:00
* Uses INotifySubscriptionContext and INotifyEventContext for subscriptioning,
*eventing.
2014-09-30 19:50:14 +00:00
*/
2014-12-15 08:43:28 +00:00
class INotifyEventPublisher
: public EventPublisher<INotifySubscriptionContext, INotifyEventContext> {
2015-01-30 18:44:25 +00:00
DECLARE_PUBLISHER("inotify");
public:
2014-09-30 19:50:14 +00:00
/// Create an `inotify` handle descriptor.
2014-12-08 10:22:59 +00:00
Status setUp();
2014-09-19 08:54:33 +00:00
void configure();
2014-09-30 19:50:14 +00:00
/// Release the `inotify` handle descriptor.
2014-09-19 08:54:33 +00:00
void tearDown();
Status run();
2015-04-12 02:50:35 +00:00
INotifyEventPublisher()
: EventPublisher(), inotify_handle_(-1), last_restart_(-1) {}
2014-09-30 19:50:14 +00:00
/// Check if the application-global `inotify` handle is alive.
bool isHandleOpen() { return inotify_handle_ > 0; }
2014-09-19 08:54:33 +00:00
private:
INotifyEventContextRef createEventContextFrom(struct inotify_event* event);
/// Check all added Subscription%s for a path.
2014-10-06 21:23:26 +00:00
bool isPathMonitored(const std::string& path);
/// Add an INotify watch (monitor) on this path.
bool addMonitor(const std::string& path, bool recursive);
/// Remove an INotify watch (monitor) from our tracking.
bool removeMonitor(const std::string& path, bool force = false);
bool removeMonitor(int watch, bool force = false);
/// Given a SubscriptionContext and INotifyEventContext match path and action.
2014-12-15 18:17:56 +00:00
bool shouldFire(const INotifySubscriptionContextRef& mc,
2015-02-11 03:18:56 +00:00
const INotifyEventContextRef& ec) const;
2014-09-30 19:50:14 +00:00
/// Get the INotify file descriptor.
int getHandle() { return inotify_handle_; }
2014-10-07 18:20:47 +00:00
/// Get the number of actual INotify active descriptors.
int numDescriptors() { return descriptors_.size(); }
2015-03-02 23:43:31 +00:00
/// If we overflow, try and restart the monitor
Status restartMonitoring();
2014-09-19 08:54:33 +00:00
// Consider an event queue if separating buffering from firing/servicing.
DescriptorVector descriptors_;
PathDescriptorMap path_descriptors_;
DescriptorPathMap descriptor_paths_;
int inotify_handle_;
2015-03-02 23:43:31 +00:00
int last_restart_;
2014-10-07 18:20:47 +00:00
public:
FRIEND_TEST(INotifyTests, test_inotify_optimization);
2014-09-19 08:54:33 +00:00
};
}