Skip to content

fs,sched: add chroot() filesystem jail - #19900

Open
Abhishekmishra2808 wants to merge 5 commits into
apache:masterfrom
Abhishekmishra2808:feature/fs-chroot
Open

fs,sched: add chroot() filesystem jail#19900
Abhishekmishra2808 wants to merge 5 commits into
apache:masterfrom
Abhishekmishra2808:feature/fs-chroot

Conversation

@Abhishekmishra2808

@Abhishekmishra2808 Abhishekmishra2808 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

CONFIG_FS_CHROOT adds POSIX chroot() so a task group can pin a directory as its filesystem root. Absolute lookups start at that inode, children inherit the jail, and PWD is rewritten so relative paths cannot walk out. This is a filesystem jail, not a container: descriptors opened before chroot() that already point outside the tree remain usable.

Impact

The option is off by default. When enabled, chroot() is a new syscall and, with SCHED_USER_IDENTITY, requires effective UID 0. On CONFIG_BUILD_FLAT the euid == 0 gate and tg_root share the same trust boundary as credentials. Companion apps change: apache/nuttx-apps#3735.

Testing

Host: WSL2 x86_64. Board: sim (CONFIG_FS_CHROOT=y). Companion apps PR: apache/nuttx-apps#3735.

$ ./tools/checkpatch.sh -f fs/inode/fs_inodesearch.c fs/vfs/fs_chroot.c \
    include/nuttx/sched.h include/unistd.h sched/group/group_create.c \
    sched/group/group_leave.c include/nuttx/fs/fs.h syscall/syscall.csv \
    fs/Kconfig fs/vfs/Make.defs fs/vfs/CMakeLists.txt \
    Documentation/implementation/chroot.rst \
    Documentation/implementation/user_identity.rst \
    Documentation/applications/nsh/commands.rst
✔️ All checks pass.
$ cd Documentation && make html
build succeeded.

The HTML pages are in _build/html.

NSH no-command form (syscall from userspace; chroot builtin is in apache/nuttx-apps#3735):

login: root
User Logged-in!
nsh> mkdir /tmp/jail
nsh> echo hello > /tmp/jail/marker
nsh> echo secret > /tmp/secret
nsh> chroot /tmp/jail
nsh> pwd
/
nsh> cat /marker
hello
nsh> ls /dev
nsh: ls: stat failed: 2
nsh> cat /tmp/secret
nsh: cat: open failed: 2

ostest (kernel jail, leftover fd, inheritance):

nsh> ostest
...
user_main: chroot test
chroot_test: Starting test
chroot_test: /marker is visible inside the jail
chroot_test: host paths are not visible inside the jail
chroot_test: pre-opened host fd still usable after chroot
chroot_test: grandchild still sees the jail
chroot_test: PASSED

chroot() holds a directory inode in the task group, so sched needs the
existing refcount helpers instead of duplicating them.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
Store tg_root / tg_rootrel on the task group, copy them to children,
and drop the inode when the last member leaves.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
Add CONFIG_FS_CHROOT and POSIX chroot(). Pin a directory as the group
root, rewrite PWD, and require euid 0 when user identity is enabled.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
Walk from tg_root instead of the global pseudo-root, clamp ".." at the
jail, and normalize absolute paths so chroot(".") under a mount does
not pass a leftover "." as relpath.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
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 <mishra.abhishek2808@gmail.com>
Comment on lines +251 to +252
nsh> pwd
/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Abhishekmishra2808 add here after pwd the "nsh> ls /" to show that there is not /dev, /proc available.

Comment on lines +12 to +14
This is **not** a container. NuttX does not provide PID, mount, or
network namespaces. ``chroot()`` only changes where pathname lookup
begins.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of saying "NuttX does not provide PID, mount, or network namespaces" that some people will take as true (and of course NuttX has it), I suggest adding:
Limitations: currently chroot doesn't support PID, mount, network namespaces and explain the next start as a TODO. What need to be done to support it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct !

.. _chroot:

======
chroot

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this "implementation" is misleading: you didn't explain how it was implemented, what was necessary, why did you spend an week implementing it to explain what was the difficult part of the implementation

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw other examples. Agreed on this point !!

============

Bind-mounts or unionfs to populate ``/dev`` inside a jail, mount/PID/
network namespaces, and ``pivot_root()`` are not provided.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain the challenges here, why wasn't it implemented?

Flat Build Trust Boundary
=========================

This credential model is a DAC layer for cooperating tasks, not a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is DAC? Digital Analog Converter? Please explain what is DAC in this context

Comment thread fs/inode/fs_inodesearch.c
* (tmpfs /tmp) the leftover "." is passed to the filesystem as
* relpath and fails with ENOENT.
*
****************************************************************************/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please include the Input parameters and the return

@acassis

acassis commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Nice work @Abhishekmishra2808 !
@xiaoxiang781216 @raiden00pl maybe we could use it to create separated jails/arenas to use with telnet / ssh to avoid user to damage the original root filesystems. But I think in this case we need to be able to mount a limited /dev, /proc, etc

@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Documentation Improvements or additions to documentation Size: L The size of the change in this PR is large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants