Skip to content

Commit

Permalink
linux native events wrapper
Browse files Browse the repository at this point in the history
Summary:
Handler to enable event with certain type, get an id of the event and make sure it will be disables afterwards.

Part of a linux `syscalls` tracing system, blueprint: [osquery#5218](osquery#5218)

Reviewed By: mkareta

Differential Revision: D13621388

fbshipit-source-id: c22c67e29a0edb2ba368e68ce3c41488835fc97f
  • Loading branch information
akindyakov authored and facebook-github-bot committed Jan 18, 2019
1 parent bab228b commit eb33334
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 0 deletions.
45 changes: 45 additions & 0 deletions osquery/utils/system/linux/tracing/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright (c) 2014-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under both the Apache 2.0 license (found in the
# LICENSE file in the root directory of this source tree) and the GPLv2 (found
# in the COPYING file in the root directory of this source tree).
# You may select, at your option, one of the above-listed licenses.

load("//tools/build_defs/oss/osquery:cxx.bzl", "osquery_cxx_library")
load("//tools/build_defs/oss/osquery:native.bzl", "osquery_target")
load("//tools/build_defs/oss/osquery:platforms.bzl", "LINUX")
load("//tools/build_defs/oss/osquery:third_party.bzl", "osquery_tp_target")

osquery_cxx_library(
name = "tracing",
header_namespace = "osquery/utils/system/linux/tracing",
exported_platform_headers = [
(
LINUX,
[
"native_event.h",
"types.h",
],
),
],
platform_srcs = [
(
LINUX,
[
"native_event.cpp",
],
),
],
tests = [
osquery_target("osquery/utils/system/linux/tracing/tests:tracing_tests"),
],
visibility = ["PUBLIC"],
deps = [
osquery_target("osquery/utils/conversions:conversions"),
osquery_target("osquery/utils/expected:expected"),
osquery_target("osquery/logger:logger"),
osquery_tp_target("boost"),
osquery_tp_target("googletest", "gtest"),
],
)
132 changes: 132 additions & 0 deletions osquery/utils/system/linux/tracing/native_event.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/

#include <osquery/utils/system/linux/tracing/native_event.h>

#include <osquery/utils/conversions/tryto.h>

#include <osquery/logger.h>

#include <boost/filesystem/path.hpp>
#include <boost/io/detail/quoted_manip.hpp>

#include <fstream>

namespace osquery {
namespace tracing {

namespace fs = boost::filesystem;

fs::path getNativeEventFullPath(const std::string& event_path) {
return fs::path("/sys/kernel/debug/tracing/events") / event_path;
}

NativeEvent::~NativeEvent() {
auto const exp = enable(false);
if (exp.isError()) {
LOG(WARNING) << "Disabling system event " << event_path_
<< " failed: " << exp.getError().getFullMessage();
}
}

NativeEvent::NativeEvent(NativeEvent&& other)
: id_(other.id_), event_path_(std::move(other.event_path_)) {
other.id_ = -1;
}

NativeEvent& NativeEvent::operator=(NativeEvent&& other) {
std::swap(id_, other.id_);
std::swap(event_path_, other.event_path_);
return *this;
}

Expected<NativeEvent, NativeEvent::Error> NativeEvent::load(
std::string event_path) {
auto instance = NativeEvent(std::move(event_path));
auto exp = instance.enable(true);
if (exp.isError()) {
return exp.takeError();
}
return Expected<NativeEvent, NativeEvent::Error>(std::move(instance));
}

SystemEventId NativeEvent::id() const {
return id_;
}

NativeEvent::NativeEvent(std::string event_path)
: event_path_(std::move(event_path)) {}

namespace {

Expected<int, NativeEvent::Error> extractIdFromTheSystem(
fs::path const& full_event_path) {
auto const id_path = full_event_path / "id";
auto id_in =
std::fstream(id_path.native(), std::ios_base::in | std::ios_base::binary);
auto id_str = std::string{};
if (id_in.is_open()) {
id_in >> id_str;
}
if (!id_in.is_open() || id_in.fail()) {
return createError(NativeEvent::Error::System,
"Could not open linux event id file ")
<< boost::io::quoted(id_path.string());
}
auto id_exp = tryTo<SystemEventId>(id_str);
if (id_exp.isError()) {
return createError(NativeEvent::Error::System,
"Could not parse linux event id from the string ")
<< boost::io::quoted(id_str);
}
return id_exp.get();
}

} // namespace

bool NativeEvent::isEnabled() const {
return id_ >= 0;
}

ExpectedSuccess<NativeEvent::Error> NativeEvent::enable(bool do_enable) {
if (do_enable == isEnabled()) {
// Nothing to do it is already enabled or disabled
return Success{};
}
auto const full_event_path = getNativeEventFullPath(event_path_);
auto const event_enable_path = full_event_path / "enable";
auto event_enable_out = std::fstream(
event_enable_path.native(), std::ios_base::out | std::ios_base::binary);
if (event_enable_out.is_open()) {
auto const buf = do_enable ? "1" : "0";
event_enable_out << buf;
}
if (!event_enable_out.is_open() || event_enable_out.fail()) {
auto const action = do_enable ? "enable" : "disable";
return createError(Error::System, "Could not ")
<< action << " system event, not sufficient rights to modify file "
<< boost::io::quoted(event_enable_path.string());
}
if (do_enable) {
auto id_exp = extractIdFromTheSystem(full_event_path);
if (id_exp.isError()) {
return createError(Error::System,
"Could not retrieve event id from the system",
id_exp.takeError());
}
id_ = id_exp.take();
} else {
id_ = -1;
}
return Success{};
}

} // namespace tracing
} // namespace osquery
59 changes: 59 additions & 0 deletions osquery/utils/system/linux/tracing/native_event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/

#pragma once

#include <osquery/utils/expected/expected.h>
#include <osquery/utils/system/linux/tracing/types.h>

#include <string>

namespace osquery {
namespace tracing {

/**
* Wrapper for the native linux system events, see
* "/sys/kernel/debug/tracing/events/"
*/
class NativeEvent final {
public:
~NativeEvent();

NativeEvent(NativeEvent&& other);
NativeEvent& operator=(NativeEvent&& other);

NativeEvent(NativeEvent const&) = delete;
NativeEvent& operator=(NativeEvent const&) = delete;

enum class Error {
Unknown = 1,
System = 2,
};

/**
* Enable event type with path @event_path and receive the id
*/
static Expected<NativeEvent, NativeEvent::Error> load(std::string event_path);

SystemEventId id() const;

private:
explicit NativeEvent(std::string event_path);

bool isEnabled() const;
ExpectedSuccess<Error> enable(bool do_enable);

private:
SystemEventId id_ = -1;
std::string event_path_;
};

} // namespace tracing
} // namespace osquery
30 changes: 30 additions & 0 deletions osquery/utils/system/linux/tracing/tests/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright (c) 2014-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under both the Apache 2.0 license (found in the
# LICENSE file in the root directory of this source tree) and the GPLv2 (found
# in the COPYING file in the root directory of this source tree).
# You may select, at your option, one of the above-listed licenses.

load("//tools/build_defs/oss/osquery:cxx.bzl", "osquery_cxx_test")
load("//tools/build_defs/oss/osquery:native.bzl", "osquery_target")
load("//tools/build_defs/oss/osquery:platforms.bzl", "LINUX")

osquery_cxx_test(
name = "tracing_tests",
srcs = [
"empty.cpp",
],
platform_srcs = [
(
LINUX,
[
"native_event.cpp",
],
),
],
visibility = ["PUBLIC"],
deps = [
osquery_target("osquery/utils/system/linux/tracing:tracing"),
],
)
9 changes: 9 additions & 0 deletions osquery/utils/system/linux/tracing/tests/empty.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
26 changes: 26 additions & 0 deletions osquery/utils/system/linux/tracing/tests/native_event.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/

#include <gtest/gtest.h>

#include <osquery/utils/system/linux/tracing/native_event.h>

namespace osquery {
namespace {

class NativeEventTests : public testing::Test {};

TEST_F(NativeEventTests, non_root_load_should_fail) {
auto const exp = tracing::NativeEvent::load("syscalls/sys_enter_open");
ASSERT_TRUE(exp.isError());
ASSERT_EQ(exp.getErrorCode(), tracing::NativeEvent::Error::System);
}
} // namespace
} // namespace osquery
21 changes: 21 additions & 0 deletions osquery/utils/system/linux/tracing/types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/

#pragma once

#include <cstdint>

namespace osquery {
namespace tracing {

using SystemEventId = std::int64_t;

} // namespace tracing
} // namespace osquery

0 comments on commit eb33334

Please sign in to comment.