Filesystem Permission Interface
When CONFIG_FS_PERMISSION is enabled, the VFS applies POSIX-style
discretionary access control (DAC) using the caller’s effective credentials
(tg_euid / tg_egid). This page describes the common inode helpers,
how mountpoints participate, and how access across a mount is gated by
pseudoFS directory modes.
Prerequisite reading: User and Group Identity.
Configuration
Option |
Role |
|---|---|
|
Per-task-group UID/GID credentials |
|
Store |
|
Enable DAC helpers and VFS enforcement (depends on the two options above) |
Without CONFIG_FS_PERMISSION, the helpers described here return success
and no mode-based checks are performed.
Helpers
inode_checkpermCheck
amode(R_OK/W_OK/X_OK) against an inode’si_owner/i_group/i_mode. Empty macro returning0whenCONFIG_FS_PERMISSIONis disabled.inode_checkpathpermRequire
X_OKon every ancestor of an inode, and on the inode itself when it is a pseudo directory or a mountpoint (directory search / traverse). Ifamodeis non-zero, also require that access on the inode. Takes the inode tree read lock unlessINODE_CHECK_LOCKEDis set (caller already holdsinode_lock/inode_rlock). Empty macro returning0whenCONFIG_FS_PERMISSIONis disabled.inode_checkopenpermValidate that the inode supports the requested open access, then apply mode checks for non-mountpoint inodes.
fs_checkmodeCore owner/group/other test used by the helpers above and by filesystems such as tmpfs and littlefs.
Optional mountpoint hook
struct mountpt_operations may provide a permission method for
in-volume DAC. The field is at the end of the structure so existing
positional initialisers remain valid.
tmpfs implements
tmpfs_permission.Filesystems without Unix ownership on disk (for example FAT and ROMFS) leave the method
NULL.
The VFS mount-crossing gate does not depend on this hook. Entry into a
volume is enforced with inode_checkpathperm against the mountpoint
inode’s stored i_mode. In-volume checks remain the filesystem’s job
(tmpfs and littlefs enforce DAC inside their own open/mkdir/path helpers.
mops->permission is an optional common entry point for the same policy;
the VFS does not invoke it for mount-crossing).
Open vs traverse
Mountpoint inodes are not open-mode-checked by inode_checkopenperm.
Applying the mount directory’s mode bits as file open modes would require
read/write on the mount directory merely to open a file beneath it.
Traverse is separate: callers use inode_checkpathperm so parent
directories and the mountpoint itself still require X_OK.
Typical order after a successful inode_find:
inode_checkpathperm(inode, 0, 0)— search permission on the path prefix (and on the mountpoint when entering a volume). Call sites that already hold the tree lock passINODE_CHECK_LOCKED; mount and pseudoFS create/remove may pass a non-zeroamode(for exampleW_OK) to combine traverse and target checks in one call.Operation-specific checks —
inode_checkopenperm, or the filesystem’s own methods for paths inside a mount.
Mount-crossing
Path walk stops at a mountpoint and returns that inode plus a relative path into the volume. Without traverse checks, a restrictive mode on a pseudoFS parent would not protect objects under a filesystem mounted beneath it.
Example:
/secure_dir # pseudoFS directory, mode 0700, owner root
/secure_dir/mnt # mounted volume (tmpfs, FAT, ...)
/secure_dir/mnt/a # object inside the volume
inode_checkpathperm requires X_OK on secure_dir and on the
mountpoint mnt. A non-root open of /secure_dir/mnt/a therefore
returns EACCES, even if the mounted filesystem itself has no Unix DAC.
Where the checks run
After
inode_findin open, unlink, mkdir, rmdir, rename, stat, chstat, statfs, readlink, mount, and umount.inode_checkpathpermtakesinode_rlockunless the caller already holds the tree lock (INODE_CHECK_LOCKED).Inside
inode_reserve/inode_removefor pseudoFS create and remove (ancestorX_OKand parentW_OKin one call, underinode_lock).
Who enforces what
PseudoFS parent dirs —
X_OK(andW_OKwhen creating/removing)Mountpoint inode —
X_OKto enter the volume (storedi_mode)Inside the volume — Filesystem methods; optional
mops->permissionFAT / ROMFS — No Unix ownership on disk; entry still gated by the mountpoint
i_mode
Execute permission
With CONFIG_BINFMT_CHECKEXEC (the default with
CONFIG_SCHED_USER_IDENTITY), exec(), posix_spawn() and the other
functions that start a program from a file refuse a file that has no execute
permission, with EACCES. Each binary format checks the mode of the file
that it opens, also for scripts and for their interpreters. With
CONFIG_SCHED_USER_IDENTITY, the owner, group or other execute bit is
checked for the effective user and group IDs, and root needs any execute bit.
Without it, any execute bit is enough.
The mode is the one that stat() reports:
File systems without a stored mode (FAT, xipfs, zipfs, spiffs, nxffs, and tmpfs without
CONFIG_FS_PERMISSION) report execute permission for all files.File systems that store the mode (littlefs, smartfs, mnemofs, tmpfs with
CONFIG_FS_PERMISSION, romfs, cromfs, hostfs, NFS, v9fs) report it. A program that was created with a mode without execute bits needschmodbefore it can run.A file system mounted with
MS_NOEXECreports its regular files without execute permission.
References
fs/inode/fs_inode.c—inode_checkperm,inode_checkpathperminclude/nuttx/fs/fs.h—struct mountpt_operationsfs/tmpfs/fs_tmpfs.c—tmpfs_permissionUser and Group Identity — credential model
LITTLEFS — littlefs in-volume DAC
TMPFS — tmpfs overview