mirror of
https://github.com/varun-r-mallya/Python-BPF.git
synced 2026-02-07 13:40:59 +00:00
Fix documentation: correct comm() usage, XDP types, copyright year, and add uv support
Co-authored-by: r41k0u <76248539+r41k0u@users.noreply.github.com>
This commit is contained in:
@ -8,6 +8,14 @@ This directory contains the Sphinx documentation for PythonBPF.
|
|||||||
|
|
||||||
Install the documentation dependencies:
|
Install the documentation dependencies:
|
||||||
|
|
||||||
|
**Using uv (recommended):**
|
||||||
|
```bash
|
||||||
|
uv pip install -r requirements.txt
|
||||||
|
# Or install the optional docs dependencies
|
||||||
|
uv pip install pythonbpf[docs]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using pip:**
|
||||||
```bash
|
```bash
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
# Or install the optional docs dependencies
|
# Or install the optional docs dependencies
|
||||||
|
|||||||
@ -327,7 +327,7 @@ Ring buffer for efficient event delivery.
|
|||||||
### Process Information
|
### Process Information
|
||||||
|
|
||||||
* `pid()` - Get current process ID
|
* `pid()` - Get current process ID
|
||||||
* `comm()` - Get current process command name
|
* `comm(buf)` - Get current process command name (requires buffer parameter)
|
||||||
* `uid()` - Get current user ID
|
* `uid()` - Get current user ID
|
||||||
|
|
||||||
### Time
|
### Time
|
||||||
@ -450,7 +450,8 @@ def track_exec(ctx: c_void_p) -> c_int64:
|
|||||||
event = Event()
|
event = Event()
|
||||||
event.timestamp = ktime()
|
event.timestamp = ktime()
|
||||||
event.pid = pid()
|
event.pid = pid()
|
||||||
event.comm = comm()
|
# Note: comm() requires a buffer parameter
|
||||||
|
# comm(event.comm) # Fills event.comm with process name
|
||||||
|
|
||||||
events.output(event)
|
events.output(event)
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ sys.path.insert(0, os.path.abspath('..'))
|
|||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
project = 'PythonBPF'
|
project = 'PythonBPF'
|
||||||
copyright = '2024, r41k0u, varun-r-mallya'
|
copyright = '2024-2026, r41k0u, varun-r-mallya'
|
||||||
author = 'r41k0u, varun-r-mallya'
|
author = 'r41k0u, varun-r-mallya'
|
||||||
release = '0.1.8'
|
release = '0.1.8'
|
||||||
version = '0.1.8'
|
version = '0.1.8'
|
||||||
@ -90,9 +90,6 @@ html_theme_options = {
|
|||||||
'titles_only': False
|
'titles_only': False
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets)
|
|
||||||
html_static_path = ['_static']
|
|
||||||
|
|
||||||
# -- Options for autodoc -----------------------------------------------------
|
# -- Options for autodoc -----------------------------------------------------
|
||||||
|
|
||||||
autodoc_default_options = {
|
autodoc_default_options = {
|
||||||
|
|||||||
@ -43,8 +43,14 @@ The `llvm` package provides `llc`, the LLVM compiler that is used to compile LLV
|
|||||||
|
|
||||||
### From PyPI (Recommended)
|
### From PyPI (Recommended)
|
||||||
|
|
||||||
The easiest way to install PythonBPF is using pip:
|
The easiest way to install PythonBPF is using uv or pip:
|
||||||
|
|
||||||
|
**Using uv (recommended):**
|
||||||
|
```bash
|
||||||
|
uv pip install pythonbpf pylibbpf
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using pip:**
|
||||||
```bash
|
```bash
|
||||||
pip install pythonbpf pylibbpf
|
pip install pythonbpf pylibbpf
|
||||||
```
|
```
|
||||||
@ -73,6 +79,13 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|||||||
|
|
||||||
3. Install in development mode:
|
3. Install in development mode:
|
||||||
|
|
||||||
|
**Using uv (recommended):**
|
||||||
|
```bash
|
||||||
|
uv pip install -e .
|
||||||
|
uv pip install pylibbpf
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using pip:**
|
||||||
```bash
|
```bash
|
||||||
pip install -e .
|
pip install -e .
|
||||||
pip install pylibbpf
|
pip install pylibbpf
|
||||||
@ -88,6 +101,14 @@ make install
|
|||||||
|
|
||||||
If you want to build the documentation locally:
|
If you want to build the documentation locally:
|
||||||
|
|
||||||
|
**Using uv (recommended):**
|
||||||
|
```bash
|
||||||
|
uv pip install pythonbpf[docs]
|
||||||
|
# Or from the repository root:
|
||||||
|
uv pip install -e .[docs]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using pip:**
|
||||||
```bash
|
```bash
|
||||||
pip install pythonbpf[docs]
|
pip install pythonbpf[docs]
|
||||||
# Or from the repository root:
|
# Or from the repository root:
|
||||||
@ -100,6 +121,12 @@ Some examples require access to kernel data structures. To use these features, y
|
|||||||
|
|
||||||
1. Install additional dependencies:
|
1. Install additional dependencies:
|
||||||
|
|
||||||
|
**Using uv (recommended):**
|
||||||
|
```bash
|
||||||
|
uv pip install ctypeslib2
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using pip:**
|
||||||
```bash
|
```bash
|
||||||
pip install ctypeslib2
|
pip install ctypeslib2
|
||||||
```
|
```
|
||||||
@ -151,8 +178,8 @@ If you get errors about `llc` or `clang` not being found:
|
|||||||
If Python can't find the `pythonbpf` module:
|
If Python can't find the `pythonbpf` module:
|
||||||
|
|
||||||
* Make sure you've activated your virtual environment
|
* Make sure you've activated your virtual environment
|
||||||
* Verify installation with `pip list | grep pythonbpf`
|
* Verify installation with `uv pip list | grep pythonbpf` or `pip list | grep pythonbpf`
|
||||||
* Try reinstalling: `pip install --force-reinstall pythonbpf`
|
* Try reinstalling: `uv pip install --force-reinstall pythonbpf` or `pip install --force-reinstall pythonbpf`
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
|
|||||||
@ -120,15 +120,14 @@ Let's make a more interesting program that tracks which processes are being crea
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
|
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
|
||||||
from pythonbpf.helper import pid, comm
|
from pythonbpf.helper import pid
|
||||||
from ctypes import c_void_p, c_int64
|
from ctypes import c_void_p, c_int64
|
||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@section("tracepoint/syscalls/sys_enter_execve")
|
@section("tracepoint/syscalls/sys_enter_execve")
|
||||||
def track_exec(ctx: c_void_p) -> c_int64:
|
def track_exec(ctx: c_void_p) -> c_int64:
|
||||||
process_id = pid()
|
process_id = pid()
|
||||||
process_name = comm()
|
print(f"Process with PID: {process_id} is starting")
|
||||||
print(f"Process {process_name} (PID: {process_id}) is starting")
|
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@ -145,7 +144,6 @@ trace_pipe()
|
|||||||
This program uses BPF helper functions:
|
This program uses BPF helper functions:
|
||||||
|
|
||||||
* `pid()` - Gets the current process ID
|
* `pid()` - Gets the current process ID
|
||||||
* `comm()` - Gets the current process command name
|
|
||||||
|
|
||||||
Run it with `sudo python3 track_exec.py` and watch processes being created!
|
Run it with `sudo python3 track_exec.py` and watch processes being created!
|
||||||
|
|
||||||
@ -182,12 +180,11 @@ def trace_open(ctx: c_void_p) -> c_int64:
|
|||||||
For network packet processing:
|
For network packet processing:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ctypes import c_uint32
|
from pythonbpf.helper import XDP_PASS
|
||||||
|
|
||||||
@section("xdp")
|
@section("xdp")
|
||||||
def xdp_pass(ctx: c_void_p) -> c_uint32:
|
def xdp_pass(ctx: c_void_p) -> c_int64:
|
||||||
# XDP_PASS = 2
|
return XDP_PASS
|
||||||
return c_uint32(2)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|||||||
@ -108,12 +108,13 @@ def trace_open_return(ctx):
|
|||||||
For network packet processing at the earliest point:
|
For network packet processing at the earliest point:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from ctypes import c_uint32
|
from pythonbpf.helper import XDP_PASS
|
||||||
|
from ctypes import c_void_p, c_int64
|
||||||
|
|
||||||
@section("xdp")
|
@section("xdp")
|
||||||
def xdp_prog(ctx: c_void_p) -> c_uint32:
|
def xdp_prog(ctx: c_void_p) -> c_int64:
|
||||||
# XDP_PASS = 2, XDP_DROP = 1, XDP_ABORTED = 0
|
# XDP_PASS, XDP_DROP, XDP_ABORTED constants available from pythonbpf.helper
|
||||||
return c_uint32(2)
|
return XDP_PASS
|
||||||
```
|
```
|
||||||
|
|
||||||
#### TC (Traffic Control)
|
#### TC (Traffic Control)
|
||||||
@ -257,7 +258,8 @@ def track_processes(ctx: c_void_p) -> c_int64:
|
|||||||
event = ProcessEvent()
|
event = ProcessEvent()
|
||||||
event.timestamp = ktime()
|
event.timestamp = ktime()
|
||||||
event.pid = pid()
|
event.pid = pid()
|
||||||
event.comm = comm()
|
# Note: comm() requires a buffer parameter
|
||||||
|
# comm(event.comm) # Fills event.comm with process name
|
||||||
|
|
||||||
events.output(event)
|
events.output(event)
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
|
|||||||
@ -39,14 +39,19 @@ from pythonbpf.helper import comm
|
|||||||
@bpf
|
@bpf
|
||||||
@section("tracepoint/syscalls/sys_enter_execve")
|
@section("tracepoint/syscalls/sys_enter_execve")
|
||||||
def trace_exec(ctx: c_void_p) -> c_int64:
|
def trace_exec(ctx: c_void_p) -> c_int64:
|
||||||
process_name = comm()
|
# comm requires a buffer to fill
|
||||||
|
process_name = str(16)
|
||||||
|
comm(process_name)
|
||||||
print(f"Executing: {process_name}")
|
print(f"Executing: {process_name}")
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Returns:** `str(16)` - The command name of the current task
|
**Parameters:**
|
||||||
|
* `buf` - Buffer to fill with the process command name
|
||||||
|
|
||||||
**Note:** The returned string is limited to 16 characters (TASK_COMM_LEN).
|
**Returns:** `c_int64` - 0 on success, negative on error
|
||||||
|
|
||||||
|
**Note:** The buffer should be at least 16 bytes (TASK_COMM_LEN) to hold the full command name.
|
||||||
|
|
||||||
#### uid()
|
#### uid()
|
||||||
|
|
||||||
@ -406,17 +411,16 @@ trace_pipe()
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
|
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
|
||||||
from pythonbpf.helper import pid, comm, uid
|
from pythonbpf.helper import pid, uid
|
||||||
from ctypes import c_void_p, c_int64
|
from ctypes import c_void_p, c_int64
|
||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@section("tracepoint/syscalls/sys_enter_execve")
|
@section("tracepoint/syscalls/sys_enter_execve")
|
||||||
def track_exec(ctx: c_void_p) -> c_int64:
|
def track_exec(ctx: c_void_p) -> c_int64:
|
||||||
process_id = pid()
|
process_id = pid()
|
||||||
process_name = comm()
|
|
||||||
user_id = uid()
|
user_id = uid()
|
||||||
|
|
||||||
print(f"User {user_id} started {process_name} (PID: {process_id})")
|
print(f"User {user_id} started process (PID: {process_id})")
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@ -477,7 +481,7 @@ for cpu, count in map_obj.items():
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
|
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
|
||||||
from pythonbpf.helper import random, pid, comm
|
from pythonbpf.helper import random, pid
|
||||||
from ctypes import c_void_p, c_int64
|
from ctypes import c_void_p, c_int64
|
||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@ -486,8 +490,7 @@ def sample_opens(ctx: c_void_p) -> c_int64:
|
|||||||
# Sample 5% of events
|
# Sample 5% of events
|
||||||
if (random() % 100) < 5:
|
if (random() % 100) < 5:
|
||||||
process_id = pid()
|
process_id = pid()
|
||||||
process_name = comm()
|
print(f"Sampled: PID {process_id} opening file")
|
||||||
print(f"Sampled: {process_name} ({process_id}) opening file")
|
|
||||||
|
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
|
|
||||||
|
|||||||
@ -215,7 +215,8 @@ def log_exec(ctx: c_void_p) -> c_int64:
|
|||||||
event = ProcessEvent()
|
event = ProcessEvent()
|
||||||
event.timestamp = ktime()
|
event.timestamp = ktime()
|
||||||
event.pid = pid()
|
event.pid = pid()
|
||||||
event.comm = comm()
|
# Note: comm() requires a buffer parameter
|
||||||
|
# comm(event.comm) # Fills event.comm with process name
|
||||||
events.output(event)
|
events.output(event)
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
|
|
||||||
|
|||||||
@ -119,10 +119,11 @@ def capture_event(ctx: c_void_p) -> c_int64:
|
|||||||
# Set fields
|
# Set fields
|
||||||
event.timestamp = ktime()
|
event.timestamp = ktime()
|
||||||
event.pid = pid()
|
event.pid = pid()
|
||||||
event.comm = comm()
|
# Note: comm() requires a buffer parameter to fill
|
||||||
|
# comm(event.comm) # Fills event.comm with process name
|
||||||
|
|
||||||
# Use the struct
|
# Use the struct
|
||||||
print(f"Process {event.comm} with PID {event.pid}")
|
print(f"Process with PID {event.pid}")
|
||||||
|
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
```
|
```
|
||||||
@ -204,7 +205,8 @@ def trace_fork(ctx: c_void_p) -> c_int64:
|
|||||||
event = ProcessEvent()
|
event = ProcessEvent()
|
||||||
event.timestamp = ktime()
|
event.timestamp = ktime()
|
||||||
event.pid = pid()
|
event.pid = pid()
|
||||||
event.comm = comm()
|
# Note: comm() requires a buffer parameter
|
||||||
|
# comm(event.comm) # Fills event.comm with process name
|
||||||
|
|
||||||
# Send to userspace
|
# Send to userspace
|
||||||
events.output(event)
|
events.output(event)
|
||||||
@ -265,7 +267,8 @@ Assign values to fields:
|
|||||||
event = Event()
|
event = Event()
|
||||||
event.timestamp = ktime()
|
event.timestamp = ktime()
|
||||||
event.pid = pid()
|
event.pid = pid()
|
||||||
event.comm = comm()
|
# Note: comm() requires a buffer parameter
|
||||||
|
# comm(event.comm) # Fills event.comm with process name
|
||||||
```
|
```
|
||||||
|
|
||||||
### String Fields
|
### String Fields
|
||||||
@ -285,8 +288,8 @@ def example(ctx: c_void_p) -> c_int64:
|
|||||||
# Assign string value
|
# Assign string value
|
||||||
msg.text = "Hello from BPF"
|
msg.text = "Hello from BPF"
|
||||||
|
|
||||||
# Use helper to get process name
|
# Use helper to get process name (requires buffer)
|
||||||
msg.text = comm()
|
# comm(msg.text) # Fills msg.text with process name
|
||||||
|
|
||||||
return c_int64(0)
|
return c_int64(0)
|
||||||
```
|
```
|
||||||
@ -316,6 +319,7 @@ class MyStruct:
|
|||||||
```python
|
```python
|
||||||
from pythonbpf import bpf, struct, map, section
|
from pythonbpf import bpf, struct, map, section
|
||||||
from pythonbpf.maps import RingBuffer
|
from pythonbpf.maps import RingBuffer
|
||||||
|
from pythonbpf.helper import ktime, XDP_PASS
|
||||||
from ctypes import c_void_p, c_int64, c_uint8, c_uint16, c_uint32, c_uint64
|
from ctypes import c_void_p, c_int64, c_uint8, c_uint16, c_uint32, c_uint64
|
||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@ -336,7 +340,7 @@ def packets() -> RingBuffer:
|
|||||||
|
|
||||||
@bpf
|
@bpf
|
||||||
@section("xdp")
|
@section("xdp")
|
||||||
def capture_packets(ctx: c_void_p) -> c_uint32:
|
def capture_packets(ctx: c_void_p) -> c_int64:
|
||||||
pkt = PacketEvent()
|
pkt = PacketEvent()
|
||||||
pkt.timestamp = ktime()
|
pkt.timestamp = ktime()
|
||||||
# Parse packet data from ctx...
|
# Parse packet data from ctx...
|
||||||
@ -344,7 +348,7 @@ def capture_packets(ctx: c_void_p) -> c_uint32:
|
|||||||
packets.output(pkt)
|
packets.output(pkt)
|
||||||
|
|
||||||
# XDP_PASS
|
# XDP_PASS
|
||||||
return c_uint32(2)
|
return XDP_PASS
|
||||||
```
|
```
|
||||||
|
|
||||||
### Process Lifecycle Tracking
|
### Process Lifecycle Tracking
|
||||||
@ -377,7 +381,8 @@ def track_fork(ctx: c_void_p) -> c_int64:
|
|||||||
info = ProcessLifecycle()
|
info = ProcessLifecycle()
|
||||||
info.pid = process_id
|
info.pid = process_id
|
||||||
info.start_time = ktime()
|
info.start_time = ktime()
|
||||||
info.comm = comm()
|
# Note: comm() requires a buffer parameter
|
||||||
|
# comm(info.comm) # Fills info.comm with process name
|
||||||
|
|
||||||
process_info.update(process_id, info)
|
process_info.update(process_id, info)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user