This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 4002e6af5f99ec7bf2fb91335f4c325c1ec95d9c
Author: Abhishek Mishra <[email protected]>
AuthorDate: Sun Aug 2 17:54:38 2026 +0000

    Documentation: describe FS permission interface and mount-crossing
    
    Document inode_checkperm / inode_checkpathperm, mountpoint traverse vs open
    semantics, and the optional mountpt_operations.permission hook in
    file_permission.rst.
    
    Signed-off-by: Abhishek Mishra <[email protected]>
---
 Documentation/components/filesystem/littlefs.rst |   3 +
 Documentation/components/filesystem/pseudofs.rst |   4 +
 Documentation/components/filesystem/tmpfs.rst    |  10 ++
 Documentation/implementation/file_permission.rst | 137 +++++++++++++++++++++++
 Documentation/implementation/index.rst           |   1 +
 Documentation/implementation/user_identity.rst   |  13 ++-
 6 files changed, 165 insertions(+), 3 deletions(-)

diff --git a/Documentation/components/filesystem/littlefs.rst 
b/Documentation/components/filesystem/littlefs.rst
index 35c042cc8f7..7eeb477012e 100644
--- a/Documentation/components/filesystem/littlefs.rst
+++ b/Documentation/components/filesystem/littlefs.rst
@@ -57,3 +57,6 @@ target directory.
 Files created before permission support was enabled, or without stored
 attributes, default to mode ``0777`` until ``chmod``/``chown`` sets explicit
 metadata.
+
+Path components above the littlefs mountpoint are enforced by the VFS; see
+:ref:`file-permission`.
diff --git a/Documentation/components/filesystem/pseudofs.rst 
b/Documentation/components/filesystem/pseudofs.rst
index c8e13cd4007..e8397094fac 100644
--- a/Documentation/components/filesystem/pseudofs.rst
+++ b/Documentation/components/filesystem/pseudofs.rst
@@ -211,3 +211,7 @@ will also fail. You cannot do this, for example:
 
 See also NxFileSystem in 
 `Porting Guide 
<https://cwiki.apache.org/confluence/display/NUTTX/Porting+Guide>`_
+
+When ``CONFIG_FS_PERMISSION`` is enabled, pseudoFS directory modes also gate
+access into mounted volumes beneath them.  See
+:ref:`file-permission`.
diff --git a/Documentation/components/filesystem/tmpfs.rst 
b/Documentation/components/filesystem/tmpfs.rst
index 1d0dacb4901..c6f146e9ace 100644
--- a/Documentation/components/filesystem/tmpfs.rst
+++ b/Documentation/components/filesystem/tmpfs.rst
@@ -11,3 +11,13 @@ At runtime, simply use ``mount -t tmpfs /tmp`` to have a 
``/tmp`` folder backed
 Be aware that TMPFS is backed by kernel memory thus don't expect to store big 
files on it and its size is limited by free kernel memory.
 
 We can watch the size of TMPFS with ``df -h`` command, especially you can see 
