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

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

commit 4b86c1dd230d10da79b716152827502dd285ca40
Author: Abhishek Mishra <[email protected]>
AuthorDate: Wed Aug 19 08:07:17 2026 +0000

    docs: document chroot jail root
    
    Describe the jail, leftover pre-opened fds, the NSH command-form scrub,
    and the flat-build trust boundary shared with credentials.
    
    Signed-off-by: Abhishek Mishra <[email protected]>
---
 Documentation/applications/nsh/commands.rst    |  46 +++++
 Documentation/applications/nsh/config.rst      |   1 +
 Documentation/implementation/chroot.rst        | 252 +++++++++++++++++++++++++
 Documentation/implementation/index.rst         |   1 +
 Documentation/implementation/user_identity.rst |  22 ++-
 Documentation/reference/user/10_filesystem.rst |   3 +
 Documentation/standards/posix.rst              |   5 +
 fs/mount/fs_automount.c                        | 158 ++++++++--------
 8 files changed, 408 insertions(+), 80 deletions(-)

diff --git a/Documentation/applications/nsh/commands.rst 
b/Documentation/applications/nsh/commands.rst
index d1477e958df..c1e79508a89 100644
--- a/Documentation/applications/nsh/commands.rst
+++ b/Documentation/applications/nsh/commands.rst
@@ -215,6 +215,52 @@ Also sets the previous working directory environment 
variable
 ``cd ..``              sets the current working directory to the parent 
directory.
 ==================  =====================================
 
+.. _cmdchroot:
+
+``chroot`` Change Root Directory
+================================
+
+**Command Syntax**::
+
+  chroot <newroot> [<command> [args...]]
+
+**Synopsis**. Change the filesystem root of the current task group so
+absolute path lookups start at ``<newroot>``. Requires
+``CONFIG_FS_CHROOT``. This is a filesystem jail, not a container.
+
+The command performs ``chdir(newroot)``, ``chroot(".")``, then
+``chdir("/")``. With no extra arguments the current NSH session stays
+jailed (``pwd`` shows ``/``). An optional command is executed with
+``execvp()`` after the jail is in place.
+
+When ``CONFIG_SCHED_USER_IDENTITY`` is enabled, ``chroot()`` requires
+effective UID 0. Drop extra privilege after jailing so a later
+``chroot()`` cannot be used to escape.
+
+File descriptors opened before ``chroot()`` are not retroactively
+contained. The ``chroot <newroot> <command>`` form closes non-stdio
+descriptors that are not already ``O_CLOEXEC`` before ``execvp()``.
+The no-command form leaves the current session's existing descriptors
+usable, including any that point outside the jail.
+
+**Example**::
+
+  nsh> mkdir /tmp/jail
+  nsh> echo hello > /tmp/jail/marker
+  nsh> chroot /tmp/jail
+  nsh> pwd
+  /
+  nsh> ls /
+  /:
+   marker
+  nsh> cat /marker
+  hello
+
+Note that ``ls /`` only lists ``marker``: ``/dev`` and ``/proc`` are not
+visible inside the jail because they were never created under
+``/tmp/jail``. ``chroot()`` does not bind-mount or otherwise populate
+these pseudo-filesystems into the new root; see :ref:`chroot`.
+
 .. _cmdchmod:
 
 ``chmod`` Change File Permissions
diff --git a/Documentation/applications/nsh/config.rst 
b/Documentation/applications/nsh/config.rst
index 19b92ebfe03..31816b97981 100644
--- a/Documentation/applications/nsh/config.rst
+++ b/Documentation/applications/nsh/config.rst
@@ -40,6 +40,7 @@ Command                Depends on Configuration               
     Can Be Disabl
                        ! ``CONFIG_NSH_DISABLE_LOOPS``  
 :ref:`cmdcat`          ``CONFIG_NSH_DISABLE_CAT``                  .
 :ref:`cmdcd`           ! ``CONFIG_DISABLE_ENVIRON``                
``CONFIG_NSH_DISABLE_CD``
+:ref:`cmdchroot`       ``CONFIG_FS_CHROOT``                        
``CONFIG_NSH_DISABLE_CHROOT``
 :ref:`cmdcmp`          ``CONFIG_NSH_DISABLE_CMP``                  .
 :ref:`cmdcp`           ``CONFIG_NSH_DISABLE_CP``                   .
 :ref:`cmddate`         ``CONFIG_NSH_DISABLE_DATE``                 .
