Extended Berkeley Packet Filter (eBPF) is a powerful and versatile technology that allows developers to both safely and efficiently run custom code inside the Linux kernel. Due to its ability to enable deep visibility and control of system behavior, eBPF has seen much popularity in recent years. Developers rely on eBPF to provide a common infrastructure for a wide range of use cases, including networking, security, tracing, and performance analysis.
A Brief History of BPFs
Berkeley Packet Filters (BPFs) were created in 1992, designed to analyze and filter network traffic. At the time, the internet was still in its early stages and engineers were interested in finding ways to better understand the traffic flowing through their networks. BPF was designed to provide a way to do this without having to modify the code of all the servers in an organization or fork the kernel code and update it with instrumentation instructions.
Applied to network analytics, BPFs were used to log all incoming and outgoing TCP communications on a server. While this approach required less work than modifying the code of all the servers, it still needed significant effort to build the code and deploy it across all the servers in the organization.
BPF was also used for filtering network traffic. However, it could only accept packets with a signed hash in the header. When an incoming packet arrived, the BPF program would be launched and check the header to see if the expected value was present. Depending on the results, the packet would either be accepted or dropped.
Today, BPF is used for various purposes beyond just analyzing and filtering network traffic. It has been extended to provide more features and support for 64 bytes, allowing for more information collection and storage.
Later on with the release of kernel 3.18, Extended Berkeley Packet Filters (eBPFs) were made to register almost all kernel events. An extension of the original BPFs, eBPFs can store and exchange more data and be used for various purposes, including monitoring, tracing, and optimizing kernel functions.
The Introduction of eBPFs
From a historical perspective, developers have always worked within operating systems to implement and observe network functionality, using the kernel’s privileged ability to monitor and control the entire system. Where operating system kernels have been limited lies in their lack of evolution – innovating at the operating system level is lower than compared to capabilities seen outside them. Further, developers adding modules or modifying kernel source code meant trudging through abstracted layers and complex infrastructure that are difficult to debug. When eBFP was first introduced in 2014, it addressed all of these issues.
As eBPFs work by allowing sandboxed programs to run within the operating system, developers were suddenly able to add new capabilities to the operating system at runtime. It is a type of virtual machine that runs inside the kernel and provides a sandboxed environment for executing bytecode programs. The eBPF virtual machine is designed to be simple, efficient, and safe, with a limited set of instructions that can only access a restricted set of resources.
Since its inception, eBPF has evolved and can be found driving a wide array of use cases. eBPF has enabled innovations in high-performance network and load-balancing in cloud native environments, provided security leaders with granular security data at a low overhead cost, and supported organizations in their preventative security efforts.
Understanding how eBFP Works
At a high level, eBPF works by allowing developers to write small programs, known as eBPF programs, that can be attached to various points in the kernel to intercept and process data. Usually written in a subset of the C programming language, the programs are then compiled to eBPF bytecode, which is then loaded into the kernel and executed. Unlike traditional kernel modules, eBPF programs are easy to deploy and manage as they don’t need kernel source code modifications or recompilation.
An eBPF program follows a specific set of steps when it is executed within the Linux kernel:
- Once the eBPF program has been written, it is compiled into eBPF bytecode. The resulting bytecode is a low-level, platform-independent representation of the eBPF program that can be executed within the kernel.
- Then, the eBPF bytecode is loaded into the kernel. The loading process involves verifying the bytecode for safety and compatibility with the running kernel, and allocating the necessary resources to execute the eBPF program.
- Once the eBPF program has been loaded, it can be attached to a specific kernel event, such as a network packet or a system call (syscall).
- When the attached kernel event occurs, the eBPF program is executed automatically by the kernel. The eBPF program can access and modify data associated with the event, using standard C programming constructs such as loops and conditional statements.
- After the eBPF program has processed the data, it can optionally return a result to the kernel. For example, an eBPF program attached to a network interface might drop a packet if it matches certain criteria, or an eBPF program attached to a system call might modify the arguments passed to the call before allowing it to proceed.
- When the eBPF program is no longer needed, it can be unloaded from the kernel, freeing up the resources allocated to the eBPF program and ensuring that it will no longer be executed when the attached kernel event occurs.
One of the key features of eBPF is its safety guarantees. eBPF programs run in a restricted virtual machine within the kernel, and they cannot access or modify kernel data structures directly nor cause crashes or security vulnerabilities. eBPF programs are additionally subject to various runtime checks, such as bounds checking and type checking, to ensure that they don’t violate memory safety or other security properties.
Exploring the Benefits of eBPF
In today’s world, developers use eBPF to improve their system’s security, performance, and stability. eBPF has become such a popular technology in the Linux ecosystem owing to its many advantages.
First, organizations use eBPF to ensure speed and performance. As eBPF programs are executed within the Linux kernel, they operate with minimal overhead compared to traditional userspace programs. In cases where low latency and high performance are critical, eBPF is the ideal choice to get the task done.
eBPF programs also allow technical teams to remain flexible. Since the programs can be attached to a wide range of kernel events, including network packets, syscalls, and kernel functions, this allows them to be used for a wide range of use cases, including network monitoring, security analysis, and performance profiling. eBPF programs can be dynamically loaded and unloaded from the kernel, which means they can be used for short-lived tasks such as debugging or troubleshooting.
Developers using eBPF are able to write new functionality that previously could not have been done due to technical limitations or security concerns. With eBPF, they can write applications that take advantage of hardware acceleration on embedded devices such as Raspberry Pi or other ARM-based systems.
Just-in-time (JIT) compiled rather than precompiled like traditional software packages, developers can use eBPF to create their applications or services without sacrificing performance or scalability. The technology requires minimal setup time compared to other solutions so developers can quickly deploy their applications in production environments with less effort.
eBPF Use Cases
eBPF is most commonly used for four main use cases: security, networking, tracing, and observability.
- Security – Typically in security, systems independently handle aspects of syscall filtering. Syscall filters allow applications to define exactly which syscalls they are permitted to execute. eBPF supports better system security by facilitating visibility into all aspects. By interpreting all syscalls and providing packet and socket-level views of all networking operations, security leaders have the context they need to improve the level of control they have over systems.
- Networking – eBPF supports packet processing requirements due to its efficiency and programmability. It does so by adding additional protocol parsers and programs forwarding logic to meet new requirements without having to exit the Linux kernel’s packet processing context.
- Tracing – Developers attach eBPF programs to trace points as well as kernel and user application probe points to secure visibility into the runtime behavior of all system applications. eBPF provides context to both systems and applications; the combination of these gives technical teams powerful insights that they can use to troubleshoot performance issues.
- Observability – eBPF is used to collect in-kernel aggregation of system metrics that technical teams can customize based on a wide range of sources. Instead of having to rely on time-consuming and large exports of sampling data, eBPF increases the depth of visibility by collecting only the absolutely necessary data, saving organizations from system overhead costs.
How eBPF Augments Modern Cloud Security Measures
A Cloud Workload Protection Platform (CWPP) agent is an essential element when building a robust cloud security strategy. It offers real-time protection against runtime threats such as ransomware and zero-day attacks, which sets it apart from other security controls. eBPF greatly improves performance and scalability for cloud systems that continue to see wide-spread adoption across global organizations.
CWPP agents record workload telemetry, providing valuable information for forensic analysis. In contrast, side-scanning solutions, which inspect cloud compute instance storage volumes, can only be run once a day and lack process-level visibility, leading to real-time protection and accuracy limitations. Using the eBPF framework within a CWPP program offers several benefits, including the following:
- Operational stability – Running code in the kernel is a major risk as it raises the chances of introducing vulnerabilities into the kernel and destabilizing the entire system. The eBPF framework includes safety controls such as the JIT compiler so as not to crash the kernel.
- System performance – Data transfers between the kernel to the user space is typically slow and generates performance overhead. The eBPF framework enables teams to observe kernel behavior and perform analysis within the kernel before transferring a subset of results back to the user space, lowering the overhead needed.
- Business agility – By operating from the user space, eBPF offers greater flexibility and agility for DevOps teams and the vendor. DevOps can focus on innovation without worrying about kernel dependency issues, and the vendor can concentrate on innovation rather than maintenance. This leads to a continuous cycle of innovation and improved customer experience.
eBPF has quickly become an important technology for a wide range of applications, from networking and security to observability and performance analysis. Its flexibility and safety guarantees make it a powerful tool for customizing and extending the Linux kernel, and its popularity and adoption continue to grow as more use cases are discovered and developed.
Leading organizations continue to invest in solutions such as SentinelOne’s CWPP, Singularity Cloud Workload Security, that have embedded the benefits of the eBPF framework. As digital environments continue to grow more dynamic and complex and large numbers of workloads run on shared infrastructure, eBPF can help improve visibility and control, allowing security teams to monitor and protect workloads more effectively.
Reach out to us to learn how SentinelOne’s security solutions channel the benefits of eBPF to improve performance and efficiency across diverse environments. Book a demo with our security experts today.