Skip to content

Security: KKingZero/FirmwareGuard

Security

docs/SECURITY.md

FirmwareGuard Security Analysis

Phase 2 Implementation

Document Type: Security Considerations & Threat Model Version: 1.0 Date: 2025-11-20 Classification: Public


Executive Summary

FirmwareGuard Phase 2 implements destructive firmware modifications requiring extensive security measures. This document analyzes the threat model, attack surface, and security controls implemented to prevent system compromise.


Threat Model

Assets Protected

  1. System Firmware: UEFI variables, BIOS settings, boot configuration
  2. Boot Integrity: GRUB configuration, kernel parameters
  3. System Availability: Prevention of bricking, boot failures
  4. User Data: Configuration files, backup registry, logs

Threat Actors

  1. Malicious User: Local attacker with limited privileges
  2. Malicious Software: Malware attempting to exploit FirmwareGuard
  3. Supply Chain Attack: Compromised binaries or dependencies
  4. Accidental Misuse: User error causing system damage

Attack Scenarios

Scenario 1: Privilege Escalation

Attack: Non-root user attempts to modify UEFI variables

Mitigations:

  • All destructive operations require root (UID 0 check)
  • File permissions: 0600 on sensitive files
  • Systemd service runs with limited capabilities
  • No SUID binaries

Scenario 2: Command Injection

Attack: Inject shell commands via GRUB parameters or UEFI variable names

Mitigations:

// Example from grub_config.c
if (strchr(param, ';') || strchr(param, '&') || strchr(param, '|') ||
    strchr(param, '`') || strchr(param, '$') || strchr(param, '\n')) {
    FG_LOG_ERROR("Invalid kernel parameter (contains dangerous characters)");
    return FG_ERROR;
}

Scenario 3: Path Traversal

Attack: Use ../ in backup names to overwrite system files

Mitigations:

// Example from safety.c
if (strchr(name, '/') || strchr(name, '\\') || strstr(name, "..")) {
    FG_LOG_ERROR("Invalid backup name (contains path traversal): %s", name);
    return FG_ERROR;
}

Scenario 4: Buffer Overflow

Attack: Provide oversized inputs to overflow buffers

Mitigations:

  • All string operations use bounded functions (strncpy, snprintf)
  • Buffer sizes validated before allocation
  • No use of unsafe functions (strcpy, sprintf, gets)
// Example: Always bounds-checked
strncpy(config->log_file, value, sizeof(config->log_file) - 1);
config->log_file[sizeof(config->log_file) - 1] = '\0'; // Ensure null termination

Scenario 5: Integer Overflow

Attack: Cause integer overflow in size calculations

Mitigations:

// Example from uefi_vars.c
if (region.size == 0 || region.size > (1UL << 30)) {
    pr_err("fwguard: invalid MMIO region size: %lu\n", region.size);
    return -EINVAL;
}

Scenario 6: UEFI Variable Corruption

Attack: Corrupt UEFI variables to brick system

Mitigations:

  • Automatic backup before modification
  • Checksum verification on backups
  • Dry-run mode for testing
  • User confirmation for CRITICAL operations
  • Rollback capability

Scenario 7: Race Conditions

Attack: TOCTOU (Time-of-Check-Time-of-Use) attacks

Mitigations:

  • Atomic file operations where possible
  • Use of O_EXCL flag for exclusive access
  • No reliance on stat() followed by open()
// Use fstat on open file descriptor, not stat on path
if (fstat(fileno(fp), &st) != 0) {
    // Error handling
}

Security Controls

Input Validation

ALL external inputs are validated:

Input Source Validation Location
CLI arguments getopt_long, bounds checking main.c
Configuration files Parse validation, type checks config.c
UEFI variable names Path traversal check, length limit uefi_vars.c
Kernel parameters Dangerous char check, length limit grub_config.c
Backup names Path traversal check, char whitelist safety.c
MMIO addresses Range check, alignment check fwguard_km.c

Memory Safety

Safe String Functions

// NEVER used in codebase:
strcpy(), strcat(), sprintf(), gets()

// ALWAYS used:
strncpy(), strncat(), snprintf(), fgets()

Bounds Checking