diff --git a/Documentation/implementation/chroot.rst 
b/Documentation/implementation/chroot.rst
new file mode 100644
index 00000000000..8a06eeb1013
--- /dev/null
+++ b/Documentation/implementation/chroot.rst
@@ -0,0 +1,252 @@
+.. _chroot:
+
+======
+chroot
+======
+
+``chroot()`` is a kernel-enforced filesystem jail.  When
+``CONFIG_FS_CHROOT`` is enabled, each task group may pin a directory as
+its root.  Absolute path lookup starts there, so the group cannot see
+files outside that tree.
+
+Limitations: this is **not** a container.  The current implementation
+only changes where pathname lookup begins; it does not provide PID,
+mount, or network namespaces, and it does not populate the new root
+with ``/dev`` or ``/proc``.  See `TODO`_ for what each of these would
+require.
+
+Design and implementation
+==========================
+
+The Kconfig option and the syscall are the easy part; ``chroot()`` on
+NuttX has no MMU-backed process isolation to lean on, so the whole
+feature has to be built on top of the single, global pseudo-filesystem
+inode tree that every task already shares. This section walks through
+why that made the implementation harder than it looks, in the order
+the pieces had to be worked out.
+
+Where does the jail live?
+--------------------------
+
+The first question is what a "jail" even is in a system with one
+shared filesystem tree: it cannot be a separate tree, so it has to be
+a *starting point* that path lookups are not allowed to walk above.
+That starting point needs to be remembered somewhere per-caller, and
+it needs to survive ``fork()``-style child creation the same way an
+open file table or a working directory does.
+
+NuttX already keeps exactly that kind of shared, inheritable state on
+the task group (``struct task_group_s``), not on the individual task,
+because every thread in a task group is supposed to see the same
+filesystem view. The jail is stored as a single absolute path::
+
+  struct task_group_s
+  {
+    ...
+  #ifdef CONFIG_FS_CHROOT
+    FAR char *tg_root;     /* Absolute jail path, or NULL */
+  #endif
+  };
+
+A path is used instead of a cached inode so a later unmount/remount
+at that location is picked up on the next lookup.  ``tg_root`` is
+``NULL`` when the group has not called ``chroot()``.
+
+``group_inherit_chroot()`` (``sched/group/group_create.c``) copies the
+string to child task groups (kernel threads are skipped):
+
+.. code-block:: c
+
+  if (rgroup->tg_root == NULL)
+    {
+      return OK;
+    }
+
+  group->tg_root = strdup(rgroup->tg_root);
+  if (group->tg_root == NULL)
+    {
+      return -ENOMEM;
+    }
+
+That is what makes a jail apply to a whole subtree of children, not
+just the one task that called ``chroot()``.
+
+How lookups stay inside the jail
+---------------------------------
+
+Every absolute path goes through ``inode_search_setup()`` and then
+the original walk from ``g_root_inode``:
+
+1. Prepend ``tg_root`` to the incoming path (``/tmp/jail`` + ``/foo``
+   becomes ``/tmp/jail/foo``).
+2. Canonicalize the combined string with ``_inode_canonicalize()``:
+   drop empty and ``.`` segments and collapse ``..``.  The jail prefix
+   is the floor for that walk, so ``..`` cannot pop above ``tg_root``.
+3. ``/../etc`` inside the jail therefore becomes ``/tmp/jail/etc``,
+   not host ``/etc``.
+4. Continue the original inode-tree walk on that host path.
+
+Without a jail the same canonicalize step still runs, so
+``chroot(".")`` under a mount (``$PWD/.``) does not pass a leftover
+``.`` to the filesystem as ``relpath``.
+
+There is no separate jailed walk, and no extra ``..`` handling inside
+the tree traversal.
+
+Why ``chroot()`` does not touch ``PWD``
+-----------------------------------------
+
+Relative lookups go through ``inode_search()``, which prepends
+``$PWD`` to the path and then calls the exact same absolute-path
+logic described above. That raises an obvious question: what happens
+to a task's current directory when its whole notion of "root" just
+moved?
+
+An earlier version of this change rewrote ``PWD`` inside ``chroot()``
+itself to keep it consistent with the new jail. That turned out to be
+both the wrong layer and unnecessary:
+
+* ``chroot()`` is a filesystem primitive; ``PWD`` is environ state.
+  POSIX ``chroot()`` does not touch the current directory either --
+  the well-known Unix idiom is that the *caller* must ``chdir()``
+  immediately after ``chroot()``, precisely so that no stale
+  reference to the old tree is left lying around.
+* It is not needed for containment. A stale ``PWD`` used in a
+  relative lookup after ``chroot()`` is still rewritten by
+  ``inode_search_setup()`` (prepend the jail path, canonicalize, clamp
+  ``..``) before the tree walk. The lookup can fail or land on a
+  path inside the jail that was not intended, but it cannot resolve
+  to a node outside the jail.
+
+So ``chroot()`` leaves ``PWD`` alone, and the caller is responsible
+for calling ``chdir()`` afterward if a sane current directory inside
+the jail is needed -- exactly as the NSH ``chroot`` command already
+does with its trailing ``chdir("/")`` (see `NSH`_ below), which sets
+``PWD`` correctly via the ordinary ``chdir()`` path, with no special
+jail-aware logic required.
+
+Why the privilege gate lives in ``chroot()`` itself
+-----------------------------------------------------
+
+The last design question was who is allowed to call ``chroot()`` at
+all. When ``CONFIG_SCHED_USER_IDENTITY`` is enabled, the syscall
+checks ``tg_euid`` directly and returns ``EPERM`` for anything but
+effective UID 0::
+
+  #ifdef CONFIG_SCHED_USER_IDENTITY
+    if (group->tg_euid != 0)
+      {
+        set_errno(EPERM);
+        return ERROR;
+      }
+  #endif
+
+This is intentionally the same *class* of check as the credential DAC
+checks described in :ref:`user-identity`, and it inherits the same
+caveat: on ``CONFIG_BUILD_FLAT``, kernel and application code share
+one address space, so this is a userspace-visible gate rather than a
+hardware-enforced boundary -- other code in that address space can
+write ``tg_euid`` or ``tg_root`` directly. Protected and kernel builds
+close that gap by enforcing the check at the syscall boundary, which
+untrusted code cannot bypass. Without ``CONFIG_SCHED_USER_IDENTITY``
+at all, every task is effectively root, so ``chroot()`` stays
+available to everyone and is a pure path-containment mechanism with no
+privilege check gating it.
+
+Configuration
+=============
+
+Enable ``CONFIG_FS_CHROOT`` in the filesystem configuration.  The
+syscall is then available from ``unistd.h``.
+
+Semantics
+=========
+
+* ``chroot(path)`` resolves ``path`` relative to the caller's current
+  root (so a nested ``chroot()`` cannot walk back to the host tree).
+* ``path`` must name a directory (``ENOTDIR`` otherwise).
+* ``chroot("/")`` resolves to the host root and clears the jail
+  (``tg_root = NULL``).  From inside a jail, ``/`` is the jail root, so
+  it cannot be used to escape.
+* The jail is stored on the task group as the absolute path ``tg_root``.
+  Child tasks inherit it.  Kernel threads do not.
+* ``chroot()`` does not modify ``PWD`` or any other environ state; the
+  caller is responsible for calling ``chdir()`` afterward if a
+  specific current directory inside the jail is needed.  See
+  `Why chroot() does not touch PWD`_.
+
+NSH
+===
+
+The NSH ``chroot`` command performs the usual Unix dance::
+
+  chdir(newroot);
+  chroot(".");
+  chdir("/");
+
+With no extra arguments the current NSH session stays jailed (``pwd``
+shows ``/``, ``ls /`` lists the jail tree) because of the trailing
+``chdir("/")`` in the sequence above, not because ``chroot()`` itself
+touches ``PWD``.  An optional command is executed with ``execvp()``
+after the jail is in place; NSH closes non-stdio, non-``O_CLOEXEC``
+descriptors first (see below).
+
+When ``CONFIG_SCHED_USER_IDENTITY`` is enabled, drop extra privilege
+after the jail is in place (for example ``setuid()`` to a non-root
+user) so a later ``chroot()`` cannot be used to escape.
+
+Open file descriptors
+=====================
+
+File descriptors opened before ``chroot()`` are not retroactively
+contained.  POSIX allows this; NuttX does not close them.  A jailed
+task that inherits a host descriptor can read and write that file
+without going through pathname lookup, so the jail does not apply.
+This is the most common way ``chroot()`` is misused as a security
+tool.  Do not treat it as a sandbox against a process that already
+holds host file descriptors.
+
+The NSH ``chroot <newroot> <command>`` form closes every open
+descriptor above stderr that is not already marked ``O_CLOEXEC``
+before ``execvp()``.  Stdio (fds 0--2) is left intact.  The
+no-command form leaves the current NSH session jailed with its
+existing descriptors, including any that point outside the tree.
+
+TODO
+====
+
+The following are deliberately out of scope for this initial
+implementation, and are listed with what each would require, since
+that scoping was itself a large part of the design work:
+
+* **Populating ``/dev``, ``/proc``, etc. inside the jail.**  Nothing
+  bind-mounts or otherwise recreates these pseudo-filesystems under
+  the new root, so a jailed task cannot open devices or read process
+  info unless the jail directory tree already contains them.  Adding
+  this needs either a bind-mount primitive (mount an existing inode
+  subtree at a second path) or a per-jail selective mount step run at
+  ``chroot()`` time; neither existed in the VFS before this change,
+  and both are a materially larger change than pathname jailing.
+  This is the specific gap raised for using ``chroot()`` to sandbox
+  remote logins (telnet/ssh): without a minimal ``/dev``, a jailed
+  shell cannot even do much I/O.
+* **PID namespaces.**  NuttX has one flat, global task/PID table.
+  Isolating it per jail would mean making scheduler and IPC lookups
+  (``kill()``, ``/proc``-style listings, signal delivery) aware of a
+  namespace boundary, which touches the scheduler core, not just the
+  VFS. This implementation does not attempt that.
+* **Mount namespaces.**  The mount table (``g_root_inode`` and its
+  mounted filesystems) is process-global. A jailed task group can be
+  confined to a subtree of the existing mount table, but it cannot
+  have a private view where mounts made outside the jail are hidden,
+  or where the jailed task can mount/unmount without affecting the
+  rest of the system.  That requires per-task-group mount tables.
+* **Network namespaces.**  Sockets and network interfaces are global
+  to the OS instance; nothing in this change touches the network
+  stack.
+* **``pivot_root()``.**  Swapping the process root while keeping the
+  old root reachable is not implemented; ``chroot()`` only changes
+  where lookups begin.
+
+None of these are ruled out architecturally -- they are simply not
+part of this change, which is scoped to pathname-lookup containment.
diff --git a/Documentation/implementation/index.rst 
b/Documentation/implementation/index.rst
index 4d53b205c6d..a0d71ddb152 100644
--- a/Documentation/implementation/index.rst
+++ b/Documentation/implementation/index.rst
@@ -9,6 +9,7 @@ Implementation Details
    bottomhalf_interrupt.rst
    cancellation_points.rst
    chip_h.rst
