swrap: Provide a fcntl64()
authorAndreas Schneider <asn@samba.org>
Fri, 23 Jun 2023 09:10:45 +0000 (11:10 +0200)
committerAndreas Schneider <asn@samba.org>
Thu, 29 Jun 2023 09:22:38 +0000 (11:22 +0200)
We want to run with and without large file support. It depends on if the
application is build with large file support so it will either choose fcntl or
fcntl64.

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
src/socket_wrapper.c

index aa559b84fd76f37a9b4cab4603b626e1df4d8ad7..c759d350fb1816bd1c7de26adac7fd034d01476e 100644 (file)
@@ -627,10 +627,9 @@ struct swrap_libc_symbols {
        SWRAP_SYMBOL_ENTRY(connect);
        SWRAP_SYMBOL_ENTRY(dup);
        SWRAP_SYMBOL_ENTRY(dup2);
+       SWRAP_SYMBOL_ENTRY(fcntl);
 #ifdef HAVE_FCNTL64
        SWRAP_SYMBOL_ENTRY(fcntl64);
-#else
-       SWRAP_SYMBOL_ENTRY(fcntl);
 #endif
        SWRAP_SYMBOL_ENTRY(fopen);
 #ifdef HAVE_FOPEN64
@@ -1001,27 +1000,27 @@ 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.
-        */
+       rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
+
+       return rc;
+}
+
 #ifdef HAVE_FCNTL64
+DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+static int libc_vfcntl64(int fd, int cmd, va_list ap)
+{
+       void *arg;
+       int rc;
+
+       swrap_bind_symbol_all();
+
+       arg = va_arg(ap, void *);
+
        rc = swrap.libc.symbols._libc_fcntl64.f(fd, cmd, arg);
-#else
-       rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
-#endif
 
        return rc;
 }
+#endif
 
 static int libc_getpeername(int sockfd,
                            struct sockaddr *addr,
@@ -1463,10 +1462,9 @@ static void __swrap_bind_symbol_all_once(void)
        swrap_bind_symbol_libsocket(connect);
        swrap_bind_symbol_libc(dup);
        swrap_bind_symbol_libc(dup2);
+       swrap_bind_symbol_libc(fcntl);
 #ifdef HAVE_FCNTL64
        swrap_bind_symbol_libc(fcntl64);
-#else
-       swrap_bind_symbol_libc(fcntl);
 #endif
        swrap_bind_symbol_libc(fopen);
 #ifdef HAVE_FOPEN64
@@ -8536,6 +8534,80 @@ int fcntl(int fd, int cmd, ...)
        return rc;
 }
 
+/****************************
+ * FCNTL64
+ ***************************/
+
+#ifdef HAVE_FCNTL64
+static int swrap_vfcntl64(int fd, int cmd, va_list va)
+{
+       struct socket_info *si;
+       int rc, dup_fd, idx;
+
+       idx = find_socket_info_index(fd);
+       if (idx == -1) {
+               return libc_vfcntl64(fd, cmd, va);
+       }
+
+       si = swrap_get_socket_info(idx);
+
+       switch (cmd) {
+       case F_DUPFD:
+               dup_fd = libc_vfcntl64(fd, cmd, va);
+               if (dup_fd == -1) {
+                       int saved_errno = errno;
+                       errno = saved_errno;
+                       return -1;
+               }
+
+               /* Make sure we don't have an entry for the fd */
+               swrap_remove_stale(dup_fd);
+
+               if ((size_t)dup_fd >= socket_fds_max) {
+                       SWRAP_LOG(SWRAP_LOG_ERROR,
+                         "The max socket index limit of %zu has been reached, "
+                         "trying to add %d",
+                         socket_fds_max,
+                         dup_fd);
+                       libc_close(dup_fd);
+                       errno = EMFILE;
+                       return -1;
+               }
+
+               SWRAP_LOCK_SI(si);
+
+               swrap_inc_refcount(si);
+
+               SWRAP_UNLOCK_SI(si);
+
+
+               set_socket_info_index(dup_fd, idx);
+
+               rc = dup_fd;
+               break;
+       default:
+               rc = libc_vfcntl64(fd, cmd, va);
+               break;
+       }
+
+       return rc;
+}
+
+int fcntl64(int fd, int cmd, ...)
+{
+       va_list va;
+       int rc;
+
+       va_start(va, cmd);
+
+       rc = swrap_vfcntl64(fd, cmd, va);
+
+       va_end(va);
+
+       return rc;
+}
+#endif
+
 /****************************
  * EVENTFD
  ***************************/