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

openat2(2)

FieldValue
Numbers (x64 / i386 / arm64-generic / arm32)437 / 437 / 437 / 437 (cached kernel tables; hub agrees)
Since (kernel)5.6 (man VERSIONS)
Man pageman2/openat2.2 (local cache, dated 2021-03-22); struct open_how cross-checked against kernel include/uapi/linux/openat2.h (master, fetched this session)
glibc wrapperNone: glibc provides no wrapper, necessitating syscall(2) (man page)
Aliases coverednone
Ledger IDSC-openat2

Purpose

openat2() is an extension of openat(2) and a superset of it. Instead of a flags int it takes an extensible struct open_how, which carries the O_* flags, the mode, and a resolve mask that restricts how every component of the pathname is resolved. The use case is letting trusted programs open untrusted paths safely: absolute symlinks, “..” escapes, magic links (/proc/[pid]/fd/*), and mount-point crossings can each be forbidden. Unlike openat(2), which ignores unknown flag bits, openat2() rejects unknown or conflicting flags and modes with EINVAL.

Synopsis

#include <linux/openat2.h>      /* struct open_how, RESOLVE_* */
#include <fcntl.h>              /* O_* constants */
int openat2(int dirfd, const char *pathname,
            struct open_how *how, size_t size);

Arguments and behavior

struct open_how (kernel include/uapi/linux/openat2.h) has three __u64 fields:

FieldContents
flagsThe O_* flags of openat(2); unknown or conflicting bits fail EINVAL.
modePermission bits for O_CREAT/O_TMPFILE; bits outside 07777 fail, and nonzero mode without O_CREAT or O_TMPFILE fails.
resolveRESOLVE_* mask; unknown bits fail. The structure must be zero-filled; size is an implicit version number.

RESOLVE_* flags (values from include/uapi/linux/openat2.h):

FlagValueMeaning
RESOLVE_NO_XDEV0x01Fail EXDEV if resolution crosses a mount point (including bind mounts)
RESOLVE_NO_MAGICLINKS0x02Fail ELOOP on procfs-style magic links
RESOLVE_NO_SYMLINKS0x04Fail ELOOP on any symlink component; implies NO_MAGICLINKS
RESOLVE_BENEATH0x08Reject resolution escaping dirfd (absolute paths, “..” tricks)
RESOLVE_IN_ROOT0x10Treat dirfd as the root while resolving (per-open chroot(2) analog)
RESOLVE_CACHED0x20Fail EAGAIN unless the lookup can be served from cache

Return value and errors

Returns a new fd on success; -1 with errno: all openat(2) errors plus E2BIG (unsupported extension, nonzero size mismatch), EAGAIN (IN_ROOT/BENEATH could not rule out a “..” escape, or RESOLVE_CACHED would need I/O), EINVAL, ELOOP, EXDEV (escape detected, or NO_XDEV crossing).

Flags and constants

The master UAPI header adds OPENAT2_REGULAR (1 << 32) in how.flags (“only open regular files”), not present in the 2021 man page; since-version unverified here, kernel-source provenance noted.

Security and notes

  • Zero-fill struct open_how (designated initializers or memset) so future fields stay no-ops; an all-nonzero size probe can discover kernel support via E2BIG.
  • BENEATH/IN_ROOT currently also disable magic links, but the man page says this may change: pass RESOLVE_NO_MAGICLINKS explicitly.
  • With O_PATH | O_NOFOLLOW the call may return an fd to the magic link/symlink itself instead of failing.

References

  • man2/openat2.2 in the cached man-pages tree (dated 2021-03-22).
  • Kernel headers fetched this session: include/uapi/linux/openat2.h, fs/open.c (source-cache/fetched/master-uapi-openat2.h, master-fs-open.c).
  • Syscalls ledger row SC-openat2; sibling open documents the O_* flags.