A comprehensive, secure crate for dropping privileges in Unix-based systems.
The privdrop
crate provides a robust, security-focused mechanism for applications that need to drop root privileges safely. This is a critical security practice for services that start with root permissions but need to operate with minimal privileges during execution.
- Atomic Operations: All privilege-dropping actions occur in one atomic step
- Comprehensive Security: Handles all aspects of privilege dropping properly
- Flexible Configuration: Builder pattern for simple, chainable setup
- Error Handling: Detailed error reporting for security operations
- Cross-Platform: Works on Unix-like systems with privilge-dropping syscalls
The crate enables processes to:
- Change Root Directory (chroot): Isolate the application's filesystem access
- Switch User: Relinquish root privileges by changing to a non-root user
- Manage Primary Group: Control primary group membership
- Configure Supplementary Groups: Set precise access permissions
- Handle Numeric IDs: Optionally use UIDs/GIDs directly when names aren't available
Add the dependency to your Cargo.toml
:
[dependencies]
privdrop = "0.5.5"
This example shows the simplest way to drop privileges:
use privdrop::PrivDrop;
fn main() {
// Application starts with root privileges
PrivDrop::default()
.chroot("/var/empty") // Restrict filesystem access
.user("nobody") // Switch to unprivileged user
.apply() // Apply all changes atomically
.unwrap_or_else(|e| panic!("Failed to drop privileges: {}", e));
// Continue running with dropped privileges...
}
This example demonstrates more complex configurations:
use privdrop::PrivDrop;
fn main() {
PrivDrop::default()
// Basic configuration
.chroot("/var/empty") // Change root directory
.user("service-user") // Switch to non-root user
// Group management
.group("service-group") // Set primary group
.group_list(&["www-data", "logs"]) // Add supplementary groups
.include_default_supplementary_groups() // Include user's default groups
// Fallback options
.fallback_to_ids_if_names_are_numeric() // Allow numeric UIDs/GIDs
// Apply all changes
.apply()
.unwrap_or_else(|e| panic!("Failed to drop privileges: {}", e));
// Continue running with limited privileges...
}
The privilege dropping process is carefully designed to prevent security issues:
- Preloading: System resources are preloaded before dropping privileges to prevent deadlocks
- Complete Preparation: All user/group IDs are looked up while still privileged
- Chroot First: Root directory is changed before user/group IDs to prevent bypassing
- Atomic ID Changes: User and group IDs are changed in the correct order
- All-or-Nothing: If any operation fails, the entire privilege drop fails
This crate is supported on:
- Linux
- macOS
- FreeBSD
- OpenBSD
- Other Unix-like systems that provide the necessary privilege-dropping syscalls
For detailed API documentation and more examples, see the API documentation.
Licensed under ISC license, see LICENSE for details.