Storage Hardening
MinIO AIStor supports kernel-level storage protection to prevent accidental deletion of data directories by system administrators while allowing the MinIO AIStor process full control over managed drives.
This protection is critical for production environments where a mistyped rm -rf /drive* command could result in catastrophic data loss.
Protection model
Storage hardening provides:
- MinIO AIStor process: Full read/write/delete access to managed drives.
- Host OS (including root): Cannot delete protected data. With SELinux, other processes have read-only access to protected directories. With eBPF LSM, other processes are blocked from deleting or renaming files owned by a protected UID.
- Kernel-level enforcement: Protection cannot be bypassed through normal filesystem operations.
- No performance impact: Both implementations add negligible overhead.
Choose an implementation
MinIO AIStor provides two storage protection implementations:
| Feature | SELinux | eBPF LSM |
|---|---|---|
| Kernel version | Any (built into most enterprise distros) | Supported on all AIStor-compatible kernels |
| Best for | RHEL, CentOS, Fedora | Ubuntu, Debian, other distros |
| Configuration | Policy files and labels | Kernel parameter + daemon |
| Protection model | File labels (minio_data_t) |
File ownership (UID allowlist) |
| Maturity | 20+ years in production | Newer, but production-ready |
Recommendations:
- RHEL/CentOS/Fedora: Use SELinux (better integration, native support)
- Ubuntu/Debian: Use eBPF LSM (default kernel support, no SELinux required)
- Other distributions: Use eBPF LSM for universal compatibility
SELinux-based protection
Use SELinux-based storage protection on RHEL, CentOS, Fedora, and other SELinux-enabled systems.
Prerequisites
- RHEL 8/9, CentOS 8/9, Fedora, or any Linux distribution with SELinux.
- SELinux in enforcing or permissive mode (not disabled).
- SELinux policy development tools.
Check SELinux status:
getenforce
The output should be Enforcing or Permissive.
If the output is Disabled, enable SELinux first:
# Edit SELinux config
sudo vi /etc/selinux/config
# Set SELINUX=enforcing
SELINUX=enforcing
# Reboot required
sudo reboot
Install required tools:
sudo dnf install -y policycoreutils-python-utils selinux-policy-devel
Setup
Follow these steps to create and install the SELinux policy.
Create the SELinux policy module
Create a file named minio_storage.te:
policy_module(minio_storage, 1.0.0)
require {
type unconfined_t;
type user_t;
type sysadm_t;
type init_t;
class dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write };
class file { append create getattr ioctl link lock map open read rename setattr unlink write };
}
# Define MinIO domain
type minio_t;
type minio_exec_t;
type minio_data_t;
# MinIO binary type
files_type(minio_exec_t)
# MinIO data directories type
files_type(minio_data_t)
# Allow MinIO domain to be entered from init
init_daemon_domain(minio_t, minio_exec_t)
domain_type(minio_t)
# MinIO process has FULL access to minio_data_t
allow minio_t minio_data_t:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write };
allow minio_t minio_data_t:file { append create getattr ioctl link lock map open read rename setattr unlink write };
# All other processes can ONLY read, CANNOT delete or write
allow unconfined_t minio_data_t:dir { getattr open read search };
allow unconfined_t minio_data_t:file { getattr open read };
allow user_t minio_data_t:dir { getattr open read search };
allow user_t minio_data_t:file { getattr open read };
allow sysadm_t minio_data_t:dir { getattr open read search };
allow sysadm_t minio_data_t:file { getattr open read };
# MinIO network access
corenet_tcp_bind_generic_node(minio_t)
corenet_tcp_connect_http_port(minio_t)
corenet_tcp_bind_http_port(minio_t)
corenet_tcp_bind_generic_port(minio_t)
corenet_udp_bind_generic_port(minio_t)
# MinIO system permissions
kernel_read_system_state(minio_t)
dev_read_urand(minio_t)
fs_getattr_xattr_fs(minio_t)
files_read_etc_files(minio_t)
miscfiles_read_localization(minio_t)
sysnet_dns_name_resolve(minio_t)
# Allow MinIO to execute itself
allow minio_t minio_exec_t:file { execute execute_no_trans getattr map open read };
Compile and install the policy
# Compile the policy module
checkmodule -M -m -o minio_storage.mod minio_storage.te
# Package the module
semodule_package -o minio_storage.pp -m minio_storage.mod
# Install the policy module
semodule -i minio_storage.pp
# Verify installation
semodule -l | grep minio_storage
Label the MinIO AIStor binary
# Set file context for MinIO AIStor binary
semanage fcontext -a -t minio_exec_t "/usr/local/bin/minio"
# Apply the label
restorecon -v /usr/local/bin/minio
# Verify the label
ls -Z /usr/local/bin/minio
The output should show system_u:object_r:minio_exec_t:s0.
Label data directories
For each drive that MinIO AIStor manages:
# Add file context rules for each drive
semanage fcontext -a -t minio_data_t "/drive1(/.*)?"
semanage fcontext -a -t minio_data_t "/drive2(/.*)?"
semanage fcontext -a -t minio_data_t "/drive3(/.*)?"
semanage fcontext -a -t minio_data_t "/drive4(/.*)?"
# Apply labels recursively
restorecon -R -v /drive1 /drive2 /drive3 /drive4
# Verify labels
ls -Z /drive1
The output should show system_u:object_r:minio_data_t:s0.
Verify SELinux protection
Test that protection is working:
# Create a test file (as MinIO AIStor or with proper context)
sudo -u minio-user touch /drive1/test-file
# Try to delete as root (should fail)
sudo rm /drive1/test-file
# Expected: rm: cannot remove '/drive1/...': Permission denied
Check that processes are running in the correct SELinux domain:
# Check MinIO AIStor process context
ps -eZ | grep minio
# Expected: system_u:system_r:minio_t:s0
# Check file contexts
ls -Z /drive1
# Expected: system_u:object_r:minio_data_t:s0
eBPF LSM-based protection
Use eBPF LSM-based storage protection on Ubuntu, Debian, and other distributions without SELinux.
Prerequisites
- AIStor-compatible Linux kernel with eBPF LSM support.
CONFIG_BPF_LSM=ykernel configuration.lsm=...,bpfkernel boot parameter.- Root access for installation.
Check kernel support:
# Check kernel version
uname -r
# Check if eBPF LSM is enabled
cat /sys/kernel/security/lsm | grep -q bpf && echo "Supported" || echo "Not supported"
# Check kernel configuration (if available)
grep CONFIG_BPF_LSM /boot/config-$(uname -r)
Enable eBPF LSM
If eBPF LSM is not in the LSM list, enable it via kernel boot parameters.
Install required packages
How eBPF protection works
The minio-lsm-bpf daemon uses a pure UID-based protection model.
You pass it one or more UIDs to protect using the -u option, typically the UID of the user that runs MinIO AIStor.
The daemon then protects all files owned by those UIDs, regardless of their location on disk:
- The daemon attaches eBPF programs to the kernel LSM hooks.
- When a process attempts to delete a file, the hook checks whether the file is owned by a protected UID.
- If the file is owned by a protected UID, the operation is allowed only when the deleting process runs as the same UID.
- All other processes, including
root, are blocked from deleting files owned by a protected UID.
The eBPF LSM hooks intercept:
unlink()- File deletion.rmdir()- Directory deletion.rename()- Moving or renaming files.
Because protection is based on file ownership rather than path, any drive whose files are owned by a protected UID is covered automatically.
Setup
Follow these steps to build, install, and run the protection daemon from the scripts/ebpf directory of the MinIO AIStor source tree.
Verify kernel support
# Check eBPF LSM support
if ! cat /sys/kernel/security/lsm | grep -q bpf; then
echo "eBPF LSM not enabled - add 'bpf' to kernel boot parameters"
exit 1
fi
echo "Kernel support: OK"
You can also run make check-kernel from the scripts/ebpf directory to verify that the system is ready.
Build the eBPF program
cd scripts/ebpf
# Verify the required build tools are present
make check-tools
# Build the binary (default 'all' target)
make
# Verify the binary was created
ls -lh minio-lsm-bpf
Install the binary
# Install to system path
sudo install -m 0755 minio-lsm-bpf /usr/local/bin/
Create the systemd service
Determine the UID that MinIO AIStor runs as:
# Get the UID of minio-user (for example, 1000)
id -u minio-user
Create /etc/systemd/system/minio-lsm-bpf.service, replacing 1000 with the UID from the previous command:
[Unit]
Description=MinIO eBPF LSM Protection
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/minio-lsm-bpf -u 1000
Restart=always
RestartSec=10
LimitMEMLOCK=infinity
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
To protect more than one UID, repeat the -u option, for example ExecStart=/usr/local/bin/minio-lsm-bpf -u 1000 -u 1001.
The daemon supports the following options:
-u UID- UID whose files are protected (required, can be repeated).-v- Enable verbose logging (logs allowed operations in addition to blocked operations).
Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable --now minio-lsm-bpf
sudo systemctl status minio-lsm-bpf
Verify eBPF protection
Test that protection is working:
# Create a test file owned by the protected user
sudo -u minio-user touch /drive1/test-file
# Try to delete as root (should fail)
sudo rm /drive1/test-file
# Expected: rm: cannot remove '/drive1/test-file': Operation not permitted
# Verify the file still exists
ls -l /drive1/test-file
# Delete as the file owner (should succeed)
sudo -u minio-user rm /drive1/test-file
Check service status:
# Service status
sudo systemctl status minio-lsm-bpf
# View logs (blocked operations appear in real time)
sudo journalctl -u minio-lsm-bpf -f
# Example output:
# BLOCKED unlink: op_pid=1234 op_uid=0 comm=rm owner_uid=1000
Troubleshooting
MinIO AIStor cannot start
If MinIO AIStor fails to start after enabling protection:
MinIO AIStor cannot write to drives
If MinIO AIStor cannot write to protected drives:
Protection not blocking root
If root can still delete files:
Security considerations
Defense in depth
Storage hardening is one layer of defense. Implement additional measures:
- Regular backups to separate storage
- Filesystem snapshots (ZFS, Btrfs, LVM)
- Restricted SSH access with key-based authentication
- Multi-factor authentication for administrative access
- Monitoring for unauthorized access attempts
Limitations
Both implementations have known limitations:
| Limitation | Mitigation |
|---|---|
| Root can disable the protection service | Monitor service status, use systemd protections |
| Root can change kernel parameters via reboot | Use TPM/UEFI Secure Boot to protect boot parameters |
| Direct block device access bypasses filesystem | Use disk encryption, monitor block device access |