nuttx/Documentation/implementation/user_identity.rst
Abhishek Mishra ddf38abe45 Documentation: describe credential APIs and pseudo-fs ownership
Document setreuid/setregid, getresuid/getresgid, and how inode_reserve
assigns owner and group for pseudo-filesystem objects.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
2026-07-30 09:48:10 +08:00

100 lines
3.6 KiB
ReStructuredText

.. _user-identity:
=======================
User and Group Identity
=======================
When ``CONFIG_SCHED_USER_IDENTITY`` is enabled, each task group maintains POSIX
process credentials. All threads within a task group share the same credentials
(see :ref:`tasks-vs-threads`).
Credentials
===========
The full POSIX three-field credential model is stored in ``struct task_group_s``
(``include/nuttx/sched.h``):
* ``tg_uid`` / ``tg_gid`` — real user and group IDs.
* ``tg_euid`` / ``tg_egid`` — effective IDs used for permission checks.
* ``tg_suid`` / ``tg_sgid`` — saved set-IDs that allow a non-root process to
restore a previously held effective ID.
All six fields are zero-initialized at task creation, so the initial task runs
as root (UID/GID 0) unless explicitly changed.
Inheritance
===========
When a new task is created, ``group_inherit_identity()`` in
``sched/group/group_create.c`` copies all six credential fields from the parent
task group to the child task group.
Privilege Transitions
=====================
``setuid()`` and ``setgid()``
-----------------------------
When the effective ID is zero (root):
* ``setuid(uid)`` sets ``tg_uid``, ``tg_euid``, and ``tg_suid`` to ``uid``.
* ``setgid(gid)`` sets ``tg_gid``, ``tg_egid``, and ``tg_sgid`` to ``gid``.
When the effective ID is non-zero:
* The caller may only set the effective ID to the current real or saved value.
* Any other value causes the function to return ``-1`` with ``errno`` set to
``EPERM``.
``seteuid()`` and ``setegid()``
-------------------------------
When the effective ID is zero, any value may be assigned as the new effective
ID.
When the effective ID is non-zero, the requested value must equal the real or
the saved ID. Otherwise the function returns ``-1`` with ``errno`` set to
``EPERM``.
This implements the standard POSIX pattern of temporarily dropping privileges
with ``seteuid()`` or ``setegid()`` and later restoring them to the saved value.
``setreuid()`` and ``setregid()``
---------------------------------
These functions set the real and/or effective IDs in a single call. When the
effective ID is zero, any requested real and effective values may be assigned
and the saved set-ID is updated accordingly. When the effective ID is
non-zero, each requested value must equal the current effective ID, saved
set-ID, or (for the effective argument only) the real ID; otherwise the call
returns ``-1`` with ``errno`` set to ``EPERM``. When the real ID is changed,
or the effective ID is changed to a value not equal to the real ID, the saved
set-ID is set to the new effective ID.
``getresuid()`` and ``getresgid()``
-----------------------------------
These functions return the real, effective, and saved set-IDs for the calling
task group. Any output pointer may be ``NULL`` if that ID is not needed.
Configuration
=============
``CONFIG_SCHED_USER_IDENTITY``
Enables per-task-group credential tracking. Without this option, stub
root-only versions of all credential interfaces are provided.
``CONFIG_FS_PERMISSION``
Enables filesystem ownership and permission enforcement. Requires
``CONFIG_SCHED_USER_IDENTITY``.
Pseudo-Filesystem Ownership
===========================
When ``CONFIG_PSEUDOFS_ATTRIBUTES`` and ``CONFIG_SCHED_USER_IDENTITY`` are both
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).