forked from osquery/osquery
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eBPF program loader class (osquery#5355)
Summary: Pull Request resolved: osquery#5355 C++ wrapper to load and keep track of eBPF program in order to close if afterwards. Blueprint: [osquery#5218](osquery#5218) Reviewed By: guliashvili Differential Revision: D13609628 fbshipit-source-id: 536d908da8f9a55961aee4e04864d2c1da704f3d
- Loading branch information
1 parent
966c971
commit 8127730
Showing
5 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/** | ||
* 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/program.h> | ||
#include <osquery/utils/system/linux/ebpf/ebpf.h> | ||
|
||
#include <boost/io/detail/quoted_manip.hpp> | ||
|
||
#include <linux/version.h> | ||
|
||
namespace osquery { | ||
namespace ebpf { | ||
|
||
Program::Program(Program&& other) : fd_(other.fd_) { | ||
other.fd_ = -1; | ||
} | ||
|
||
Program& Program::operator=(Program&& other) { | ||
std::swap(fd_, other.fd_); | ||
return *this; | ||
} | ||
|
||
Program::~Program() { | ||
if (fd_ > 0) { | ||
close(fd_); | ||
fd_ = -1; | ||
} | ||
} | ||
|
||
Expected<Program, Program::Error> Program::load( | ||
std::vector<struct bpf_insn> const prog, | ||
enum bpf_prog_type const program_type, | ||
bool const debug) { | ||
static char const* kLicense = "GPL"; | ||
constexpr auto kLogBufSize = std::uint32_t{1 << 16}; | ||
|
||
auto bpf_log_buf = std::array<char, kLogBufSize>{}; | ||
union bpf_attr attr = { | ||
.prog_type = program_type, | ||
.insns = reinterpret_cast<__aligned_u64>(prog.data()), | ||
.insn_cnt = static_cast<std::uint32_t>(prog.size()), | ||
.license = reinterpret_cast<__aligned_u64>(kLicense), | ||
.log_buf = 0u, | ||
.log_size = 0u, | ||
.log_level = 0u, | ||
.kern_version = LINUX_VERSION_CODE, | ||
}; | ||
if (debug) { | ||
bpf_log_buf.fill('\0'); | ||
attr.log_buf = reinterpret_cast<std::uint64_t>(bpf_log_buf.data()); | ||
attr.log_size = reinterpret_cast<std::uint32_t>(kLogBufSize); | ||
attr.log_level = 1; | ||
} | ||
auto instance = Program{}; | ||
auto fd_exp = syscall(BPF_PROG_LOAD, &attr); | ||
if (fd_exp.isError()) { | ||
return createError(Program::Error::Unknown, | ||
"eBPF program load failed ", | ||
fd_exp.takeError()) | ||
<< " bpf log: " << boost::io::quoted(bpf_log_buf.data()); | ||
} | ||
instance.fd_ = fd_exp.take(); | ||
return Expected<Program, Program::Error>(std::move(instance)); | ||
} | ||
|
||
int Program::fd() const { | ||
return fd_; | ||
} | ||
|
||
} // namespace ebpf | ||
} // namespace osquery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/** | ||
* 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 <linux/bpf.h> | ||
|
||
namespace osquery { | ||
namespace ebpf { | ||
|
||
class Program final { | ||
public: | ||
Program(Program&& other); | ||
Program& operator=(Program&& other); | ||
|
||
Program(Program const&) = delete; | ||
Program& operator=(Program const&) = delete; | ||
|
||
~Program(); | ||
|
||
enum class Error { | ||
Unknown = 1, | ||
NotSupportedBySystem = 2, | ||
}; | ||
|
||
static Expected<Program, Program::Error> load( | ||
std::vector<struct bpf_insn> prog, | ||
enum bpf_prog_type const program_type = BPF_PROG_TYPE_KPROBE, | ||
bool const debug = false); | ||
|
||
int fd() const; | ||
|
||
private: | ||
Program() = default; | ||
|
||
private: | ||
int fd_ = -1; | ||
}; | ||
|
||
} // namespace ebpf | ||
} // namespace osquery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ osquery_cxx_test( | |
[ | ||
"ebpf.cpp", | ||
"map.cpp", | ||
"program.cpp", | ||
], | ||
), | ||
], | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
*/ | ||
|
||
#include <osquery/utils/system/linux/ebpf/program.h> | ||
#include <osquery/utils/system/linux/ebpf/ebpf.h> | ||
|
||
#include <osquery/logger.h> | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace osquery { | ||
namespace { | ||
|
||
class EbpfProgramTests : public testing::Test {}; | ||
|
||
bool const kDebug = | ||
#ifndef NDEBUG | ||
true; | ||
#else | ||
false; | ||
#endif | ||
|
||
TEST_F(EbpfProgramTests, empty_debug) { | ||
auto const ebpf_exp = ebpf::isSupportedBySystem(); | ||
EXPECT_TRUE(ebpf_exp.isValue()) | ||
<< ebpf_exp.getError().getFullMessageRecursive(); | ||
if (!ebpf_exp.get()) { | ||
LOG(WARNING) << "This system does not support eBPF of required vesion, " | ||
"test will be skipped"; | ||
return; | ||
} | ||
auto program_exp = ebpf::Program::load({}, BPF_PROG_TYPE_KPROBE, kDebug); | ||
ASSERT_TRUE(program_exp.isError()); | ||
ASSERT_EQ(program_exp.getErrorCode(), ebpf::Program::Error::Unknown); | ||
} | ||
|
||
} // namespace | ||
} // namespace osquery |