Skip to content

Commit

Permalink
eBPF initial declarations and isSupportedBySystem function (osquery#5354
Browse files Browse the repository at this point in the history
)

Summary:
Pull Request resolved: osquery#5354

eBPF system call osquery wrapper with Expected as a return value and function to check if functionality is supported by current kernel.

Blueprint: [osquery#5218](osquery#5218)

Reviewed By: mkareta

Differential Revision: D13607442

fbshipit-source-id: 270a2f7c51c2cb8d6c3ecc6fd070b4a173093656
  • Loading branch information
akindyakov authored and facebook-github-bot committed Jan 16, 2019
1 parent 6fe7b4c commit a2e388a
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 0 deletions.
45 changes: 45 additions & 0 deletions osquery/utils/system/linux/ebpf/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 = "ebpf",
header_namespace = "osquery/utils/system/linux/ebpf",
exported_platform_headers = [
(
LINUX,
[
"ebpf.h",
],
),
],
platform_srcs = [
(
LINUX,
[
"ebpf.cpp",
],
),
],
tests = [
osquery_target("osquery/utils/system/linux/ebpf/tests:ebpf_tests"),
],
visibility = ["PUBLIC"],
deps = [
osquery_target("osquery/utils/conversions:conversions"),
osquery_target("osquery/utils/expected:expected"),
osquery_target("osquery/utils/versioning:semantic"),
osquery_target("osquery/utils/system:errno"),
osquery_target("osquery/logger:logger"),
osquery_tp_target("boost"),
],
)
73 changes: 73 additions & 0 deletions osquery/utils/system/linux/ebpf/ebpf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* 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/ebpf/ebpf.h>
#include <osquery/utils/versioning/semantic.h>

#include <osquery/logger.h>

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

#include <linux/version.h>
#include <sys/utsname.h>

#ifndef __NR_bpf

#if defined(__i386__)
#define __NR_bpf 357
#elif defined(__x86_64__)
#define __NR_bpf 321
#elif defined(__aarch64__)
#define __NR_bpf 280
#elif defined(__sparc__)
#define __NR_bpf 349
#elif defined(__s390__)
#define __NR_bpf 351
#else
#error __NR_bpf is undefined, probably this arch is not supported.
#endif

#endif // __NR_bpf

namespace osquery {
namespace ebpf {

constexpr int kMinimalLinuxVersionCode = KERNEL_VERSION(4, 9, 0);

Expected<bool, PosixError> isSupportedBySystem() {
struct utsname utsbuf;
if (uname(&utsbuf) == -1) {
return createError(to<PosixError>(errno), "syscall uname() failed: ")
<< boost::io::quoted(strerror(errno));
}
auto release_version_exp =
tryTo<SemanticVersion>(std::string(utsbuf.release));
if (release_version_exp.isError()) {
return createError(PosixError::Unknown,
"uname() release field is malformed",
release_version_exp.takeError())
<< boost::io::quoted(utsbuf.release);
}
auto const version = release_version_exp.take();
return kMinimalLinuxVersionCode <=
KERNEL_VERSION(version.major, version.minor, version.patches);
}

Expected<int, PosixError> syscall(int cmd, union bpf_attr* attr) {
int const ret = ::syscall(__NR_bpf, cmd, attr, sizeof(union bpf_attr));
if (ret < 0) {
return createError(to<PosixError>(errno), "bpf() syscall failed: ")
<< boost::io::quoted(strerror(errno));
}
return ret;
}

} // namespace ebpf
} // namespace osquery
26 changes: 26 additions & 0 deletions osquery/utils/system/linux/ebpf/ebpf.h
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.
*/

#pragma once

#include <osquery/utils/expected/expected.h>
#include <osquery/utils/system/posix/errno.h>

#include <linux/bpf.h>

namespace osquery {
namespace ebpf {

Expected<bool, PosixError> isSupportedBySystem();

Expected<int, PosixError> syscall(int cmd, union bpf_attr* attr);

} // namespace ebpf
} // namespace osquery
30 changes: 30 additions & 0 deletions osquery/utils/system/linux/ebpf/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 = "ebpf_tests",
srcs = [
"empty.cpp",
],
platform_srcs = [
(
LINUX,
[
"ebpf.cpp",
],
),
],
visibility = ["PUBLIC"],
deps = [
osquery_target("osquery/utils/system/linux/ebpf:ebpf"),
],
)
49 changes: 49 additions & 0 deletions osquery/utils/system/linux/ebpf/tests/ebpf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* 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/ebpf/ebpf.h>

namespace osquery {
namespace {

class EbpfTests : public testing::Test {};

TEST_F(EbpfTests, isSupportedBySystem) {
auto const exp = ebpf::isSupportedBySystem();
ASSERT_TRUE(exp.isValue()) << exp.getError().getFullMessageRecursive();
}

TEST_F(EbpfTests, sysEbpf_null_attr) {
auto const exp = ebpf::syscall(BPF_MAP_CREATE, nullptr);
ASSERT_TRUE(exp.isError());
ASSERT_EQ(exp.getErrorCode(), PosixError::FAULT);
}

TEST_F(EbpfTests, sysEbpf_create_map) {
auto const is_supported_exp = ebpf::isSupportedBySystem();
EXPECT_TRUE(is_supported_exp.isValue())
<< is_supported_exp.getError().getFullMessageRecursive();
if (is_supported_exp.get()) {
union bpf_attr attr;
memset(&attr, 0, sizeof(union bpf_attr));
attr.map_type = BPF_MAP_TYPE_ARRAY;
attr.key_size = 4;
attr.value_size = 4;
attr.max_entries = 12;
auto exp_bpf = ebpf::syscall(BPF_MAP_CREATE, &attr);
ASSERT_TRUE(exp_bpf.isValue());
ASSERT_GE(exp_bpf.get(), 0);
}
}

} // namespace
} // namespace osquery
9 changes: 9 additions & 0 deletions osquery/utils/system/linux/ebpf/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.
*/

0 comments on commit a2e388a

Please sign in to comment.