CHROOT(2)
โจ chroot(2), fchroot(2) โ change root directory โจ
okay bestie so this one's from the System Calls Manual, section 2, and the whole thing ships in the Standard C Library (libc, -lc). buckle up, we're moving the root of the filesystem today ๐
๐ธ NAME ๐ธ
chroot, fchroot โ change root directory
๐ LIBRARY ๐
Standard C Library (libc, -lc) โ she's built in, no extra credit needed ๐
๐ฆ SYNOPSIS ๐ฆ
#include <unistd.h>
int
chroot(const char *dirname);
int
fchroot(int fd);
โจ DESCRIPTION โจ
so dirname is the address of the pathname of a directory, and it's terminated by an ASCII NUL โ classic string behaviour, no notes ๐. The chroot() system call makes dirname become the root directory, like, the actual starting point for path searches of any pathname that begins with /. very main character energy for a directory ngl ๐
For a directory to become the root directory, a process must have execute (search) access on that directory. no search access, no root, periodt.
โ ๏ธ also lowkey important: chroot() has no effect on the process's current directory. she does not touch it. do not @ me.
This call is restricted to the super-user โ unless the security.bsd.unprivileged_chroot sysctl variable is set to 1 and the process has enabled the PROC_NO_NEW_PRIVS_CTL procctl(2). both. it's an and situation, bestie ๐ซถ
Depending on how kern.chroot_allow_open_directories is set, open file descriptors that reference directories will make chroot() fail like this:
- If
kern.chroot_allow_open_directoriesis set to zero,chroot()will always fail withEPERMif there are any directories open. any. at all. ๐ - If
kern.chroot_allow_open_directoriesis set to one โ and hey, that's the default โchroot()will fail withEPERMif there are any directories open and the process is already subject to thechroot()system call. - Any other value for
kern.chroot_allow_open_directorieswill bypass the check for open directories entirely, mimicking the historic insecure behavior ofchroot()that's still present on other systems. iykyk, that's the sketchy one ๐ฉ
The fchroot() system call is identical to chroot() except it takes a file descriptor instead of a path. same vibes, different argument โจ
๐ RETURN VALUES ๐
Upon successful completion, the value 0 is returned; otherwise the value -1 is returned and the global variable errno is set to indicate the error. zero = slay, negative one = check errno, that's the whole deal ๐
๐ฅ ERRORS ๐ฅ
The chroot() and fchroot() system calls will fail and the root directory will be unchanged if:
[EPERM]โ the effective user ID is not the super-user and thesecurity.bsd.unprivileged_chrootsysctl is0. sorry bestie, no root for you ๐[EPERM]โ the effective user ID is not the super-user and the process has not enabled thePROC_NO_NEW_PRIVS_CTLprocctl(2).[EPERM]โ one or more file descriptors are open directories and thekern.chroot_allow_open_directoriessysctl is not set to permit this.[EIO]โ an I/O error occurred while reading from or writing to the file system. ow ๐ญ[EINTEGRITY]โ corrupted data was detected while reading from the file system.
The chroot() system call will fail and the root directory will be unchanged if:
[ENOTDIR]โ a component of the path name is not a directory.[ENAMETOOLONG]โ a component of a pathname exceeded255characters, or an entire path name exceeded1023characters. that's a Lot of characters ๐[ENOENT]โ the named directory does not exist. she's not there, girl.[EACCES]โ search permission is denied for any component of the path name.[ELOOP]โ too many symbolic links were encountered in translating the pathname. symlink spiral, we've all been there ๐[EFAULT]โ thedirnameargument points outside the process's allocated address space.
The fchroot() system call will fail and the root directory will be unchanged if:
[EACCES]โ search permission is denied for the directory referenced by the file descriptor.[EBADF]โ the argumentfdis not a valid file descriptor.[ENOTDIR]โ the file descriptor does not reference a directory.
๐ซถ SEE ALSO ๐ซถ
like yeah go read those too, they're literally the neighbours ๐
๐ HISTORY ๐
The chroot() system call appeared in Version 7 AT&T UNIX โ ancient. iconic. she's been here a minute ๐ฐ๏ธ. It was marked as โlegacyโ in Version 2 of the Single UNIX Specification (โSUSv2โ), and was removed in subsequent standards. rip bozo-ish behaviour, but she's still here ๐. The fchroot() system call first appeared in FreeBSD 15.0. fresh out the box โจ
๐ BUGS ๐
okay so this is a weird one: if the process is able to change its working directory to the target directory, but another access control check fails โ like a check for open directories, or a MAC check โ it is possible that this system call may return an error, with the working directory of the process left changed. so you get a fail and a side effect. rude. ๐
๐ SECURITY CONSIDERATIONS ๐
The system has many hardcoded paths to files which it may load after the process starts. so like, it is generally recommended to drop privileges immediately after a successful chroot call, and to restrict write access to a limited subtree of the chroot root. for instance, set up the sandbox so the sandboxed user will have no write access to any well-known system directories. please. for me. ๐ฅบ
For complete isolation from the rest of the system, use jail(2) instead. that's the actual final form, no cap ๐
๐ that's the whole page bestie, go forth and chroot responsibly ๐
and this little beauty comes to you via Debian, dated April 27, 2026 โ mwah, take care of her ๐๐ฆ๐
๐ฆ where this page comes from
- freebsd 15.1: base 15.1
- Copyright (c) 1983, 1991, 1993 The Regents of the University of California. All rights reserved
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms