The documentation we have about O_EXEC and O_SEARCH is confusing:

   "Gnulib defines these macros to @samp{O_RDONLY}, which is typically 0.
    The @samp{O_PATH} macro of GNU/Linux is not a suitable substitute, as
    fchmod fails ..."

The second sentence is an explanation of an implementation choice of
Gnulib. It does not belong in user documentation, but rather in comments
of our code.

So I was tempted to add these comments:

diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 8b8274295a..e3a4dbcf69 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -313,6 +313,8 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
 #endif
 
 #ifndef O_EXEC
+/* Not: #define O_EXEC O_PATH
+   See <https://lists.gnu.org/archive/html/bug-gnulib/2012-11/msg00029.html>  
*/
 # define O_EXEC O_RDONLY /* This is often close enough in older systems.  */
 #endif
 
@@ -370,6 +372,8 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
 #endif
 
 #ifndef O_SEARCH
+/* Not: #define O_SEARCH O_PATH
+   See <https://lists.gnu.org/archive/html/bug-gnulib/2012-11/msg00029.html>  
*/
 # define O_SEARCH O_RDONLY /* This is often close enough in older systems.  */
 #endif
 

But upon reviewing the issue, I cannot agree with it.

  * I can confirm that fchown() on a file descriptor opened with O_PATH,
    in Linux, fails with EBADF.

    How to reproduce: Compile this program
====================================
#define _GNU_SOURCE 1
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main ()
{
  {
    int fd = open ("/tmp/1", O_RDONLY);
    fchmod (fd, 777);
    close (fd);
  }
  {
    int fd = open ("/tmp/2", O_PATH);
    fchmod (fd, 777);
    close (fd);
  }
}
====================================
    and run it under 'strace'. The first fchmod() call succeeds,
    the second one fails.

  * I don't agree that it is a Linux kernel bug.
    The POSIX description of O_EXEC and O_SEARCH
    <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fcntl.h.html>
      - "O_EXEC: Open for execute only"
      - "O_SEARCH: Open directory for search only."
    does not support an expectation that fchmod() would succeed
    for a file descriptor opened with one of these flags.
    Nor does
    <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchmod.html>.

  * musl libc defines O_EXEC and O_SEARCH to O_PATH. Therefore, regardless
    of the fallback that Gnulib may use on glibc/Linux systems, fchmod() on
    a file descriptor opened with O_EXEC or O_SEARCH will fail on some systems.

I hope the doc change below reflects this better.


2024-08-28  Bruno Haible  <br...@clisp.org>

        doc: Add more details about O_EXEC and O_SEARCH.
        * doc/posix-headers/fcntl.texi: Add platforms list and revisit note
        about O_EXEC and O_SEARCH.

diff --git a/doc/posix-headers/fcntl.texi b/doc/posix-headers/fcntl.texi
index c7ffba8cf4..b190761e6a 100644
--- a/doc/posix-headers/fcntl.texi
+++ b/doc/posix-headers/fcntl.texi
@@ -36,11 +36,30 @@
 non-zero value; otherwise, the gnulib replacement is 0.
 
 @item
-@samp{O_EXEC} and @samp{O_SEARCH} are not defined on some platforms.
-Gnulib defines these macros to @samp{O_RDONLY}, which is typically 0.
-The @samp{O_PATH} macro of GNU/Linux is not a suitable substitute, as
-fchmod fails with @samp{errno==EBADF} when invoked on a file
-descriptor that was opened with @samp{O_PATH}.
+@samp{O_EXEC} is not defined on some platforms:
+glibc 2.40, macOS 12, FreeBSD 7.4, NetBSD 9.4, OpenBSD 7.5, HP-UX 11, Solaris 
10, Cygwin 1.5.x, mingw, MSVC 14, Android.
+When not otherwise defined,
+Gnulib defines this macro to @samp{O_RDONLY}, which is typically 0.
+
+Note: @samp{O_EXEC} is not suitable for opening a file descriptor
+that you want to use with @code{fchmod} later, because
+musl libc defines @samp{O_EXEC} to @code{O_PATH} and
+@c https://lists.gnu.org/archive/html/bug-gnulib/2012-11/msg00029.html
+Linux @code{fchmod} fails with error @code{EBADF} when given such a file
+descriptor.
+
+@item
+@samp{O_SEARCH} is not defined on some platforms:
+glibc 2.40, macOS 12, FreeBSD 12.4, NetBSD 6.1, OpenBSD 7.5, AIX 6.1, HP-UX 
11, Solaris 10, Cygwin 1.5.x, mingw, MSVC 14, Android.
+When not otherwise defined,
+Gnulib defines this macro to @samp{O_RDONLY}, which is typically 0.
+
+Note: @samp{O_SEARCH} is not suitable for opening a file descriptor
+that you want to use with @code{fchmod} later, because
+musl libc defines @samp{O_EXEC} to @code{O_PATH} and
+@c https://lists.gnu.org/archive/html/bug-gnulib/2012-11/msg00029.html
+Linux @code{fchmod} fails with error @code{EBADF} when given such a file
+descriptor.
 
 @item
 @samp{O_ACCMODE} is not defined on some platforms:




Reply via email to