selinux拦截mysql读写时,先用getenforce和setenforce 0验证是否为根因;再通过ausearch -m avc -c mysqld定位拒绝点;最后用semanage fcontext+restorecon修复上下文或setsebool启用对应布尔值。

SELinux 拦截数据库读写时,通常不报明确错误,只表现为 MySQL 启动失败、连接后查询报错(如 Can't open file、Permission denied)、日志里反复出现 EACCES 或 EIO,甚至服务能启动但无法访问数据文件。排查重点不是“关 SELinux”,而是确认它是否在拦、拦在哪、怎么精准放行。
确认 SELinux 是否是根因
先排除其他干扰因素:
- 运行
getenforce—— 若返回Enforcing,说明策略正在生效;若为Permissive或Disabled,则基本可排除 SELinux - 临时切宽容模式验证:
setenforce 0,然后立即重启数据库:systemctl restart mysqld;若此时能正常启动且读写无误,基本锁定 SELinux - 切回强制模式:
setenforce 1,避免长期处于 Permissive 影响审计日志完整性
查拒绝日志,定位具体被拒动作
数据库的拒绝记录不会出现在 /var/log/messages 或 journalctl -u mysqld 的常规输出中,必须查审计日志:
- 查最近的 AVC 拒绝:
ausearch -m avc -ts recent | grep mysqld - 按进程名过滤更准:
ausearch -m avc -c mysqld - 用
audit2why解读每条拒绝:ausearch -m avc -c mysqld | audit2why—— 它会指出缺哪条allow规则,并建议执行restorecon或setsebool - 生成可读报告(需已安装
setroubleshoot):sealert -a /var/log/audit/audit.log
修复三类高频拦截场景
90% 的数据库 SELinux 故障集中在以下三类上下文错配:
-
数据目录标签错误:比如把 MySQL 数据目录移到
/data/mysql,但该路径默认标签是default_t或var_t,而 mysqld 进程类型mysqld_t只被允许读写mysqld_db_t
→ 查当前标签:ls -Zd /data/mysql
→ 修复:先添加永久规则semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?",再恢复上下文restorecon -Rv /data/mysql -
套接字或日志文件标签异常:MySQL 的 socket(如
/var/lib/mysql/mysql.sock)或错误日志(如/var/log/mysqld.log)若被手动移动或创建,可能带错标签
→ 查标签:ls -Z /var/lib/mysql/mysql.sock /var/log/mysqld.log
→ 修复:restorecon -v /var/lib/mysql/mysql.sock /var/log/mysqld.log,或批量恢复整个目录restorecon -Rv /var/lib/mysql /var/log/mysqld.log -
布尔值未开启:例如 MySQL 需要连接网络(主从复制、外部认证)、访问用户家目录、或使用 NFS 存储
→ 查相关开关:getsebool -a | grep mysql(或grep -i sql)
→ 临时启用:setsebool mysql_connect_any on(或mysqld_can_network_connect on)
→ 永久生效:setsebool -P mysql_connect_any on
不推荐直接用 audit2allow 生成策略
audit2allow 会基于日志自动生成 allow 规则,但它无法区分“合理需求”和“危险行为”。对数据库这类高权限服务,盲目加载自定义模块可能绕过关键防护。只有在确认是策略缺失(而非上下文或布尔值问题),且经过严格测试后,才考虑:
ausearch -m avc -c mysqld | audit2allow -M mysql_customsemodule -i mysql_custom.pp- 务必配合
semodule -l | grep mysql确认模块已加载,并持续观察日志是否还有新拒绝











