Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

chroot(2)

FieldValue
Numbers (x64 / i386 / arm64-generic / arm32)x64 161 / i386 61 / arm64-generic 51 / arm32 61
Since (kernel)1.0 (hub)
Man pageman2/chroot.2 (local cache, dated 2021-03-22)
glibc wrapperYes; chroot() in <unistd.h>; glibc gates (since 2.2.2): _XOPEN_SOURCE && !(_POSIX_C_SOURCE >= 200112L) or _DEFAULT_SOURCE (glibc >= 2.20) or _BSD_SOURCE (glibc <= 2.19)
Aliases coverednone (post-6.17-era fchroot, x64/generic 472, is a separate hub row, not covered here)
Ledger IDSC-chroot

Purpose

chroot() changes the root directory of the calling process to path. Pathnames beginning with / are then resolved from that directory, and the new root is inherited by all children. The man page is explicit that this call “changes an ingredient in the pathname resolution process and does nothing else”: it is not a security mechanism, not a sandbox, and does not restrict filesystem system calls. For a real root swap, including switching the mount, use pivot_root.md.

Synopsis

#include <unistd.h>
int chroot(const char *path);

Arguments and behavior

ArgumentMeaning
pathDirectory that becomes the new root for /-prefixed lookups

The call does not change the current working directory, so after the call . can lie outside the tree rooted at the new /; the man page gives the classic escape mkdir foo; chroot foo; cd ... It also does not close open file descriptors, which keep working and may point outside the chroot tree. Another documented escape: chdir(2) into a directory that is later moved out of the chroot, then open a relative path such as ../../../etc/passwd; the man page warns that daemons accepting a “chroot directory” parameter must ensure directories are never moved out of it.

Return value and errors

Returns 0 on success, -1 on error with errno set. Errors per the man page: EACCES (search permission denied on a path prefix component), EFAULT, EIO, ELOOP, ENAMETOOLONG, ENOENT, ENOMEM, ENOTDIR, and EPERM (caller has insufficient privilege).

Security and notes

Only a privileged process may call chroot(): Linux requires the CAP_SYS_CHROOT capability in the caller’s user namespace (man page; kernel fs/open.c SYSCALL_DEFINE1(chroot) enforces ns_capable(current_user_ns(), CAP_SYS_CHROOT) – fetched master copy, source-cache/fetched/master-fs-open.c line 607). Because unprivileged users can create user namespaces, CAP_SYS_CHROOT in a non-initial user namespace is attainable, which is why the man page’s “not a sandbox” warning matters. Children inherit the root via fork(2) and keep it across execve(2). The /proc/[pid]/root magic link exposes a process’s root directory (proc(5)). FreeBSD offers the stronger jail(). Related calls in this directory: chdir.md, pivot_root.md, and the hub rows for fchroot (472, post-6.17 era) in overview.md.

References

  • Cached man page: source-cache/man-pages-sparse/man2/chroot.2
  • Online: https://man7.org/linux/man-pages/man2/chroot.2.html
  • Kernel source: fs/open.c (torvalds/linux master, source-cache/fetched/master-fs-open.c)
  • Conformance per man page: SVr4, 4.4BSD, SUSv2 (marked LEGACY); not in POSIX.1-2001