// Example pattern used throughout:
char buffer[256];
if (input_length >= sizeof(buffer)) {
    FG_LOG_ERROR("Input too large");
    return FG_ERROR;
}
strncpy(buffer, input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';

Memory Allocation

// Always check malloc/calloc return
void *data = malloc(size);
if (!data) {
    FG_LOG_ERROR("Memory allocation failed");
    return FG_ERROR;
}

// Always free allocated memory
free(data);
data = NULL;

File Operations Security

Secure Permissions

// Backups: 0600 (owner read/write only)
fchmod(fileno(fp), 0600);

// Config directory: 0755 (world-readable, owner-writable)
mkdir(CONFIG_DIR, 0755);

// State directory: 0700 (owner-only)
mkdir("/var/lib/firmwareguard", 0700);

Atomic Operations

// Use temporary file + rename for atomic writes
snprintf(temp_file, sizeof(temp_file), "%s.tmp", config->grub_file);
// ... write to temp_file ...
rename(temp_file, config->grub_file);

Cryptographic Operations

Checksum Verification

// CRC32-like checksum for backup integrity
uint32_t safety_calculate_checksum(const void *data, size_t size) {
    const uint8_t *bytes = (const uint8_t *)data;
    uint32_t checksum = 0;

    for (size_t i = 0; i < size; i++) {
        checksum = (checksum << 5) + checksum + bytes[i];
    }
    return checksum;
}

// Verification before restore
if (checksum != backup->checksum) {
    FG_LOG_ERROR("Backup checksum mismatch");
    return FG_ERROR;
}

Note: For production, consider using SHA-256 for stronger integrity guarantees.

Privilege Separation

Capability-Based Security

# firmwareguard.service
AmbientCapabilities=CAP_SYS_RAWIO CAP_SYS_ADMIN CAP_DAC_OVERRIDE
NoNewPrivileges=false

Only required capabilities are granted, not full root.

Kernel Module Separation

// Kernel module validates all ioctl inputs
static long fwguard_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    // Validate command
    if (_IOC_TYPE(cmd) != FWGUARD_IOC_MAGIC) {
        return -ENOTTY;
    }

    // Copy from user with validation
    if (copy_from_user(&region, (void __user *)arg, sizeof(region))) {
        return -EFAULT;
    }

    // Bounds check
    if (region.size == 0 || region.size > MAX_REGION_SIZE) {
        return -EINVAL;
    }
}

Attack Surface Analysis

1. Command-Line Interface

Exposure: User-provided arguments Mitigations:

  • getopt_long for parsing
  • Bounds checking on all inputs
  • No shell execution of user input

2. Configuration File

Exposure: Parsing /etc/firmwareguard/config.conf Mitigations:

  • Restricted file permissions (0600)
  • Whitelist-based parsing
  • Type validation
  • Dangerous character rejection

3. UEFI Variables

Exposure: Write to /sys/firmware/efi/efivars/ Mitigations:

  • Path traversal prevention
  • Automatic backup before write
  • Checksum verification
  • User confirmation for CRITICAL changes

4. GRUB Configuration

Exposure: Modify /etc/default/grub Mitigations:

  • Backup before modification
  • Syntax validation
  • Command injection prevention
  • Atomic write (temp file + rename)

5. Kernel Module Interface

Exposure: /dev/fwguard ioctl interface Mitigations:

  • Input validation in kernel space
  • copy_from_user for all user data
  • Bounds checking on all sizes
  • Permission checks

6. Backup System

Exposure: Read/write /var/lib/firmwareguard/backups/ Mitigations:

  • Restricted directory permissions (0700)
  • Path traversal prevention
  • Checksum verification
  • Backup file permissions (0600)

Secure Coding Practices Followed

1. Return Value Checking

// ALWAYS check return values
if (mkdir(path, 0700) != 0 && errno != EEXIST) {
    FG_LOG_ERROR("Failed to create directory: %s", strerror(errno));
    return FG_ERROR;
}

2. Error Handling

// Explicit error codes
#define FG_SUCCESS          0
#define FG_ERROR           -1
#define FG_NO_PERMISSION   -2
#define FG_NOT_FOUND       -3
#define FG_NOT_SUPPORTED   -4

// Consistent error reporting
if (error_condition) {
    FG_LOG_ERROR("Descriptive error message");
    return FG_ERROR;
}

3. Resource Cleanup

