Theo de Raadt proposed to include a new mechanism in OpenBSD aimed at reducing the attack surface, implemented through an extension of the openat system call capabilities. Patches with additional flags for openat and open, which restrict the ability to navigate to parent directories via "../" and to access files through absolute paths, have been prepared for the kernel, libc, and some applications from the base system. The changes have not yet been integrated into OpenBSD-current and are currently under discussion among developers.
The family of system calls openat(2) operates as an analog to open(2), except that if a relative path is provided in the "path" parameter, the file being opened is determined relative to the directory associated with the file descriptor "fd", rather than the current working directory. If an absolute path is passed to openat, for example: int dirfd = open("/tmp", O_RDONLY | O_DIRECTORY); int hfd = openat(dirfd, "/etc/hosts", O_RDONLY);
The openat() function will ignore "dirfd" and consequently, the absolute path will be processed in the usual manner.
Therefore, replacing open() with openat() does not, by itself, enhance the security of the program. Such a call may speed up path parsing, but does not restrict access to the file system. The flags that prevent absolute paths (such as RESOLVE_BENEATH and/or RESOLVE_IN_ROOT for openat2 in Linux) do not guarantee protection: the programmer must add them to all appropriate calls, and if the control of the process is compromised, an attacker may exploit other file-opening paths.
During the development of the openrsync utility, Theo faced the necessity to limit its filesystem traversal capabilities, but it was not feasible to do this with the unveil() and pledge() functions. This led to the idea of a mechanism similar to openat(), but with security properties that complement pledge/unveil or even operate in their absence.
The main idea is to make restrictions part of the directory file descriptor itself. To achieve this, a F_BELOW flag is proposed, which can be set via fcntl() or an O_BELOW flag for open(). A file descriptor restricted in this way will only allow downward transitions in the directory tree: openat() calls with an absolute path or moving up through ".." will fail with an ENOENT error. In the event of an attack leading to code execution, the process's file descriptor table will contain less functional "dirfd" entries, which will limit the attack surface.
Source: opennet.ru
