From patchwork Wed Mar 26 20:23:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 876324 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f4c:0:b0:38f:210b:807b with SMTP id cm12csp3367888wrb; Wed, 26 Mar 2025 13:25:34 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWxlOGZPLyVskW6HH2CWREDRIOL5ToYvSyRm/7PHytiNLXjMzpZMhiGFdFLkoqkBeBqecnHUQ==@linaro.org X-Google-Smtp-Source: AGHT+IFDV0RoZ6P19bFLJta12+Rc1qJGEpyW1WPZ/OoycfGY3nuKVj2Dm0FjMRQjfsxPZV/WUJJF X-Received: by 2002:a05:622a:58c6:b0:477:c04:b511 with SMTP id d75a77b69052e-4776e0d8890mr19290201cf.31.1743020734586; Wed, 26 Mar 2025 13:25:34 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1743020734; cv=pass; d=google.com; s=arc-20240605; b=WPofDpR08QWfs6P4eLa8gEZCxjy4OFP6feSmy5ycvQePJjScn2DCPrr9EWjozr2U/o itNqRfR2r4x2IPNiYiu/fTzQxvgr0BK4bUp5kkCeb99Tyru19sHKixUnFboR20Ghhulc YBGMQrVQky/AirVyVE+/bVfG8PJDrU4h9ExMnwyFBCt+IlxeGYIoY3yojuz9EBBxAEph nCailyGDRiCaE8cCr6a5uiJdcQoQM5RFJaT0seBao/M3bLmov+svBCxND3OpiCySyCyL vJGoe/Cb91AFmMPjuL7mvmAtKJCWaM0YSd8+A1YaVH2IvyaXGQk2mCXY64TWFqJzOPj5 VVYQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :dkim-filter:arc-filter:dmarc-filter:delivered-to:dkim-filter; bh=q2v6FcKjRqrsYZnckfiS65SnN/R2zEnZOtvEwyq3U4U=; fh=5vlP+0ToNsZNUEx4IDYFBtVkL7R0+LPY9AvG1oUICyQ=; b=iYEJxQxlAcFECJyHR+cNKOEaSN3EnDXdi+WsfNiIiek/Zay1EqdKVgTL32j/oDomZf uIhtSp7ZwrcMREIF46FUtIhluRcroQhwvImd89IU21xeOedC2i1VtV6oHKjciYNkC+5C NAZYjX9zgk/ws9d6JgEO2sd091z+ljrTsx7PfLxvqgLyqwsn/KXTIU2d05NJD4ME5H3o eol9kW/0HJejaWFDc1x3do4qi207daMH6XcfHiF6ofV4uml327+pkht8WjNic96SwZzQ 5NckD9zwJhEVAODMZd0fmoO/DsnWXKbaC6ciuIMninqU6qnDejx+Z5CsbVenP5wr3itP suHA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=H2Jlvarl; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id d75a77b69052e-4771d4febbdsi120225511cf.202.2025.03.26.13.25.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Mar 2025 13:25:34 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=H2Jlvarl; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 240AA385B51A for ; Wed, 26 Mar 2025 20:25:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 240AA385B51A Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=H2Jlvarl X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id 28062385B508 for ; Wed, 26 Mar 2025 20:25:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 28062385B508 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 28062385B508 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1743020706; cv=none; b=f0V6vJOfBTcqPr6vKbI40g6KYTgEEJfgmZ4tdXcPfPxQs5U3b4Q0Lo2li1SU6friqOFBPTcFXIgV78cWfNK21JzizJVsehco+28YB2QzwNLkJ1ep2d8Zx/V7TX/KSThXR8KhsIm0HMLj0j7UPO52aZTLBSusO65zGu162J/b1hE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1743020706; c=relaxed/simple; bh=M2nWPF/S6Nd4eEA+mZv0T0JNBA1akJtiyfw8J2aLudU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=u+uQAxLjJ9keXA2apUu4TEoL2J/q/L4GKpOTYGu97cZ7Argb3rX0VRLi7FOa+w4ERN2hSIx4dEFPiLWSNdWFBuEY1A9LFGEzUb+Gb/SfFhTXqTZ1ctxoQx8E/IJaSQvuiNAsLKSpjs5FDYtGS1Qym4kIZmNTHcpGP+AjFtPfchU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 28062385B508 Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-2255003f4c6so6688115ad.0 for ; Wed, 26 Mar 2025 13:25:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1743020705; x=1743625505; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=q2v6FcKjRqrsYZnckfiS65SnN/R2zEnZOtvEwyq3U4U=; b=H2Jlvarl5mhYoCgwy/cZWdjA/TD9sJ6cLtgNRkqhVtM8fV2IanI+zA36fFlIvsivib YzmTBJjTXZ5Z5WbcM8MW0LjRJ2uwkkpXQYj9/uSFcOHpo+8Qu9jn3nTtcO7HBL4A9dkM RnNv5szcbKo9JWAu2xsvJI42PSwb0xFQ8FTYuIWKEKqB3vnjrNhKgQloA6iFAaddYUKO goAZTLcNfFHaXPPqGCcoh0fSi1Sj7XZX/MquUNB6Sl4Zet7gnoiaDE0M+IUqUOvws7O+ bDjFlxMyJBF8U1H3E8dGxqCVR7J+TJOVlezb41D2nTyr2LPWXq4BY+tgeRjODWX0axEr VUYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743020705; x=1743625505; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=q2v6FcKjRqrsYZnckfiS65SnN/R2zEnZOtvEwyq3U4U=; b=dQuv/55i7r04uC14jo1nRzsTwVt52l/az9oEMpVIxdoxVep5tyPCSKo/3hOhP7qI6z 0q7u3Y50RX1S8QNc1Q5aB88ZblnYdIshr/6Dp7ZNBxNkekV0YrwowI/WsOy4OF4ESzJB y3kxNi317JvYqCk76pScb1J3FegQLdUoAgMeoM0/ORSAVbwBMyw9WlYDvX0YOs6R5JIK +Ul1tVhz5uhX53b92IpvBNIDGhsaYXUK0HhLxh5ohupsL49ig3bPNc+5Ec4tHL+48krW zSX4eOF5naplCJgrm89n2Ev5oTK8dr704f4QV5/k3KK+7L/CReqwZSGNbuCjhCvFhCCd Dy9Q== X-Gm-Message-State: AOJu0Yx6Jg7YLzgYy1tMqK49V9eSZhW/n7QwfiKz6xJy2siKKEykVNRt a5L0LRWk+pjgLErD46uR1Apl0HphexCZ6ITRVaCVcMIGW+Hu4znpfPLpZYzK9BpvMhZLVDUDonK h X-Gm-Gg: ASbGncsG0NtvxcGNdSHh0UYmQpzxUC2rEi8iBjF7H2q4dVE3ANUzTzJS0qZLv+VSBe4 IxblvfUxpcVIct9P0OvCGcMx+6qS0QaOCZE8U/+W5Q7+9St0w74AgIANpN88VnxnrPFKTGD0GLf dvkyC4HEdG8BdMoN8/bCuim6Bw/ZtByk/bfAaksxPQSwHqTltAktjNirv+JpNsZv7PsjI+xY1XC 9UiaPVfIgHTyrp3vlLE0/+bWNpPwaSFFk8g6kjuPUm5dZTk57AJhaFCEFdNNCpxX+bLGxcNncAg wFeUiKMErnzL3ypXKEnQazylkhkI0HWioSSf5w1mDnCDmEMxAuZPCko+LH4jW/aDlNKV X-Received: by 2002:a17:903:2f85:b0:225:abd2:5e4b with SMTP id d9443c01a7336-22804854979mr11995575ad.16.1743020703834; Wed, 26 Mar 2025 13:25:03 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c2:348b:4ef6:7201:973e:a24d]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22780f45a06sm114753685ad.69.2025.03.26.13.25.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Mar 2025 13:25:03 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer Subject: [PATCH v4] linux: Add openat2 (BZ 31664) Date: Wed, 26 Mar 2025 17:23:53 -0300 Message-ID: <20250326202459.1428196-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patch=linaro.org@sourceware.org The openat2 syscall was added on Linux 5.6, as an extension of openat. Different than other open-like functions, the kernel only provides the LFS variant (so files larger than 4GB always succeed, as other functions with offset larger than off_t). Also, imilar to other open functions, the new symbol is a cancellable entrypoint. The test case added only stresses some of the syscalls provided functionalities and it is based on an existent kernel self-test. Since the prototype does not use variadic arguments, there is no need to add a fortify wrapper to catch wrong usages. The documentation mostly defers to the Linux manual pages. Checked on x86_64-linux-gnu. --- Changes from v3: * Extend testing for RESOLVE_BENEATH and RESOLVE_IN_ROOT flags. * Fixed manual wording. Changes from v2: * Rebased against master and adapt to version 2.42 --- NEWS | 4 + manual/llio.texi | 113 ++++ sysdeps/unix/sysv/linux/Makefile | 17 + sysdeps/unix/sysv/linux/Versions | 3 + sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 + sysdeps/unix/sysv/linux/alpha/libc.abilist | 1 + sysdeps/unix/sysv/linux/arc/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/bits/fcntl-linux.h | 22 + sysdeps/unix/sysv/linux/bits/openat2.h | 61 +++ sysdeps/unix/sysv/linux/csky/libc.abilist | 1 + sysdeps/unix/sysv/linux/hppa/libc.abilist | 1 + sysdeps/unix/sysv/linux/i386/libc.abilist | 1 + .../sysv/linux/loongarch/lp64/libc.abilist | 1 + .../sysv/linux/m68k/coldfire/libc.abilist | 1 + .../unix/sysv/linux/m68k/m680x0/libc.abilist | 1 + .../sysv/linux/microblaze/be/libc.abilist | 1 + .../sysv/linux/microblaze/le/libc.abilist | 1 + .../sysv/linux/mips/mips32/fpu/libc.abilist | 1 + .../sysv/linux/mips/mips32/nofpu/libc.abilist | 1 + .../sysv/linux/mips/mips64/n32/libc.abilist | 1 + .../sysv/linux/mips/mips64/n64/libc.abilist | 1 + sysdeps/unix/sysv/linux/openat2.c | 29 ++ sysdeps/unix/sysv/linux/or1k/libc.abilist | 1 + .../linux/powerpc/powerpc32/fpu/libc.abilist | 1 + .../powerpc/powerpc32/nofpu/libc.abilist | 1 + .../linux/powerpc/powerpc64/be/libc.abilist | 1 + .../linux/powerpc/powerpc64/le/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv32/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv64/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-32/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-64/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/le/libc.abilist | 1 + .../sysv/linux/sparc/sparc32/libc.abilist | 1 + .../sysv/linux/sparc/sparc64/libc.abilist | 1 + sysdeps/unix/sysv/linux/tst-openat2-consts.py | 63 +++ sysdeps/unix/sysv/linux/tst-openat2-lfs.c | 1 + sysdeps/unix/sysv/linux/tst-openat2.c | 482 ++++++++++++++++++ .../unix/sysv/linux/x86_64/64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 42 files changed, 827 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/bits/openat2.h create mode 100644 sysdeps/unix/sysv/linux/openat2.c create mode 100755 sysdeps/unix/sysv/linux/tst-openat2-consts.py create mode 100644 sysdeps/unix/sysv/linux/tst-openat2-lfs.c create mode 100644 sysdeps/unix/sysv/linux/tst-openat2.c diff --git a/NEWS b/NEWS index c2a978b460..073c2a945a 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,10 @@ Major new features: * On Linux, the pthread_gettid_np function has been added. +* On Linux, the openat2 function has been added. It is an extension of + openat and provides a superset of its functionality. It is supported only + in LFS mode and it is a cancellable entrypoint. + Deprecated and removed features, and other changes affecting compatibility: [Add deprecations, removals and changes affecting compatibility here] diff --git a/manual/llio.texi b/manual/llio.texi index b6bc7f2210..a7191884e8 100644 --- a/manual/llio.texi +++ b/manual/llio.texi @@ -218,6 +218,119 @@ new, extended API using 64 bit file sizes and offsets transparently replaces the old API. @end deftypefun +@deftp {Data Type} {struct open_how} +@standards{Linux, fcntl.h} +The @code{open_how} structure describes how to open a file using @code{openat2}. + +@strong{Portability note:} In the future, additional fields can be added +to @code{struct open_how} at the end, so that the size of this data +type changes. Do not use it in places where this matters, such as +structure fields in installed header files, where such a change could +impact the application binary interface (ABI). + +The following generic fields are available. + +@table @code +@item flags +This field specifies the file creation and file status flags to use when +opening the file. +All of the @code{O_*} flags defined for @code{openat} are valid. +Different than @code{openat}, @code{openat2} returns an error for unknown +or conflicting values. + +@item mode +This field specifies the mode for the new file, similar to @code{mode} +argument of @code{openat}. Different than @code{openat}, @code{openat2} +returns an error for invalid value (like value larger than @code{07777}). + +@item resolve +This is a bitmask of flags that modify the way in @strong{all} components +of @code{pathname}. It allows trusted programs to restrict how untrusted +paths are resolved. The following generic flags are available. + +@table @code +@item RESOLVE_NO_XDEV +Disallow traversal of mount points during path resolution (including all +bind mounts). + +@item RESOLVE_NO_MAGICLINKS +Disallow all @strong{magic-link} resolution during path resolution. Magic +links are symbolic link-like objects that are found in @strong{procfs}; +for example the @code{/proc/pid/exe}. + +@item RESOLVE_NO_SYMLINKS +Disallow resolution of symbolic links during path resolution. +This option implies @code{RESOLVE_NO_MAGICLINKS}. + +@item RESOLVE_BENEATH +Do not permit the path resolution to succeed if any component of the +resolution is not a descendant of the directory indicated by @var{dirfd}. +This cause absolute symbolic links and absolute values of @var{pathname} +to be reject. + +@item RESOLVE_IN_ROOT +Treat the directory referred by @var{dirfd} as the root directory +while resolving the @var{pathname}. +Absolute symbolic links and absolute values of @var{pathnames} are +interpreted relative to @var{dirfd}. +The effect of this flag is as though the calling process has used +@code{chroot} to modify its root direftory. + +@item RESOLVE_CACHED +Make the open operation fail unless all path components are already +present in the kernel's lookup cache. +@end table + +@end table + +For additional information, consult the manual page @manpageurl{openat2,2}. +@xref{Linux Kernel}. +@end deftp + + +@deftypefun int openat2 (int @var{dirfd}, const char *@var{pathname}, struct open_how *@var{how}, size_t @var{size}) +@standards{Linux, fcntl.h} +@safety{@mtsafe{}@assafe{}@acsafe{}} +This function is a extension of the @code{openat} and provides a superset of its +functionality. @xref{Descriptor-Relative Access}. + +The @code{size} define the expected size of @code{how} data structure. +It is recommended to initialize unused fields to zero, either using +@code{memset}, or using a structure initializer. + +On failure, @code{openat2} returns @math{-1} and sets @code{errno}. The +following errors are also returned: + +@table @code +@item E2BIG +An extension that the kernel does support was specified in @code{*@var{how}}, +or a larger struct was used with non-zero fields. + +@item EAGAIN +@code{@var{how}->resolve} contains either RESOLVE_IN_ROOT or RESOLVE_BENEATH, and +the kernel could not ensure that @code{".."} component did not escape. Or +@code{RESOLVE_CACHED} was set, and the open operation cannot be performed +using only cached information. + +@item EINVAL +And unknown flag or invalid value was used on @code{*@var{how}}; or +@code{@var{how}->mode} is non-zero, but @code{@var{how}->flags} does not contain +@code{O_CREAT} or@code{O_TMPFILE}, or @var{size} is smaller than the ones supported +by the kernel. +@end table + +It can also return all the errors @code{openat} returns, or other errors +due new fields added by the kernel. + +Similar to @code{openat}, @code{openat2} is a cancellation point. + +@strong{NB:} Different than other open-like functions, the kernel only +provides the LFS variant. When the sources are translated with +@code{_FILE_OFFSET_BITS == 64} this function is not routed a different +symbol. +@end deftypefun + + @deftypefn {Obsolete function} int creat (const char *@var{filename}, mode_t @var{mode}) @standards{POSIX.1, fcntl.h} @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index dcd87b295e..8a0747d718 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -135,6 +135,7 @@ sysdep_headers += \ bits/mman-linux.h \ bits/mman-map-flags-generic.h \ bits/mman-shared.h \ + bits/openat2.h \ bits/procfs-extra.h \ bits/procfs-id.h \ bits/procfs-prregset.h \ @@ -615,6 +616,7 @@ sysdep_routines += \ internal_statvfs \ open64_nocancel \ open_nocancel \ + openat2 \ openat64_nocancel \ openat_nocancel \ pread64_nocancel \ @@ -635,7 +637,22 @@ tests += \ tst-fallocate64 \ tst-getcwd-smallbuff \ tst-o_path-locks \ + tst-openat2 \ + tst-openat2-lfs \ # tests + +tests-special += \ + $(objpfx)tst-openat2-consts.out \ + # tests-special +$(objpfx)tst-openat2-consts.out: ../sysdeps/unix/sysv/linux/tst-openat2-consts.py + $(sysdeps-linux-python) \ + ../sysdeps/unix/sysv/linux/tst-openat2-consts.py \ + $(sysdeps-linux-python-cc) \ + < /dev/null > $@ 2>&1; $(evaluate-test) +$(objpfx)tst-openat2-consts.out: $(sysdeps-linux-python-deps) + +CFLAGS-tst-openat2-lfs.c += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE + endif ifeq ($(subdir),elf) diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index 55d565545a..f921f954c1 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -332,6 +332,9 @@ libc { sched_getattr; sched_setattr; } + GLIBC_2.42 { + openat2; + } GLIBC_PRIVATE { # functions used in other libraries __syscall_rt_sigqueueinfo; diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index 41f8f39911..f5fd82f2b2 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2752,4 +2752,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 34efc96781..5423cdfa04 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -3099,6 +3099,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist index de7c618d28..79d87053a5 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2513,4 +2513,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist index 96f0314b16..f59e33c6e9 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -2805,6 +2805,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist index 635468fa13..c30121bce3 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -2802,6 +2802,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h index dfc554aafc..3fab352061 100644 --- a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h +++ b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h @@ -453,6 +453,28 @@ extern int name_to_handle_at (int __dfd, const char *__name, extern int open_by_handle_at (int __mountdirfd, struct file_handle *__handle, int __flags); +#ifdef __has_include +# if __has_include ("linux/openat2.h") +# include "linux/openat2.h" +# define __glibc_has_open_how 1 +# endif +#endif + +#include + +/* Similar to `openat' but the arguments are packed on HOW with the size + USIZE. If flags and mode from HOW are non-zero, then openat2 operates + like openat. + + Unlike openat2, unknown or invalid flags result in an error (EINVAL), + rather than being ignored. The mode must be zero unless one O_CREAT + or O_TMPFILE are set. + + The kernel does not support legacy non-LFS interface. */ +extern int openat2 (int __dfd, const char *__filename, struct open_how *__how, + size_t __usize) + __nonnull ((2, 3)); + #endif /* use GNU */ __END_DECLS diff --git a/sysdeps/unix/sysv/linux/bits/openat2.h b/sysdeps/unix/sysv/linux/bits/openat2.h new file mode 100644 index 0000000000..6059095bc1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/bits/openat2.h @@ -0,0 +1,61 @@ +/* openat2 definition. Linux specific. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#ifndef __glibc_has_open_how +/* Arguments for how openat2 should open the target path. */ +struct open_how +{ + __uint64_t flags; + __uint64_t mode; + __uint64_t resolve; +}; +#endif + +/* how->resolve flags for openat2. */ +#ifndef RESOLVE_NO_XDEV +# define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings + (includes bind-mounts). */ +#endif +#ifndef RESOLVE_NO_MAGICLINKS +# define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style + "magic-links". */ +#endif +#ifndef RESOLVE_NO_SYMLINKS +# define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks + (implies OEXT_NO_MAGICLINKS). */ +#endif +#ifndef RESOLVE_BENEATH +# define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like + "..", symlinks, and absolute + paths which escape the dirfd. */ +#endif +#ifndef RESOLVE_IN_ROOT +# define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".." + be scoped inside the dirfd + (similar to chroot). */ +#endif +#ifndef RESOLVE_CACHED +# define RESOLVE_CACHED 0x20 /* Only complete if resolution can be + completed through cached lookup. May + return -EAGAIN if that's not + possible. */ +#endif diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index 490694ddce..164e3f7ac6 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2789,4 +2789,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index b1905da767..1a76151b00 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2826,6 +2826,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index 424ef34a8b..840149290c 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -3009,6 +3009,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist index 420471eb24..1974af87d1 100644 --- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist +++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist @@ -2273,4 +2273,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index 95a68c7cc1..eef0567f8b 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -2785,6 +2785,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index 442e82b6d2..c110066a15 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2952,6 +2952,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist index 20f7712988..2c47702cde 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2838,4 +2838,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist index f61ed3bf26..a87aec00d5 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2835,4 +2835,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index 381120cc16..5cd332d67c 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2913,6 +2913,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index 2f51146084..55c441be99 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2907,6 +2907,7 @@ GLIBC_2.4 renameat F GLIBC_2.4 symlinkat F GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.41 openat2 F GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index e6071be2ae..6f8314926d 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2919,6 +2919,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index f41e209a2b..de29a2a908 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2821,6 +2821,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/openat2.c b/sysdeps/unix/sysv/linux/openat2.c new file mode 100644 index 0000000000..bb4f3e1f16 --- /dev/null +++ b/sysdeps/unix/sysv/linux/openat2.c @@ -0,0 +1,29 @@ +/* Linux openat2 syscall implementation. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +int +__openat2 (int dfd, const char *filename, struct open_how *how, + size_t usize) +{ + return SYSCALL_CANCEL (openat2, dfd, filename, how, usize); +} +weak_alias (__openat2, openat2) diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist index bbcdb31f09..6e2a372186 100644 --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist @@ -2263,4 +2263,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index e0ea22b9c6..ed60bd40c5 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -3142,6 +3142,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index 16b9a771f1..d040356b86 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -3187,6 +3187,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index 070f6f5a08..c8d5f177df 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2896,6 +2896,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index 4378d1d922..68668b5121 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2972,4 +2972,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index 48c6e269a5..8ff99ecdd9 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2516,4 +2516,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index a8b0c6aca7..f382d9a630 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2716,4 +2716,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index 6c00b8440b..02fb528f0a 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -3140,6 +3140,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index f866e5d6f3..d3530fd86c 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2933,6 +2933,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist index 4f2db8cb9b..9ffb0af9d6 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2832,6 +2832,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist index a73473ee32..893d865485 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2829,6 +2829,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index dc7e27db2a..ff808e9c59 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -3161,6 +3161,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index 2ee97f42fb..fae56f00db 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2797,6 +2797,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/tst-openat2-consts.py b/sysdeps/unix/sysv/linux/tst-openat2-consts.py new file mode 100755 index 0000000000..9b65d184d7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-openat2-consts.py @@ -0,0 +1,63 @@ +#!/usr/bin/python3 +# Test that glibc's sys/openat2.h constants match the kernel's. +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# . + +import argparse +import sys + +import glibcextract +import glibcsyscalls + + +def main(): + """The main entry point.""" + parser = argparse.ArgumentParser( + description="Test that glibc's sys/openat2.h constants " + "match the kernel's.") + parser.add_argument('--cc', metavar='CC', + help='C compiler (including options) to use') + args = parser.parse_args() + + if glibcextract.compile_c_snippet( + '#include ', + args.cc).returncode != 0: + sys.exit (77) + + linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc) + # Constants in glibc were updated to match Linux v6.8. When glibc + # constants are updated this value should be updated to match the + # released kernel version from which the constants were taken. + linux_version_glibc = (6, 8) + def check(cte, exclude=None): + return glibcextract.compare_macro_consts( + '#define _FCNTL_H\n' + '#include \n' + '#include \n', + '#include \n' + '#include \n', + args.cc, + cte, + exclude, + linux_version_glibc > linux_version_headers, + linux_version_headers > linux_version_glibc) + + status = check('RESOLVE.*') + sys.exit(status) + +if __name__ == '__main__': + main() diff --git a/sysdeps/unix/sysv/linux/tst-openat2-lfs.c b/sysdeps/unix/sysv/linux/tst-openat2-lfs.c new file mode 100644 index 0000000000..85962d30c1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-openat2-lfs.c @@ -0,0 +1 @@ +#include "tst-openat2.c" diff --git a/sysdeps/unix/sysv/linux/tst-openat2.c b/sysdeps/unix/sysv/linux/tst-openat2.c new file mode 100644 index 0000000000..e52e3870d0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-openat2.c @@ -0,0 +1,482 @@ +/* Linux openat2 tests. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static int dir_fd; +static char *temp_dir; +static char *temp_subdir; +static char *temp_some_file; + +#define TEST_DIR_LINK "test_dir_link" +#define TEST_DIR_LINK_2 "test_dir_link_2" +#define TEMP_DIR_LINK "temp_dir_link" +#define INVALID_LINK "invalid-link" +#define VALID_LINK "valid-link" + +static void +create_symlink (const char *target, const char *linkpath) +{ + TEST_VERIFY_EXIT (symlinkat (target, dir_fd, linkpath) == 0); + add_temp_file (xasprintf ("%s/%s", temp_dir, linkpath)); +} + +static void +do_prepare (int argc, char *argv[]) +{ + /* + Construct a test directory with the following structure: + + temp_dir/ + |- tst-openat2.xxxxxxx + |- test_dir_link -> test_dir (/tmp) + |- test_dir_link_2 -> test_dir_link + |- temp_dir_link -> temp_dir/tst-openat2.xxxxxxx + |- some-file.xxxxxxx + |- invalid_link -> temp_dir/tst-openat2.xxxxxxx/some-file.xxxxxxx + |- valid_link -> some-file.xxxxxxx + |- subdir.xxxxxxx + |- some-file.xxxxxxx + */ + + temp_dir = support_create_temp_directory ("tst-openat2."); + dir_fd = xopen (temp_dir, O_RDONLY | O_DIRECTORY, 0); + + create_symlink (test_dir, TEST_DIR_LINK); + create_symlink (TEST_DIR_LINK, TEST_DIR_LINK_2); + create_symlink (temp_dir, TEMP_DIR_LINK); + + { + char *filename; + int fd = create_temp_file_in_dir ("some-file.", temp_dir, &filename); + TEST_VERIFY_EXIT (fd != -1); + + create_symlink (filename, INVALID_LINK); + + create_symlink (basename (filename), VALID_LINK); + } + + temp_subdir = support_create_temp_directory (xasprintf ("%s/subdir.", + basename (temp_dir))); + { + int fd = create_temp_file_in_dir ("some-file.", temp_subdir, + &temp_some_file); + TEST_VERIFY_EXIT (fd != -1); + } +} +#define PREPARE do_prepare + +static int +do_test_struct (void) +{ + static struct struct_test + { + struct open_how_ext + { + struct open_how inner; + int extra1; + int extra2; + int extra3; + } arg; + size_t size; + int err; + } tests[] = + { + { + /* Zero size. */ + .arg.inner.flags = O_RDONLY, + .size = 0, + .err = EINVAL, + }, + { + /* Normal struct. */ + .arg.inner.flags = O_RDONLY, + .size = sizeof (struct open_how), + }, + { + /* Larger struct, zeroed out the unused values. */ + .arg.inner.flags = O_RDONLY, + .size = sizeof (struct open_how_ext), + }, + { + /* Larger struct, non-zeroed out the unused values. */ + .arg.inner.flags = O_RDONLY, + .arg.extra1 = 0xdeadbeef, + .size = sizeof (struct open_how_ext), + .err = E2BIG, + }, + { + /* Larger struct, non-zeroed out the unused values. */ + .arg.inner.flags = O_RDONLY, + .arg.extra2 = 0xdeadbeef, + .size = sizeof (struct open_how_ext), + .err = E2BIG, + }, + }; + + for (struct struct_test *t = tests; t != array_end (tests); t++) + { + int fd = openat2 (AT_FDCWD, ".", (struct open_how *) &t->arg, t->size); + if (t->err != 0) + { + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, t->err); + } + else + TEST_VERIFY (fd >= 0); + } + + return 0; +} + +static int +do_test_flags (void) +{ + static struct flag_test + { + const char *path; + struct open_how how; + int err; + } tests[] = + { + /* O_TMPFILE is incompatible with O_PATH and O_CREAT. */ + { + .how.flags = O_TMPFILE | O_PATH | O_RDWR, + .err = EINVAL }, + { + .how.flags = O_TMPFILE | O_CREAT | O_RDWR, + .err = EINVAL }, + + /* O_PATH only permits certain other flags to be set ... */ + { + .how.flags = O_PATH | O_CLOEXEC + }, + { + .how.flags = O_PATH | O_DIRECTORY + }, + { + .how.flags = O_PATH | O_NOFOLLOW + }, + /* ... and others are absolutely not permitted. */ + { + .how.flags = O_PATH | O_RDWR, + .err = EINVAL }, + { + .how.flags = O_PATH | O_CREAT, + .err = EINVAL }, + { + .how.flags = O_PATH | O_EXCL, + .err = EINVAL }, + { + .how.flags = O_PATH | O_NOCTTY, + .err = EINVAL }, + { + .how.flags = O_PATH | O_DIRECT, + .err = EINVAL }, + + /* ->mode must only be set with O_{CREAT,TMPFILE}. */ + { + .how.flags = O_RDONLY, + .how.mode = 0600, + .err = EINVAL }, + { + .how.flags = O_PATH, + .how.mode = 0600, + .err = EINVAL }, + { + .how.flags = O_CREAT, + .how.mode = 0600 }, + { + .how.flags = O_TMPFILE | O_RDWR, + .how.mode = 0600 }, + /* ->mode must only contain 0777 bits. */ + { + .how.flags = O_CREAT, .how.mode = 0xFFFF, .err = EINVAL }, + { + .how.flags = O_CREAT, .how.mode = 0xC000000000000000ULL, + .err = EINVAL }, + { + .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0x1337, + .err = EINVAL }, + { + .how.flags = O_TMPFILE | O_RDWR, + .how.mode = 0x0000A00000000000ULL, + .err = EINVAL + }, + + /* ->resolve flags must not conflict. */ + { + .how.flags = O_RDONLY, + .how.resolve = RESOLVE_BENEATH | RESOLVE_IN_ROOT, + .err = EINVAL + }, + + /* ->resolve must only contain RESOLVE_* flags. */ + { + .how.flags = O_RDONLY, + .how.resolve = 0x1337, + .err = EINVAL + }, + { + .how.flags = O_CREAT, + .how.resolve = 0x1337, + .err = EINVAL + }, + { + .how.flags = O_TMPFILE | O_RDWR, + .how.resolve = 0x1337, + .err = EINVAL + }, + { + .how.flags = O_PATH, + .how.resolve = 0x1337, + .err = EINVAL + }, + + /* currently unknown upper 32 bit rejected. */ + { + .how.flags = O_RDONLY | (1ULL << 63), + .how.resolve = 0, + .err = EINVAL + }, + }; + + for (struct flag_test *t = tests; t != array_end (tests); t++) + { + const char *path; + if (t->how.flags & O_CREAT) + { + char *newfile; + int temp_fd = create_temp_file ("tst-openat2.", &newfile); + TEST_VERIFY_EXIT (temp_fd != -1); + xunlink (newfile); + path = newfile; + } + else + path = "."; + + int fd = openat2 (AT_FDCWD, path, &t->how, sizeof (struct open_how)); + if (fd != 0 && errno == EOPNOTSUPP) + { + /* Skip the testcase if FS does not support the operation (e.g. + valid O_TMPFILE on NFS). */ + continue; + } + + if (t->err != 0) + { + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, t->err); + } + else + TEST_VERIFY (fd >= 0); + } + + return 0; +} + +static void +do_test_resolve (void) +{ + int fd; + + /* TEMP_DIR_LINK links to the absolute temp_dir, which escapes the temporary + test directory. */ + fd = openat2 (dir_fd, + TEST_DIR_LINK, + &(struct open_how) + { + .resolve = RESOLVE_BENEATH, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, EXDEV); + + /* Same as before, TEMP_DIR_LINK_2 links to TEMP_DIR_LINK. */ + fd = openat2 (dir_fd, + TEST_DIR_LINK_2, + &(struct open_how) + { + .resolve = RESOLVE_BENEATH, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, EXDEV); + + /* TEMP_DIR_LINK links to the temproary directory itself (dir_fd). */ + fd = openat2 (dir_fd, + TEMP_DIR_LINK, + &(struct open_how) + { + .resolve = RESOLVE_BENEATH, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, EXDEV); + + /* Although it points to a valid file in same path, the link refers to + an absolute path. */ + fd = openat2 (dir_fd, + INVALID_LINK, + &(struct open_how) + { + .resolve = RESOLVE_BENEATH, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, EXDEV); + + fd = openat2 (dir_fd, + VALID_LINK, + &(struct open_how) + { + .resolve = RESOLVE_BENEATH, + }, + sizeof (struct open_how)); + TEST_VERIFY (fd != -1); + xclose (fd); + + /* There is no such file in temp_dir/tst-openat2.xxxxxxx. */ + fd = openat2 (dir_fd, + "should-not-work", + &(struct open_how) + { + .resolve = RESOLVE_IN_ROOT, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, ENOENT); + + { + int subdir_fd = openat2 (dir_fd, + basename (temp_subdir), + &(struct open_how) + { + .flags = O_RDONLY | O_DIRECTORY, + .resolve = RESOLVE_IN_ROOT, + }, + sizeof (struct open_how)); + TEST_VERIFY (subdir_fd != -1); + + /* Open the file within the subdir.xxxxxx with both tst-openat2.xxxxxxx + and tst-openat2.xxxxxxx/subdir.xxxxxxx file descriptors. */ + fd = openat2 (subdir_fd, + basename (temp_some_file), + &(struct open_how) + { + .resolve = RESOLVE_IN_ROOT, + }, + sizeof (struct open_how)); + TEST_VERIFY (fd != -1); + xclose (fd); + + fd = openat2 (dir_fd, + xasprintf ("%s/%s", + basename (temp_subdir), + basename (temp_some_file)), + &(struct open_how) + { + .resolve = RESOLVE_IN_ROOT, + }, + sizeof (struct open_how)); + TEST_VERIFY (fd != -1); + xclose (fd); + } +} + +static int +do_test_basic (void) +{ + int fd; + + fd = openat2 (dir_fd, + "some-file", + &(struct open_how) + { + .flags = O_CREAT|O_RDWR|O_EXCL, + .mode = 0666, + }, + sizeof (struct open_how)); + TEST_VERIFY (fd != -1); + + xwrite (fd, "hello", 5); + + /* Before closing the file, try using this file descriptor to open + another file. This must fail. */ + { + int fd2 = openat2 (fd, + "should-not-work", + &(struct open_how) + { + .flags = O_CREAT|O_RDWR|O_EXCL, + .mode = 0666, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd2, -1); + TEST_COMPARE (errno, ENOTDIR); + } + + /* Remove the created file. */ + int cwdfd = xopen (".", O_RDONLY | O_DIRECTORY, 0); + TEST_COMPARE (fchdir (dir_fd), 0); + xunlink ("some-file"); + TEST_COMPARE (fchdir (cwdfd), 0); + + xclose (dir_fd); + xclose (cwdfd); + + fd = openat2 (dir_fd, + "some-file", + &(struct open_how) + { + .flags = O_CREAT|O_RDWR|O_EXCL, + .mode = 0666, + }, + sizeof (struct open_how)); + TEST_COMPARE (fd, -1); + TEST_COMPARE (errno, EBADF); + + return 0; +} + +static int +do_test (void) +{ + if (openat2 (AT_FDCWD, ".", &(struct open_how) {}, sizeof (struct open_how)) + == -1 && errno == ENOSYS) + FAIL_UNSUPPORTED ("openat2 is not supported by the kernel"); + + do_test_struct (); + do_test_flags (); + do_test_resolve (); + do_test_basic (); + + return 0; +} + +#include diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index a7ada1ea53..8bda91b215 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2748,6 +2748,7 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index f41ab77c1e..75909af91a 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2767,4 +2767,5 @@ GLIBC_2.41 sched_getattr F GLIBC_2.41 sched_setattr F GLIBC_2.42 __inet_ntop_chk F GLIBC_2.42 __inet_pton_chk F +GLIBC_2.42 openat2 F GLIBC_2.42 pthread_gettid_np F