+   chroot.rst
    context_switches.rst
    crc.rst
    critical_sections.rst
diff --git a/Documentation/implementation/user_identity.rst 
b/Documentation/implementation/user_identity.rst
index ffb08aee3b5..9f621c80e8a 100644
--- a/Documentation/implementation/user_identity.rst
+++ b/Documentation/implementation/user_identity.rst
@@ -40,7 +40,10 @@ When ``CONFIG_SCHED_NGROUPS`` is greater than zero:
   with ``setgroups()``.
 * ``NGROUPS_MAX`` equals ``CONFIG_SCHED_NGROUPS``.
 
-Filesystem DAC (``fs_checkmode()``) grants the group-class mode bits when the
+Filesystem DAC (Discretionary Access Control -- ownership- and
+mode-bit-based permission checks, as opposed to a mandatory policy
+enforced independently of the file owner) is implemented by
+``fs_checkmode()``, which grants the group-class mode bits when the
 file's group matches ``tg_egid`` **or** any entry in ``tg_groups``.
 
 Inheritance
@@ -152,6 +155,23 @@ Configuration
   See :ref:`file-permission` for the VFS helpers, mount-crossing
   traverse rules, and testing notes.
 
+Flat Build Trust Boundary
+=========================
+
+This credential model is a DAC (Discretionary Access Control) layer for
+cooperating tasks, not a process-isolation boundary.  DAC here means
+permission checks based on ownership and mode bits that the owner can
+change (``chmod()``/``chown()``), rather than a mandatory policy
+enforced independently of the object owner.  On ``CONFIG_BUILD_FLAT``,
+kernel and
+application share one address space, so other code can write
+``tg_euid`` / ``tg_egid`` (and other fields in ``task_group_s``)
+directly and bypass the syscall checks.  Protected and kernel builds
+enforce the boundary via the syscall interface.
+
+The same caveat applies to ``chroot()``'s ``euid == 0`` gate and
+``tg_root``; see :ref:`chroot`.
+
 Pseudo-Filesystem Ownership
 ===========================
 