// Goto cleanup pattern for complex functions
int function(void) {
    void *data = NULL;
    FILE *fp = NULL;
    int ret = FG_ERROR;

    data = malloc(size);
    if (!data) {
        goto cleanup;
    }

    fp = fopen(path, "r");
    if (!fp) {
        goto cleanup;
    }

    // ... operations ...
    ret = FG_SUCCESS;

cleanup:
    if (data) free(data);
    if (fp) fclose(fp);
    return ret;
}

4. Const Correctness

// Use const for read-only data
const backup_entry_t* safety_get_backup(const safety_context_t *ctx, int index);

// Use const char* for string literals
const char* get_risk_name(risk_level_t risk);

5. Static Analysis

# Run cppcheck for static analysis
make check

# Build with all warnings
CFLAGS = -Wall -Wextra -Werror

Known Vulnerabilities & Limitations

1. UEFI Secure Boot Interaction

Issue: UEFI variable modification may fail with Secure Boot enabled

Impact: MODERATE - Operations may silently fail

Mitigation: Document limitation, check Secure Boot status before operations

Status: DOCUMENTED

2. Kernel Module Symbol Conflicts

Issue: Kernel module may conflict with other firmware security modules

Impact: LOW - Module load will fail (detectable)

Mitigation: Check for conflicts before loading

Status: DOCUMENTED

3. GRUB Configuration Complexity

Issue: Complex GRUB setups (encrypted /boot, custom configs) not fully supported

Impact: MODERATE - May break custom configurations

Mitigation: Backup before modification, dry-run mode

Status: DOCUMENTED

4. Race Condition in Backup Registry

Issue: Concurrent access to backup registry not fully protected

Impact: LOW - Unlikely in normal use (single-user tool)

Mitigation: File locking could be added

Status: FUTURE WORK

5. Checksum Algorithm Strength

Issue: Simple CRC32-like checksum, not cryptographically secure

Impact: LOW - Detects accidental corruption, not malicious tampering

Mitigation: Use SHA-256 for production

Status: FUTURE IMPROVEMENT


Security Testing Recommendations

1. Fuzzing

# Fuzz configuration parser
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
afl-fuzz -i testcases/ -o findings/ -- ./firmwareguard apply @@

2. Static Analysis

# cppcheck
cppcheck --enable=all --inconclusive src/

# Clang static analyzer
scan-build make

3. Dynamic Analysis

# Valgrind for memory leaks
valgrind --leak-check=full --show-leak-kinds=all ./firmwareguard scan

# Address Sanitizer
gcc -fsanitize=address -g src/*.c -o firmwareguard
./firmwareguard scan

4. Penetration Testing

  • Attempt privilege escalation
  • Test command injection vectors
  • Verify path traversal prevention
  • Check buffer overflow boundaries
  • Test race conditions

Incident Response Plan

If Exploit Discovered

  1. Triage: Assess severity (CVSS scoring)
  2. Patch: Develop fix immediately
  3. Disclosure: 90-day coordinated disclosure
  4. CVE: Request CVE assignment if warranted
  5. Communication: Notify users via GitHub, email, website

Vulnerability Reporting

Email: security@firmwareguard.dev PGP Key: Available on project website Response Time: 48 hours acknowledgment, 7 days initial assessment


Security Audit History

Date Auditor Findings Status
2025-11-20 Internal Phase 2 self-review Complete
Future External TBD Planned

Compliance & Standards

Secure Coding Standards

  • CERT C Coding Standard: Followed where applicable
  • CWE Top 25: Addressed common weaknesses
  • OWASP: Applied relevant web/API security principles

Best Practices

  • Principle of Least Privilege
  • Defense in Depth
  • Fail Securely
  • Complete Mediation
  • Input Validation

Conclusion

FirmwareGuard Phase 2 implements extensive security controls to mitigate risks associated with destructive firmware operations. Key protections include:

  1. Comprehensive input validation
  2. Memory safety practices
  3. Automatic backup and rollback
  4. User confirmation for critical operations
  5. Privilege separation

However, users must understand that firmware modification is inherently risky. No software can completely prevent bricking if used improperly. Always maintain external backups and test in safe environments.


Document Version: 1.0 Last Updated: 2025-11-20 Next Review: Phase 3 Planning (Q2 2025)

There aren't any published security advisories