]> Savannah Git Hosting - gnulib.git/commitdiff
faccessat: work around F_OK EOVERFLOW bug
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 24 Dec 2020 19:38:48 +0000 (11:38 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 24 Dec 2020 20:06:48 +0000 (12:06 -0800)
Also, tune when LSTAT_FOLLOWS_SLASHED_SYMLINK.
* doc/posix-functions/faccessat.texi: Mention the problem.
* lib/faccessat.c (FACCESSAT_NEVER_EOVERFLOWS)
(LSTAT_FOLLOWS_SLASHED_SYMLINK): Default to 0.
(rpl_faccessat): If !FACCESSAT_NEVER_EOVERFLOWS, check
for F_OK and EOVERFLOW, which means we can return 0.
If LSTAT_FOLLOWS_SLASHED_SYMLINK, don't worry about
file names ending in slashes, as faccessat should already
do the right thing for them.
* m4/faccessat.m4 (gl_FUNC_FACCESSAT_EOVERFLOW): New macro.
(gl_FUNC_FACCESSAT): Use it.

ChangeLog
doc/posix-functions/faccessat.texi
lib/faccessat.c
m4/faccessat.m4

index 3d2186fb914fe41886df41e93dab63a4495d2041..551059e355feb6ab26efec661a996860126ce783 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2020-12-24  Paul Eggert  <eggert@cs.ucla.edu>
 
+       faccessat: work around F_OK EOVERFLOW bug
+       * doc/posix-functions/faccessat.texi: Mention the problem.
+       * lib/faccessat.c (FACCESSAT_NEVER_EOVERFLOWS): Default to 0.
+       (rpl_faccessat): If !FACCESSAT_NEVER_EOVERFLOWS, check
+       for F_OK and EOVERFLOW, which means we can return 0.
+       * m4/faccessat.m4 (gl_FUNC_FACCESSAT_EOVERFLOW): New macro.
+       (gl_FUNC_FACCESSAT): Use it.
+
        stat failing with EOVERFLOW implies existence
        * lib/euidaccess.c (euidaccess):
        * lib/file-has-acl.c (file_has_acl):
index 5d5165e47430a100d5152142b0a119f72d0ce4f7..07ea8e7bf9ac07bf70b57ac6d8272e132d3813d1 100644 (file)
@@ -15,6 +15,12 @@ glibc 2.3.6, macOS 10.12, FreeBSD 7.4, NetBSD 6.1.5, OpenBSD 4.9, Minix 3.1.8, A
 On some platforms, @code{faccessat (dfd, "file/", amode, flag)}
 succeeds instead of failing when @file{file} is not a directory.
 macOS 10.13.
+@item
+On some platforms, @code{faccessat} can incorrectly fail with
+@code{EOVERFLOW} when the mode is @code{F_OK}:
+GNU/Linux with glibc 2.32, or with Linux kernel 5.7.
+@c This bug should be fixed in glibc 2.33 and kernel 5.8.  See:
+@c https://sourceware.org/bugzilla/show_bug.cgi?id=18683
 @end itemize
 
 Portability problems not fixed by Gnulib:
@@ -30,9 +36,11 @@ The replacement does not support the @code{AT_SYMLINK_NOFOLLOW} flag,
 which is supported by GNU @code{faccessat}.
 @item
 On some platforms, @code{faccessat} can mishandle @code{AT_EACCESS}
-after a process starts as root and then becomes non-root:
-GNU/Linux with glibc 2.32.
-@c This bug should be fixed in glibc 2.33.  See:
+after a process starts as root and then becomes non-root,
+or can incorrectly fail with @code{EOVERFLOW} when the mode
+is not @code{F_OK}:
+GNU/Linux with glibc 2.32, or with Linux kernel 5.7.
+@c These bugs should be fixed in glibc 2.33 and kernel 5.8.  See:
 @c https://sourceware.org/bugzilla/show_bug.cgi?id=18683
 @end itemize
 
index 9f6a11bf6e38b3f17d31c01b73c853601dd9d7fe..330c54a0be267519f4170cfdc0bb3f0409aa891d 100644 (file)
 #include <sys/stat.h>
 #undef _GL_INCLUDING_UNISTD_H
 
+#ifndef FACCESSAT_NEVER_EOVERFLOWS
+# define FACCESSAT_NEVER_EOVERFLOWS 0
+#endif
+#ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK
+# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0
+#endif
+
 #if HAVE_FACCESSAT
 static int
 orig_faccessat (int fd, char const *name, int mode, int flag)
@@ -59,7 +66,12 @@ rpl_faccessat (int fd, char const *file, int mode, int flag)
 {
   int result = orig_faccessat (fd, file, mode, flag);
 
-  if (result == 0 && file[strlen (file) - 1] == '/')
+  if (result != 0)
+    {
+      if (!FACCESSAT_NEVER_EOVERFLOWS && mode == F_OK && errno == EOVERFLOW)
+        return 0;
+    }
+  else if (!LSTAT_FOLLOWS_SLASHED_SYMLINK && file[strlen (file) - 1] == '/')
     {
       struct stat st;
       result = fstatat (fd, file, &st, 0);
index 7a8b979f8db519acd3a172efaee8c5d38da3247c..a4ad31a469b86df991b2061e079eb09d6f1e4fcd 100644 (file)
@@ -1,4 +1,4 @@
-# serial 8
+# serial 9
 # See if we need to provide faccessat replacement.
 
 dnl Copyright (C) 2009-2020 Free Software Foundation, Inc.
@@ -8,6 +8,31 @@ dnl with or without modifications, as long as this notice is preserved.
 
 # Written by Eric Blake.
 
+AC_DEFUN([gl_FUNC_FACCESSAT_EOVERFLOW],
+[
+  AC_CHECK_FUNCS_ONCE([faccessat])
+  if test "$ac_cv_func_faccessat" = yes; then
+    AC_CACHE_CHECK([whether faccessat works when stat would EOVERFLOW],
+      [gl_cv_func_faccessat_never_eoverflows],
+      [AC_COMPILE_IFELSE(
+         [AC_LANG_PROGRAM([],
+            [[#ifdef __linux__
+               #include <linux/version.h>
+               #if (! (KERNEL_VERSION (5, 8, 0) <= LINUX_VERSION_CODE \
+                    && 2 < (__GLIBC__ + (33 <= __GLIBC_MINOR__))))
+                #error "faccessat might fail with EOVERFLOW"
+               #endif
+              #endif
+            ]])],
+         [gl_cv_func_faccessat_never_eoverflows=yes],
+         [gl_cv_func_faccessat_never_eoverflows=no])])
+    if test "$gl_cv_func_faccessat_never_eoverflows" = yes; then
+      AC_DEFINE([FACCESSAT_NEVER_EOVERFLOWS], 1,
+        [Define to 1 if faccessat is EOVERFLOW-free.])
+    fi
+  fi
+])
+
 AC_DEFUN([gl_FUNC_FACCESSAT],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
@@ -16,12 +41,14 @@ AC_DEFUN([gl_FUNC_FACCESSAT],
   dnl Persuade glibc <unistd.h> to declare faccessat().
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 
+  AC_REQUIRE([gl_FUNC_FACCESSAT_EOVERFLOW])
+
   AC_CHECK_FUNCS_ONCE([faccessat])
   if test $ac_cv_func_faccessat = no; then
     HAVE_FACCESSAT=0
   else
-    case "$gl_cv_func_lstat_dereferences_slashed_symlink" in
-      *yes) ;;
+    case $gl_cv_func_lstat_dereferences_slashed_symlink,$gl_cv_func_faccessat_never_eoverflows in
+      *yes,*yes) ;;
       *)    REPLACE_FACCESSAT=1 ;;
     esac
   fi