umask不是设置默认权限,而是定义创建文件或目录时自动屏蔽的权限位;实际权限由“文件0666 & (~umask)、目录0777 & (~umask)”计算,且普通文件永远无执行位。

动态生成的文件初始权限不由内核API直接控制,而是由创建进程的umask和open()或creat()系统调用传入的mode参数共同决定。内核本身不提供“在文件创建瞬间注入ACL或特殊属性”的通用API;所谓“控制初始权限”,本质是规范用户空间行为,并辅以内核机制支持落地。
核心机制:umask + open() mode 是起点
所有通过系统调用(如open(path, flags, mode))创建的普通文件,其初始权限 = mode & ~umask。内核只做这一层按位运算,不额外干预。
- umask是进程级掩码,继承自父进程,默认通常为0022(目录755 → 实际755,文件644 → 实际644)
-
mode必须显式传入:若调用
open("log.txt", O_CREAT|O_WRONLY, 0600),即使umask=0002,结果仍是600(所有者读写) - 不传mode(如仅
O_CREAT无第三参数)会导致未定义行为,多数libc会默认补0666,但不可依赖
让新文件自动带ACL:靠默认ACL(default ACL)而非内核API
若需动态生成的文件一创建就具备某用户/组的特定权限(例如:所有日志文件默认允许syslog组读取),不能靠内核模块或sysfs接口实时设置,而应提前在父目录设好默认ACL:
- 执行
setfacl -d -m g:syslog:r-- /var/log/myapp - 此后该目录下任何进程创建的新文件(包括
touch、fopen()、cp等),都会自动获得group:syslog:r--条目 - 注意:
-d只影响新文件,已有文件需单独setfacl -R补设
需要更底层控制?靠文件系统挂载选项与安全模块
真正绕过umask、强制统一初始属性的路径,不在通用VFS层,而在两个方向:
-
ext4/xfs挂载选项:启用
default_permissions(默认开启)确保传统权限生效;配合acl选项才使上述默认ACL起作用 -
LSM框架(如SELinux/AppArmor):可定义策略,让特定进程(如
/usr/bin/mydaemon)创建的所有文件自动打上指定安全上下文(如system_u:object_r:mylog_t:s0),进而通过策略控制访问——但这属于MAC层,不是POSIX权限或ACL
内核模块能做什么?极少,且不推荐用于权限初始化
虽然内核模块可通过security_inode_create()钩子拦截文件创建,理论上修改*mode参数,但:
- 这违反POSIX语义,破坏应用预期,极易引发兼容性问题
- 主流发行版默认禁用此类钩子(CONFIG_SECURITY_YAMA、SELinux策略限制)
- 无法覆盖所有创建路径(如tmpfs、procfs、devtmpfs中的文件不走同一路径)
- 运维难度高,调试困难,不符合最小权限与可审计原则

