diff --git a/Documentation/reference/user/10_filesystem.rst 
b/Documentation/reference/user/10_filesystem.rst
index 695c1e0db30..4e1aef5419e 100644
--- a/Documentation/reference/user/10_filesystem.rst
+++ b/Documentation/reference/user/10_filesystem.rst
@@ -219,6 +219,9 @@ UNIX Standard Operations (``unistd.h``)
   /* Working directory operations */
 
   int     chdir(FAR const char *path);
+  #ifdef CONFIG_FS_CHROOT
+  int     chroot(FAR const char *path);
+  #endif
   FAR char *getcwd(FAR char *buf, size_t size);
 
   /* File path operations */
diff --git a/Documentation/standards/posix.rst 
b/Documentation/standards/posix.rst
index 5333f6f11e7..e435248d746 100644
--- a/Documentation/standards/posix.rst
+++ b/Documentation/standards/posix.rst
@@ -1325,6 +1325,9 @@ POSIX_FILE_SYSTEM
 
 File System:
 
+``chroot()`` is supported when ``CONFIG_FS_CHROOT`` is enabled.  See
+:ref:`chroot`.
+
 +--------------------------------+---------+
 | API                            | Support |
 +================================+=========+
@@ -1332,6 +1335,8 @@ File System:
 +--------------------------------+---------+
 | :c:func:`chdir`                | Yes     |
 +--------------------------------+---------+
