Add fix for incorrect mapping of fcntl64() -> fcntl(), causing locking failures
authorAndrew Bartlett <abartlet@samba.org>
Fri, 5 May 2023 01:34:00 +0000 (13:34 +1200)
committerAndreas Schneider <asn@samba.org>
Mon, 8 May 2023 10:34:59 +0000 (12:34 +0200)
We need to call fcntl64() if possible for 32-bit hosts

This is a strange case of socket_wrapper breaking normal file operation.

Newer glibc has introduced fcntl64 and symbol renaming but
the end function call was not caught by the automatic rename.

This means socket_wrapper would call fcntl(), not fcntl64 in libc
and this would do a "struct flock" -> "struct flock64" translation on the
supplied argument, despite this being already a flock64 from
the caller.

This in turn changed the lock offset values (eg to 0, 0).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15367

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
ConfigureChecks.cmake
src/socket_wrapper.c

index b820a65d2dd6f204466ed2cd82cb0ca5c6d50b92..c99e2ae9edea9d8441e4dd44bcb2ff094cc7e232 100644 (file)
@@ -80,6 +80,7 @@ check_function_exists(__close_nocancel HAVE___CLOSE_NOCANCEL)
 check_function_exists(recvmmsg HAVE_RECVMMSG)
 check_function_exists(sendmmsg HAVE_SENDMMSG)
 check_function_exists(syscall HAVE_SYSCALL)
+check_function_exists(fcntl64 HAVE_FCNTL64)
 
 if (UNIX)
     find_library(DLFCN_LIBRARY dl)
index bf4a976eaee7069ab4bade1c650ca3969d5bfd56..de2f73250595528a1f256b126c17144af6205ca3 100644 (file)
@@ -611,7 +611,11 @@ struct swrap_libc_symbols {
        SWRAP_SYMBOL_ENTRY(connect);
        SWRAP_SYMBOL_ENTRY(dup);
        SWRAP_SYMBOL_ENTRY(dup2);
+#ifdef HAVE_FCNTL64
+       SWRAP_SYMBOL_ENTRY(fcntl64);
+#else
        SWRAP_SYMBOL_ENTRY(fcntl);
+#endif
        SWRAP_SYMBOL_ENTRY(fopen);
 #ifdef HAVE_FOPEN64
        SWRAP_SYMBOL_ENTRY(fopen64);
@@ -978,7 +982,24 @@ static int libc_vfcntl(int fd, int cmd, va_list ap)
 
        arg = va_arg(ap, void *);
 
+       /*
+        * If fcntl64 exists then this is a system were fcntl is
+        * renamed (including when building this file), and so we must
+        * assume that the binary under test was built with
+        * -D_FILE_OFFSET_BITS=64 and pass on to fcntl64.
+        *
+        * If we are wrong, then fcntl is unwrapped, but while that is
+        * not ideal, is is also unlikely.
+        *
+        * In any case, it is always wrong to map fcntl64() to fcntl()
+        * as this will cause a thunk from struct flock -> flock64
+        * that the caller had already prepared for.
+        */
+#ifdef HAVE_FCNTL64
+       rc = swrap.libc.symbols._libc_fcntl64.f(fd, cmd, arg);
+#else
        rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
+#endif
 
        return rc;
 }
@@ -1400,7 +1421,11 @@ static void __swrap_bind_symbol_all_once(void)
        swrap_bind_symbol_libsocket(connect);
        swrap_bind_symbol_libc(dup);
        swrap_bind_symbol_libc(dup2);
+#ifdef HAVE_FCNTL64
+       swrap_bind_symbol_libc(fcntl64);
+#else
        swrap_bind_symbol_libc(fcntl);
+#endif
        swrap_bind_symbol_libc(fopen);
 #ifdef HAVE_FOPEN64
        swrap_bind_symbol_libc(fopen64);