noexec必须写在/etc/fstab对应分区的第4列(挂载选项字段),用英文逗号拼接、无空格;defaults已含exec,须显式写defaults,noexec才能覆盖,默认行为;改完需sudo mount -a验证语法,再用findmnt和执行测试确认生效。

直接说结论:noexec 必须写在 /etc/fstab 对应分区的第4列(挂载选项字段),用英文逗号与其它选项拼接,不能有空格;改完必须运行 sudo mount -a 验证语法,再用 findmnt 或执行测试确认生效。
怎么在 /etc/fstab 里正确添加 noexec
不是“加个参数就行”,而是要精准替换或补全第4列的 options 字段。defaults 已隐含 exec,所以只写 defaults,noexec 才能覆盖掉默认行为。
- 错误写法:
tmpfs /tmp tmpfs defaults 0 0→ 实际仍是可执行 - 正确写法:
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0→ 显式禁用 exec,并同步加固 - ext4 分区示例:
UUID=abcd1234 /home ext4 defaults,noexec,nosuid,nodev 1 2 - 若原行已有其它选项(如
relatime),仍用逗号追加:relatime,noexec,nosuid,nodev
为什么 mount -a 失败后不能直接重启
sudo mount -a 是唯一能提前暴露 fstab 语法错误的命令。常见失败原因包括:漏逗号、多空格、选项拼错(如写成 no-exec)、设备路径不存在、挂载点目录未创建。
- 报错
mount: wrong fs type, bad option, bad superblock→ 通常是选项名错或格式不合法 - 报错
mount: can't find UUID=xxx→ 检查blkid输出是否匹配 - 报错
mount: cannot mount /dev/xxx read-only→ 可能目标已挂载且为 ro,需先umount - 成功无输出即表示语法通过,但不代表策略已应用——还需
findmnt查实际选项
怎么验证 noexec 真的起作用了
别只信 cat /etc/fstab,得看内核当前实际挂载状态和行为表现。
- 查挂载参数:
findmnt -o TARGET,FSTYPE,OPTIONS /tmp→ 输出中必须含noexec - 手动触发执行测试:
echo '#!/bin/sh\necho ok' > /tmp/test.sh && chmod +x /tmp/test.sh && /tmp/test.sh - 预期结果是
bash: /tmp/test.sh: Permission denied,而非command not found或正常输出 - 注意:如果
/tmp是tmpfs且挂载时没指定mode=1777,可能因权限不足导致测试失败,和noexec无关
哪些分区绝对不能加 noexec
加错位置会导致系统无法启动或关键服务崩溃,不是所有“看起来像数据目录”的路径都适合。
-
/、/usr、/bin、/sbin、/lib、/lib64:系统二进制和库所在,加了就execve()失败,连ls都跑不起来 -
/boot:虽然常设为ro,但 GRUB 启动时需读取内核镜像(非执行),加noexec一般无害,但没必要单独加——ro已隐含禁止写入和执行 -
/var/log、/etc:通常不是独立挂载点,只是根分区子目录,noexec对它们无效(挂载选项只作用于文件系统层级,不递归到子目录) - 不确定是否独立挂载?先运行
df -h /path看设备名,再查findmnt /dev/sdX1
真正容易被忽略的是:noexec 对解释器调用完全透明,python /tmp/mal.py 依然能跑——它只拦 ./mal.py。这意味着防护效果高度依赖你对业务执行方式的理解,而不是机械套用选项。


