+| :c:func:`chroot`               | Yes     |
++--------------------------------+---------+
 | :c:func:`closedir`             | Yes     |
 +--------------------------------+---------+
 | :c:func:`creat`                | Yes     |
diff --git a/fs/mount/fs_automount.c b/fs/mount/fs_automount.c
index 1afc7ac46ab..a4ecef5e8f6 100644
--- a/fs/mount/fs_automount.c
+++ b/fs/mount/fs_automount.c
@@ -476,56 +476,56 @@ static void automount_mount(FAR struct 
automounter_state_s *priv)
   ret = automount_findinode(lower->mountpoint);
   switch (ret)
     {
-    case OK_EXIST:
+      case OK_EXIST:
 
-      /* REVISIT: What should we do in this case?  I think that this would
-       * happen only if a previous unmount failed?  I suppose that we should
-       * try to unmount again because the mount might be stale.
-       */
+        /* REVISIT: What should we do in this case?  I think that this would
+         * happen only if a previous unmount failed?  I suppose that we
+         * should try to unmount again because the mount might be stale.
+         */
 
-      fwarn("WARNING: Mountpoint %s already exists\n", lower->mountpoint);
-      ret = automount_unmount(priv);
-      if (ret < 0)
-        {
-          /* We failed to unmount (again?).  Complain and abort. */
+        fwarn("WARNING: Mountpoint %s already exists\n", lower->mountpoint);
+        ret = automount_unmount(priv);
+        if (ret < 0)
+          {
+            /* We failed to unmount (again?).  Complain and abort. */
 
-          ferr("ERROR: automount_unmount failed: %d\n", ret);
-          return;
-        }
+            ferr("ERROR: automount_unmount failed: %d\n", ret);
+            return;
+          }
 
-      /* We successfully unmounted the file system.  Fall through to
-       * mount it again.
-       */
+        /* We successfully unmounted the file system.  Fall through to
+         * mount it again.
+         */
 
-    case OK_NOENT:
+      case OK_NOENT:
 
-      /* If we get here, then the volume must not be mounted */
+        /* If we get here, then the volume must not be mounted */
 
-      DEBUGASSERT(!priv->mounted);
+        DEBUGASSERT(!priv->mounted);
 
-       /* Mount the file system */
+        /* Mount the file system */
 
-      ret = nx_mount(lower->blockdev, lower->mountpoint, lower->fstype,
-                     0, NULL);
-      if (ret < 0)
-        {
-          ferr("ERROR: Mount failed: %d\n", ret);
-          return;
-        }
+        ret = nx_mount(lower->blockdev, lower->mountpoint, lower->fstype,
+                       0, NULL);
+        if (ret < 0)
+          {
+            ferr("ERROR: Mount failed: %d\n", ret);
+            return;
+          }
 
-      /* Indicate that the volume is mounted */
+        /* Indicate that the volume is mounted */
 
-      priv->mounted = true;
+        priv->mounted = true;
 
 #ifdef CONFIG_FS_AUTOMOUNTER_DRIVER
-      automount_notify(priv);
+        automount_notify(priv);
 #endif /* CONFIG_FS_AUTOMOUNTER_DRIVER */
 
-      break;
+        break;
 
-    default:
-      ferr("ERROR: automount_findinode failed: %d\n", ret);
-      break;
+      default:
+        ferr("ERROR: automount_findinode failed: %d\n", ret);
+        break;
     }
 }
 
