From 48c5d39ffe7639e8680a2a05fa1728caf32bc044 Mon Sep 17 00:00:00 2001 From: Alexander Kindyakov Date: Wed, 16 Jan 2019 02:52:27 -0800 Subject: [PATCH] ebpf initial declarations and support check tests Differential Revision: D13607442 fbshipit-source-id: d41b0e98e19a82fbf390f21a3040b35afa940a0c --- osquery/utils/system/linux/ebpf/BUCK | 45 ++++++++++++ osquery/utils/system/linux/ebpf/ebpf.cpp | 73 +++++++++++++++++++ osquery/utils/system/linux/ebpf/ebpf.h | 26 +++++++ osquery/utils/system/linux/ebpf/tests/BUCK | 30 ++++++++ .../utils/system/linux/ebpf/tests/ebpf.cpp | 49 +++++++++++++ .../utils/system/linux/ebpf/tests/empty.cpp | 9 +++ 6 files changed, 232 insertions(+) create mode 100644 osquery/utils/system/linux/ebpf/BUCK create mode 100644 osquery/utils/system/linux/ebpf/ebpf.cpp create mode 100644 osquery/utils/system/linux/ebpf/ebpf.h create mode 100644 osquery/utils/system/linux/ebpf/tests/BUCK create mode 100644 osquery/utils/system/linux/ebpf/tests/ebpf.cpp create mode 100644 osquery/utils/system/linux/ebpf/tests/empty.cpp diff --git a/osquery/utils/system/linux/ebpf/BUCK b/osquery/utils/system/linux/ebpf/BUCK new file mode 100644 index 00000000000..54ea6dfafd7 --- /dev/null +++ b/osquery/utils/system/linux/ebpf/BUCK @@ -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"), + ], +) diff --git a/osquery/utils/system/linux/ebpf/ebpf.cpp b/osquery/utils/system/linux/ebpf/ebpf.cpp new file mode 100644 index 00000000000..12e6e8d3236 --- /dev/null +++ b/osquery/utils/system/linux/ebpf/ebpf.cpp @@ -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 +#include + +#include + +#include + +#include +#include + +#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 isSupportedBySystem() { + struct utsname utsbuf; + if (uname(&utsbuf) == -1) { + return createError(to(errno), "syscall uname() failed: ") + << boost::io::quoted(strerror(errno)); + } + auto release_version_exp = + tryTo(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 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(errno), "bpf() syscall failed: ") + << boost::io::quoted(strerror(errno)); + } + return ret; +} + +} // namespace ebpf +} // namespace osquery diff --git a/osquery/utils/system/linux/ebpf/ebpf.h b/osquery/utils/system/linux/ebpf/ebpf.h new file mode 100644 index 00000000000..810e36a0625 --- /dev/null +++ b/osquery/utils/system/linux/ebpf/ebpf.h @@ -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 +#include + +#include + +namespace osquery { +namespace ebpf { + +Expected isSupportedBySystem(); + +Expected syscall(int cmd, union bpf_attr* attr); + +} // namespace ebpf +} // namespace osquery diff --git a/osquery/utils/system/linux/ebpf/tests/BUCK b/osquery/utils/system/linux/ebpf/tests/BUCK new file mode 100644 index 00000000000..d2ea9607723 --- /dev/null +++ b/osquery/utils/system/linux/ebpf/tests/BUCK @@ -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"), + ], +) diff --git a/osquery/utils/system/linux/ebpf/tests/ebpf.cpp b/osquery/utils/system/linux/ebpf/tests/ebpf.cpp new file mode 100644 index 00000000000..3cb014b86a7 --- /dev/null +++ b/osquery/utils/system/linux/ebpf/tests/ebpf.cpp @@ -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 + +#include + +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 diff --git a/osquery/utils/system/linux/ebpf/tests/empty.cpp b/osquery/utils/system/linux/ebpf/tests/empty.cpp new file mode 100644 index 00000000000..9ac62ab8eb7 --- /dev/null +++ b/osquery/utils/system/linux/ebpf/tests/empty.cpp @@ -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. + */