Skip to content

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

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

fs,sched: add chroot() filesystem jail#19900
Abhishekmishra2808 wants to merge 4 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

Comment thread Documentation/applications/nsh/commands.rst
Comment thread Documentation/implementation/chroot.rst Outdated
Comment thread Documentation/implementation/chroot.rst
Comment thread Documentation/implementation/chroot.rst Outdated
Comment thread Documentation/implementation/user_identity.rst Outdated
Comment thread fs/inode/fs_inodesearch.c
@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

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

s698pm-dkit

Comment thread include/nuttx/fs/fs.h Outdated
Comment thread sched/group/group_create.c
Comment thread sched/group/group_create.c Outdated
Comment thread fs/vfs/fs_chroot.c Outdated
Comment thread sched/group/group_create.c Outdated
Comment thread fs/vfs/fs_chroot.c Outdated
Comment thread fs/inode/fs_inodesearch.c Outdated
Comment thread include/nuttx/sched.h Outdated
Comment thread fs/vfs/fs_chroot.c Outdated
Comment thread fs/inode/fs_inodesearch.c Outdated
Store the jail as an absolute path on the task group, copy it to
children, and free it when the last member leaves.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
Add CONFIG_FS_CHROOT and POSIX chroot(). Store the jail as an
absolute path on the task group, and require euid 0 when user
identity is enabled.

Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
Prepend tg_root to absolute paths, normalize, and keep the result
under the jail, then walk from g_root_inode.

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 thread sched/group/group_create.c Outdated
Comment thread sched/group/group_create.c Outdated
@Abhishekmishra2808

Copy link
Copy Markdown
Contributor Author

@acassis PTAL !

@acassis

acassis commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Comment thread fs/vfs/fs_chroot.c

/* chroot("/") from the global root is a no-op (tg_root stays NULL). */

if (strcmp(abspath, "/") == 0)

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.

but caller may change to no root before

Comment thread fs/vfs/fs_chroot.c
return ERROR;
}

SETUP_SEARCH(&desc, path, false);

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.

why need search

Comment thread fs/vfs/fs_chroot.c
out[len] = '\0';
}

strlcat(out, relpath, outlen);

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.

strlcpy by len offset

Comment thread fs/inode/fs_inodesearch.c
in++;
}

seglen = (size_t)(in - seg);

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.

remove the cast

Comment thread fs/inode/fs_inodesearch.c
}
else
{
size_t used = (size_t)(dst - out);

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.

ditto

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.

3 participants