@@ -556,69 +556,69 @@ static int automount_unmount(FAR struct 
automounter_state_s *priv)
   ret = automount_findinode(lower->mountpoint);
   switch (ret)
     {
-    case OK_EXIST:
+      case OK_EXIST:
 
-      /* If we get here, then the volume must be mounted */
+        /* If we get here, then the volume must be mounted */
 
-      DEBUGASSERT(priv->mounted);
+        DEBUGASSERT(priv->mounted);
 
-      /* Un-mount the volume */
+        /* Un-mount the volume */
 
-      ret = nx_umount2(lower->mountpoint, MNT_FORCE);
-      if (ret < 0)
-        {
-          /* We expect the error to be EBUSY meaning that the volume could
-           * not be unmounted because there are currently reference via open
-           * files or directories.
-           */
+        ret = nx_umount2(lower->mountpoint, MNT_FORCE);
+        if (ret < 0)
+          {
+            /* We expect the error to be EBUSY meaning that the volume could
+             * not be unmounted because there are currently reference via
+             * open files or directories.
+             */
 
-          if (ret == -EBUSY)
-            {
-              finfo("WARNING: Volume is busy, try again later\n");
+            if (ret == -EBUSY)
+              {
+                finfo("WARNING: Volume is busy, try again later\n");
 
-              /* Start a timer to retry the umount2 after a delay */
+                /* Start a timer to retry the umount2 after a delay */
 
-              ret = wd_start(&priv->wdog, lower->udelay,
-                             automount_timeout, (wdparm_t)priv);
-              if (ret < 0)
-                {
-                  ferr("ERROR: wd_start failed: %d\n", ret);
-                  return ret;
-                }
-            }
+                ret = wd_start(&priv->wdog, lower->udelay,
+                               automount_timeout, (wdparm_t)priv);
+                if (ret < 0)
+                  {
+                    ferr("ERROR: wd_start failed: %d\n", ret);
+                    return ret;
+                  }
+              }
 
-          /* Other errors are fatal */
+            /* Other errors are fatal */
 
-          else
-            {
-              ferr("ERROR: umount2 failed: %d\n", ret);
-              return ret;
-            }
-        }
+            else
+              {
+                ferr("ERROR: umount2 failed: %d\n", ret);
+                return ret;
+              }
+          }
 
-      /* Fall through */
+        /* Fall through */
 
-    case OK_NOENT:
+      case OK_NOENT:
 
-      /* The mountpoint is not present.  This is normal behavior in the
-       * case where the user manually un-mounted the volume before removing
-       * media.  Nice job, Mr. user.
-       */
+        /* The mountpoint is not present.  This is normal behavior in the
+         * case where the user manually un-mounted the volume before removing
+         * media.  Nice job, Mr. user.
+         */
 
-      if (priv->mounted)
-        {
-          priv->mounted = false;
+        if (priv->mounted)
+          {
+            priv->mounted = false;
 
 #ifdef CONFIG_FS_AUTOMOUNTER_DRIVER
-          automount_notify(priv);
+            automount_notify(priv);
 #endif /* CONFIG_FS_AUTOMOUNTER_DRIVER */
-        }
+          }
 
-      return OK;
+        return OK;
 
-    default:
-      ferr("ERROR: automount_findinode failed: %d\n", ret);
-      return ret;
+      default:
+        ferr("ERROR: automount_findinode failed: %d\n", ret);
+        return ret;
     }
 }
 

Reply via email to