---
name: "chroot"
section: "2"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["linux", "freebsd", "macos"]
url: "https://new.carta.tech/chroot/2"
---

# chroot(2)

change root directory

## NAME

**chroot**, **fchroot** – change root directory

## LIBRARY

Standard C Library (libc, -lc)

## SYNOPSIS

**#include \<unistd.h\>**

*int*\

**chroot**(*const char \*dirname*);

*int*\

**fchroot**(*int fd*);

## DESCRIPTION

The *dirname* argument is the address of the pathname of a directory, terminated by an ASCII NUL. The **chroot**() system call causes *dirname* to become the root directory, that is, the starting point for path searches of pathnames beginning with ‘/’.

In order for a directory to become the root directory a process must have execute (search) access for that directory.

It should be noted that **chroot**() has no effect on the process's current directory.

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)](/procctl/2.md).

Depending on the setting of the ‘kern.chroot\_allow\_open\_directories’ sysctl variable, open file descriptors which reference directories will make the **chroot**() fail as follows:

If ‘kern.chroot\_allow\_open\_directories’ is set to zero, **chroot**() will always fail with EPERM if there are any directories open.

If ‘kern.chroot\_allow\_open\_directories’ is set to one (the default), **chroot**() will fail with EPERM if there are any directories open and the process is already subject to the **chroot**() system call.

Any other value for ‘kern.chroot\_allow\_open\_directories’ will bypass the check for open directories, mimicking the historic insecure behavior of **chroot**() still present on other systems.

The **fchroot**() system call is identical to **chroot**() except it takes a file descriptor instead of path.

## RETURN VALUES

The **chroot()** function returns the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.

## 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 the ‘*security.bsd.unprivileged\_chroot*’ sysctl is 0.

- \[EPERM\]

  The effective user ID is not the super-user and the process has not enabled the PROC\_NO\_NEW\_PRIVS\_CTL [procctl(2)](/procctl/2.md).

- \[EPERM\]

  One or more file descriptors are open directories and the ‘*kern.chroot\_allow\_open\_directories*’ sysctl is not set to permit this.

- \[EIO\]

  An I/O error occurred while reading from or writing to the file system.

- \[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 exceeded 255 characters, or an entire path name exceeded 1023 characters.

- \[ENOENT\]

  The named directory does not exist.

- \[EACCES\]

  Search permission is denied for any component of the path name.

- \[ELOOP\]

  Too many symbolic links were encountered in translating the pathname.

- \[EFAULT\]

  The *dirname* argument 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 argument *fd* is not a valid file descriptor.

- \[ENOTDIR\]

  The file descriptor does not reference a directory.

## SEE ALSO

[chdir(2)](/chdir/2.md), [jail(2)](/jail/2.md)

## HISTORY

The **chroot**() system call appeared in Version 7 AT&T UNIX. It was marked as “legacy” in Version 2 of the Single UNIX Specification (“SUSv2”), and was removed in subsequent standards. The **fchroot**() system call first appeared in FreeBSD 15.0.

## BUGS

If the process is able to change its working directory to the target directory, but another access control check fails (such as 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.

## SECURITY CONSIDERATIONS

The system has many hardcoded paths to files which it may load after the process starts. It is generally recommended to drop privileges immediately after a successful **chroot** call, and restrict write access to a limited subtree of the **chroot** root. For instance, setup the sandbox so that the sandboxed user will have no write access to any well-known system directories.

For complete isolation from the rest of the system, use [jail(2)](/jail/2.md) instead.
