Document Type: Security Considerations & Threat Model Version: 1.0 Date: 2025-11-20 Classification: Public
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.
- System Firmware: UEFI variables, BIOS settings, boot configuration
- Boot Integrity: GRUB configuration, kernel parameters
- System Availability: Prevention of bricking, boot failures
- User Data: Configuration files, backup registry, logs
- Malicious User: Local attacker with limited privileges
- Malicious Software: Malware attempting to exploit FirmwareGuard
- Supply Chain Attack: Compromised binaries or dependencies
- Accidental Misuse: User error causing system damage
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
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;
}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;
}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 terminationAttack: 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;
}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
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
}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 |
// NEVER used in codebase:
strcpy(), strcat(), sprintf(), gets()
// ALWAYS used:
strncpy(), strncat(), snprintf(), fgets()// 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';// 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;// 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);// 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);// 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.
# firmwareguard.service
AmbientCapabilities=CAP_SYS_RAWIO CAP_SYS_ADMIN CAP_DAC_OVERRIDE
NoNewPrivileges=false
Only required capabilities are granted, not full root.
// 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(®ion, (void __user *)arg, sizeof(region))) {
return -EFAULT;
}
// Bounds check
if (region.size == 0 || region.size > MAX_REGION_SIZE) {
return -EINVAL;
}
}Exposure: User-provided arguments Mitigations:
- getopt_long for parsing
- Bounds checking on all inputs
- No shell execution of user input
Exposure: Parsing /etc/firmwareguard/config.conf Mitigations:
- Restricted file permissions (0600)
- Whitelist-based parsing
- Type validation
- Dangerous character rejection
Exposure: Write to /sys/firmware/efi/efivars/ Mitigations:
- Path traversal prevention
- Automatic backup before write
- Checksum verification
- User confirmation for CRITICAL changes
Exposure: Modify /etc/default/grub Mitigations:
- Backup before modification
- Syntax validation
- Command injection prevention
- Atomic write (temp file + rename)
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
Exposure: Read/write /var/lib/firmwareguard/backups/ Mitigations:
- Restricted directory permissions (0700)
- Path traversal prevention
- Checksum verification
- Backup file permissions (0600)
// ALWAYS check return values
if (mkdir(path, 0700) != 0 && errno != EEXIST) {
FG_LOG_ERROR("Failed to create directory: %s", strerror(errno));
return FG_ERROR;
}// 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;
}// 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;
}// 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);# Run cppcheck for static analysis
make check
# Build with all warnings
CFLAGS = -Wall -Wextra -WerrorIssue: 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
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
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
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
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
# Fuzz configuration parser
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
afl-fuzz -i testcases/ -o findings/ -- ./firmwareguard apply @@# cppcheck
cppcheck --enable=all --inconclusive src/
# Clang static analyzer
scan-build make# 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- Attempt privilege escalation
- Test command injection vectors
- Verify path traversal prevention
- Check buffer overflow boundaries
- Test race conditions
- Triage: Assess severity (CVSS scoring)
- Patch: Develop fix immediately
- Disclosure: 90-day coordinated disclosure
- CVE: Request CVE assignment if warranted
- Communication: Notify users via GitHub, email, website
Email: security@firmwareguard.dev PGP Key: Available on project website Response Time: 48 hours acknowledgment, 7 days initial assessment
| Date | Auditor | Findings | Status |
|---|---|---|---|
| 2025-11-20 | Internal | Phase 2 self-review | Complete |
| Future | External | TBD | Planned |
- CERT C Coding Standard: Followed where applicable
- CWE Top 25: Addressed common weaknesses
- OWASP: Applied relevant web/API security principles
- Principle of Least Privilege
- Defense in Depth
- Fail Securely
- Complete Mediation
- Input Validation
FirmwareGuard Phase 2 implements extensive security controls to mitigate risks associated with destructive firmware operations. Key protections include:
- Comprehensive input validation
- Memory safety practices
- Automatic backup and rollback
- User confirmation for critical operations
- 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)