Skip to content

Commit bf8ceab

Browse files
Repair some pain points (#546)
* Anti-fingerprint fixes and container fix * fix import pathing
1 parent 691edd3 commit bf8ceab

16 files changed

Lines changed: 430 additions & 41 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,5 @@ site/site/
6666
.github/copilot-instructions.md
6767
template_variables_report.json
6868
src/file_management/donor_info.json
69+
message.txt
70+
BUILD_LOG_ANALYSIS.md

Containerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ RUN pip3 install --no-cache-dir -r requirements.txt -r requirements-tui.txt
6363
COPY src ./src
6464
COPY configs ./configs
6565
COPY pcileech.py .
66+
COPY pyproject.toml setup.py setup.cfg ./
67+
68+
# Install the package itself so `from pcileechfwgenerator.xxx` imports work
69+
RUN pip3 install --no-cache-dir -e . || echo "Warning: Editable install failed, trying regular install" && pip3 install --no-cache-dir .
6670

6771
# Copy voltcyclone-fpga from build stage (cloned during build)
6872
COPY --from=build /src/lib/voltcyclone-fpga ./lib/voltcyclone-fpga

configs/fallbacks.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ critical_variables:
2222
- device.class_code # PCI Class Code (e.g., 020000 for network devices)
2323
- device.subsys_vendor_id # PCI Subsystem Vendor ID
2424
- device.subsys_device_id # PCI Subsystem Device ID
25+
26+
# Timing configuration (MUST come from device profiling)
27+
# Using fallbacks would create fingerprintable patterns
28+
- timing_config.min_latency_cycles
29+
- timing_config.max_latency_cycles
30+
- timing_config.avg_latency_cycles
31+
- timing_config.min_read_latency
32+
- timing_config.max_read_latency
33+
- timing_config.avg_read_latency
34+
35+
# Template context device identifiers
36+
- vendor_id_int # Integer form of vendor ID
37+
- device_id_int # Integer form of device ID
2538

2639
# Safe fallback values for non-critical variables
2740
# These will be used only if the variable is missing

install-sudo-wrapper.sh

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ log_error() {
2626
check_files() {
2727
local missing_files=()
2828

29-
if [ ! -f "pcileech-build-sudo" ]; then
30-
missing_files+=("pcileech-build-sudo")
29+
if [ ! -f "pcileech-sudo" ]; then
30+
missing_files+=("pcileech-sudo")
3131
fi
3232

3333
if [ ${#missing_files[@]} -ne 0 ]; then
@@ -59,14 +59,18 @@ if ! check_files; then
5959
fi
6060

6161
# Copy the wrapper script to the installation directory
62-
log_info "Installing pcileech-build-sudo..."
63-
cp pcileech-build-sudo "$INSTALL_DIR/"
62+
log_info "Installing pcileech-sudo..."
63+
cp pcileech-sudo "$INSTALL_DIR/"
64+
chmod +x "$INSTALL_DIR/pcileech-sudo"
65+
66+
# Also install as pcileech-build-sudo for backwards compatibility
67+
ln -sf "$INSTALL_DIR/pcileech-sudo" "$INSTALL_DIR/pcileech-build-sudo" 2>/dev/null || \
68+
cp pcileech-sudo "$INSTALL_DIR/pcileech-build-sudo"
6469
chmod +x "$INSTALL_DIR/pcileech-build-sudo"
6570

6671
log_info "Installed pcileech sudo wrapper to $INSTALL_DIR"
67-
log_info "You can now run builds with sudo using: pcileech-build-sudo build --bdf <device> --board <board>"
68-
log_warning "Note: The wrapper now uses the unified pcileech.py entrypoint"
69-
log_warning "Legacy usage is supported but consider using: sudo python3 pcileech.py build ..."
72+
log_info "You can now run commands with sudo using: pcileech-sudo <command> [args]"
73+
log_warning "Note: The wrapper uses the unified pcileech.py entrypoint"
7074

7175
# Add the directory to PATH if it's not already there
7276
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
@@ -106,9 +110,9 @@ fi
106110
log_info "Installation complete!"
107111
log_info ""
108112
log_info "Usage examples:"
109-
log_info " pcileech-build-sudo build --bdf 0000:03:00.0 --board pcileech_35t325_x1"
110-
log_info " pcileech-build-sudo tui"
111-
log_info " pcileech-build-sudo check --device 0000:03:00.0"
113+
log_info " pcileech-sudo build --bdf 0000:03:00.0 --board pcileech_35t325_x1"
114+
log_info " pcileech-sudo check --device 0000:03:00.0"
115+
log_info " pcileech-sudo tui"
112116
log_info ""
113-
log_info "Alternative (recommended):"
117+
log_info "Alternative (from project directory):"
114118
log_info " sudo python3 pcileech.py build --bdf 0000:03:00.0 --board pcileech_35t325_x1"

pcileech-sudo

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
# pcileech-sudo - Run pcileech commands with elevated privileges
3+
#
4+
# This wrapper script handles:
5+
# 1. Automatic virtual environment detection
6+
# 2. Running pcileech.py with sudo while preserving the Python environment
7+
#
8+
# Usage: pcileech-sudo <command> [args...]
9+
# Example: pcileech-sudo build --bdf 0000:03:00.0 --board pcileech_35t325_x1
10+
# pcileech-sudo check --device 0000:03:00.0
11+
# pcileech-sudo tui
12+
13+
set -euo pipefail
14+
15+
# Find the script directory (where pcileech.py is located)
16+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17+
18+
# Check if pcileech.py exists in the script directory
19+
if [ ! -f "$SCRIPT_DIR/pcileech.py" ]; then
20+
# Try to find it relative to installed location
21+
if [ -f "/app/pcileech.py" ]; then
22+
SCRIPT_DIR="/app"
23+
else
24+
echo "Error: Could not find pcileech.py in $SCRIPT_DIR or /app"
25+
echo "Please run this script from the PCILeechFWGenerator directory"
26+
exit 1
27+
fi
28+
fi
29+
30+
# Determine the Python interpreter to use
31+
PYTHON_CMD=""
32+
33+
# Check for active virtual environment first
34+
if [ -n "${VIRTUAL_ENV:-}" ]; then
35+
PYTHON_CMD="$VIRTUAL_ENV/bin/python3"
36+
elif [ -f "$SCRIPT_DIR/.venv/bin/python3" ]; then
37+
# Check for local .venv
38+
PYTHON_CMD="$SCRIPT_DIR/.venv/bin/python3"
39+
elif [ -f "$HOME/.pcileech-venv/bin/python3" ]; then
40+
# Check for user-level venv
41+
PYTHON_CMD="$HOME/.pcileech-venv/bin/python3"
42+
else
43+
# Fall back to system Python
44+
PYTHON_CMD="python3"
45+
fi
46+
47+
# Verify the Python interpreter exists
48+
if [ ! -x "$PYTHON_CMD" ] && ! command -v "$PYTHON_CMD" &> /dev/null; then
49+
echo "Error: Python interpreter not found: $PYTHON_CMD"
50+
echo "Please ensure Python 3 is installed and accessible"
51+
exit 1
52+
fi
53+
54+
# Execute pcileech.py with sudo, preserving the Python environment
55+
# Using 'sudo -E' to preserve environment variables
56+
cd "$SCRIPT_DIR"
57+
exec sudo -E "$PYTHON_CMD" "$SCRIPT_DIR/pcileech.py" "$@"

pcileech.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@
2323
sys.path.insert(0, str(project_root))
2424
sys.path.insert(0, str(project_root / "src"))
2525

26+
# Create pcileechfwgenerator namespace mapping for direct script execution
27+
# This is needed because pyproject.toml maps pcileechfwgenerator -> src/
28+
# but that only works when the package is installed via pip
29+
_src_path = project_root / "src"
30+
if _src_path.exists() and "pcileechfwgenerator" not in sys.modules:
31+
import importlib.util
32+
33+
# Check if package is already installed (editable or regular install)
34+
_spec = importlib.util.find_spec("pcileechfwgenerator")
35+
if _spec is None:
36+
# Package not installed, create the namespace mapping manually
37+
# This allows "from pcileechfwgenerator.x import y" to work as "from src.x import y"
38+
import types
39+
_pkg = types.ModuleType("pcileechfwgenerator")
40+
_pkg.__path__ = [str(_src_path)]
41+
_pkg.__file__ = str(_src_path / "__init__.py")
42+
sys.modules["pcileechfwgenerator"] = _pkg
43+
2644

2745
def get_version():
2846
"""Get the current version from the centralized version resolver."""

scripts/vfio_container_manager.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
sys.path.insert(0, str(Path(__file__).parent.parent))
2424

2525
from src.cli.vfio_handler import (
26+
DeviceInfo,
2627
VFIOBinder,
2728
VFIOBindError,
2829
VFIOPermissionError,

src/cli/vfio_diagnostics.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,9 @@ class Diagnostics:
231231
def __init__(self, device_bdf: Optional[str] = None):
232232
self.device_bdf = device_bdf
233233
self.checks: List[Check] = []
234+
# Store device vendor/device IDs for remediation commands
235+
self._vendor_id: Optional[str] = None
236+
self._device_id: Optional[str] = None
234237

235238
# Public API --------------------------------------------------------------
236239
def run(self) -> Report:
@@ -591,6 +594,9 @@ def _device_exists(self):
591594
path_manager = VFIOPathManager(self.device_bdf)
592595
if path_manager.device_path.exists():
593596
vendor_id, device_id = path_manager.get_vendor_device_id()
597+
# Store IDs for use in remediation commands (without 0x prefix)
598+
self._vendor_id = vendor_id
599+
self._device_id = device_id
594600
# Add 0x prefix for display consistency with existing behavior
595601
vendor = f"0x{vendor_id}"
596602
device = f"0x{device_id}"
@@ -828,22 +834,49 @@ def _device_driver_binding(self):
828834
commands=self._bind_commands(self.device_bdf, None),
829835
)
830836

831-
@staticmethod
832-
def _bind_commands(bdf: str, current: Optional[str]) -> List[str]:
833-
cmds: list[str] = [
834-
(
837+
def _bind_commands(self, bdf: str, current: Optional[str]) -> List[str]:
838+
"""Generate commands to bind device to vfio-pci driver.
839+
840+
Uses the new_id approach which is more robust:
841+
1. Unbind from current driver (if any)
842+
2. Register device IDs with vfio-pci via new_id (this auto-binds)
843+
844+
The new_id approach is preferred because:
845+
- It works even when the device has no current driver
846+
- It doesn't require the device to be pre-registered with vfio-pci
847+
- It handles the binding automatically after registration
848+
"""
849+
cmds: list[str] = []
850+
851+
# Step 1: Unbind from current driver if one is bound
852+
if current:
853+
cmds.append(
835854
safe_format(
836855
"echo '{bdf}' | sudo tee /sys/bus/pci/devices/{bdf}/driver/unbind",
837856
bdf=bdf,
838857
)
839-
if current
840-
else ""
841-
),
842-
safe_format(
843-
"echo '{bdf}' | sudo tee /sys/bus/pci/drivers/vfio-pci/bind", bdf=bdf
844-
),
845-
]
846-
return [c for c in cmds if c]
858+
)
859+
860+
# Step 2: Use new_id to register and auto-bind to vfio-pci
861+
# This is the recommended approach and works regardless of prior driver state
862+
if self._vendor_id and self._device_id:
863+
cmds.append(
864+
safe_format(
865+
"echo '{vid} {did}' | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id",
866+
vid=self._vendor_id,
867+
did=self._device_id,
868+
)
869+
)
870+
else:
871+
# Fallback to direct bind if we don't have device IDs
872+
# This may fail if the device IDs aren't pre-registered
873+
cmds.append(
874+
safe_format(
875+
"echo '{bdf}' | sudo tee /sys/bus/pci/drivers/vfio-pci/bind", bdf=bdf
876+
)
877+
)
878+
879+
return cmds
847880

848881
def _device_node(self):
849882
link = Path(

src/device_clone/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
TimingPattern,
2323
)
2424

25+
# Import the module itself for patching purposes
26+
from pcileechfwgenerator.device_clone import board_config
27+
2528
# Core device cloning functionality
2629
from pcileechfwgenerator.device_clone.board_config import (
2730
get_board_info,

src/templates/sv/pcileech_bar_impl_device.sv.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ module pcileech_bar_impl_device #(
214214

215215
// Device-specific timing seed for jitter
216216
// Uses vendor_id XOR device_id for deterministic but unique timing
217-
localparam [15:0] INT_TIMING_SEED = {{ "16'h%04X" % ((vendor_id | 0x8086) ^ (device_id | 0x1234)) }};
217+
localparam [15:0] INT_TIMING_SEED = {{ "16'h%04X" % ((vendor_id|bitor(0x8086))|bitxor(device_id|bitor(0x1234))) }};
218218

219219
// LFSR for interrupt timing jitter (matches tlp_latency_emulator approach)
220220
reg [15:0] int_lfsr;

0 commit comments

Comments
 (0)