the ``Size`` column of TMPFS changes when files are added or removed in the 
TMPFS folder. Changes in TMPFS size is always reflected by reverse changes of 
free kernel memory size.
+
+Permissions
+===========
+
+When ``CONFIG_FS_PERMISSION`` is enabled, tmpfs stores per-object owner, group,
+and mode and enforces them on path operations inside the volume.  It also
+implements the optional ``mountpt_operations.permission`` hook.
+
+Access into the mount from the pseudoFS is gated by the VFS (parent and
+mountpoint ``X_OK``).  See :ref:`file-permission`.
diff --git a/Documentation/implementation/file_permission.rst 
b/Documentation/implementation/file_permission.rst
new file mode 100644
index 00000000000..6b6f50c5118
--- /dev/null
+++ b/Documentation/implementation/file_permission.rst
@@ -0,0 +1,137 @@
+.. _file-permission:
+
+========================================
+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: :ref:`user-identity`.
+
+Configuration
+=============
+
+=============================== =============================================
+Option                          Role
+=============================== =============================================
+``CONFIG_SCHED_USER_IDENTITY``  Per-task-group UID/GID credentials
+``CONFIG_PSEUDOFS_ATTRIBUTES``  Store ``i_mode`` / ``i_owner`` / ``i_group``
+                                on pseudoFS inodes
+``CONFIG_FS_PERMISSION``        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_checkperm``
+  Check ``amode`` (``R_OK`` / ``W_OK`` / ``X_OK``) against an inode's
+  ``i_owner`` / ``i_group`` / ``i_mode``.  Empty macro returning ``0``
+  when ``CONFIG_FS_PERMISSION`` is disabled.
+
+``inode_checkpathperm``
+  Require ``X_OK`` on every ancestor of an inode, and on the inode itself
+  when it is a pseudo directory or a mountpoint (directory search /
+  traverse).  If ``amode`` is non-zero, also require that access on the
+  inode.  Takes the inode tree read lock unless ``INODE_CHECK_LOCKED`` is
+  set (caller already holds ``inode_lock`` / ``inode_rlock``).  Empty
+  macro returning ``0`` when ``CONFIG_FS_PERMISSION`` is disabled.
+
+``inode_checkopenperm``
+  Validate that the inode supports the requested open access, then apply
+  mode checks for non-mountpoint inodes.
+
+``fs_checkmode``
+  Core 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``:
+
+1. ``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 pass ``INODE_CHECK_LOCKED``; mount and
+   pseudoFS create/remove may pass a non-zero ``amode`` (for example
+   ``W_OK``) to combine traverse and target checks in one call.
+2. 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_find`` in open, unlink, mkdir, rmdir, rename, stat, chstat,
+  statfs, readlink, mount, and umount.  ``inode_checkpathperm`` takes
+  ``inode_rlock`` unless the caller already holds the tree lock
+  (``INODE_CHECK_LOCKED``).
+* Inside ``inode_reserve`` / ``inode_remove`` for pseudoFS create and remove
+  (ancestor ``X_OK`` and parent ``W_OK`` in one call, under ``inode_lock``).
+
+Who enforces what
+-----------------
+
+* **PseudoFS parent dirs** — ``X_OK`` (and ``W_OK`` when creating/removing)
+* **Mountpoint inode** — ``X_OK`` to enter the volume (stored ``i_mode``)
+* **Inside the volume** — Filesystem methods; optional ``mops->permission``
+* **FAT / ROMFS** — No Unix ownership on disk; entry still gated by the
+  mountpoint ``i_mode``
+
+References
+==========
+
+* ``fs/inode/fs_inode.c`` — ``inode_checkperm``, ``inode_checkpathperm``
+* ``include/nuttx/fs/fs.h`` — ``struct mountpt_operations``
+* ``fs/tmpfs/fs_tmpfs.c`` — ``tmpfs_permission``
+* :ref:`user-identity` — credential model
+* :doc:`/components/filesystem/littlefs` — littlefs in-volume DAC
+* :doc:`/components/filesystem/tmpfs` — tmpfs overview
diff --git a/Documentation/implementation/index.rst 
b/Documentation/implementation/index.rst
index 5ea1eaa7224..4d53b205c6d 100644
--- a/Documentation/implementation/index.rst
+++ b/Documentation/implementation/index.rst
@@ -16,6 +16,7 @@ Implementation Details
    device_nodes.rst
    drivers_design.rst
    file_descriptors.rst
+   file_permission.rst
    hardfaults.rst
    interrupt_controls.rst
    ioctl.rst
diff --git a/Documentation/implementation/user_identity.rst 
b/Documentation/implementation/user_identity.rst
index 5c9486901bd..a831a1f2353 100644
--- a/Documentation/implementation/user_identity.rst
+++ b/Documentation/implementation/user_identity.rst
@@ -86,7 +86,9 @@ Configuration
 
 ``CONFIG_FS_PERMISSION``
   Enables filesystem ownership and permission enforcement. Requires
-  ``CONFIG_SCHED_USER_IDENTITY``.
+  ``CONFIG_SCHED_USER_IDENTITY`` and ``CONFIG_PSEUDOFS_ATTRIBUTES``.
+  See :ref:`file-permission` for the VFS helpers, mount-crossing
+  traverse rules, and testing notes.
 
 Pseudo-Filesystem Ownership
 ===========================
@@ -96,5 +98,10 @@ enabled, ``inode_alloc()`` assigns ``i_owner`` and 
``i_group`` from the
 caller's effective credentials. This covers
 message queues (``mq_open()``), named semaphores (``sem_open()``), shared
 memory objects (``shm_open()``), FIFOs (``mkfifo()``), and pseudo-files
-created through the same inode reservation path. Open-time permission checks
-use ``inode_checkopenperm()`` (or ``inode_checkperm()`` for message queues).
+created through the same inode reservation path.
+
+Path resolution requires directory search permission (``X_OK``) on ancestors
+via ``inode_checkpathperm()``.  Open-time checks on the final node use
+``inode_checkopenperm()`` (or ``inode_checkperm()`` for named IPC
+objects).  Full details, including mounts under private pseudoFS parents,
+are in :ref:`file-permission`.

Reply via email to