Fix: liblttng-ust-fd.so: override fclose symbol
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 7 Nov 2017 20:33:40 +0000 (15:33 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 7 Nov 2017 23:04:23 +0000 (18:04 -0500)
fclose() invoked from application or libraries end up calling close()
from within the libc, which bypasses our file descriptor tracking.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/ust-fd.h
liblttng-ust-comm/lttng-ust-fd-tracker.c
liblttng-ust-fd/lttng-ust-fd.c

index 7cbcf47c8ba0ebb0a4a41262535b85fcd3699d95..032cac538412d620b379cd77bfcaf6f76ea06885 100644 (file)
@@ -24,6 +24,8 @@
  * These declarations should NOT be considered stable API.
  */
 
+#include <stdio.h>
+
 void lttng_ust_init_fd_tracker(void);
 void lttng_ust_add_fd_to_tracker(int fd);
 void lttng_ust_delete_fd_from_tracker(int fd);
@@ -31,6 +33,7 @@ void lttng_ust_lock_fd_tracker(void);
 void lttng_ust_unlock_fd_tracker(void);
 
 int lttng_ust_safe_close_fd(int fd, int (*close_cb)(int));
+int lttng_ust_safe_fclose_stream(FILE *stream, int (*fclose_cb)(FILE *stream));
 int lttng_ust_safe_closefrom_fd(int lowfd, int (*close_cb)(int));
 
 #endif /* _LTTNG_UST_FD_H */
index 5a763ff2960550c094306d9d7d90de3d2bf9d037..d56288e370470e1deb94a25dc5603048c75f03aa 100644 (file)
@@ -197,6 +197,38 @@ int lttng_ust_safe_close_fd(int fd, int (*close_cb)(int fd))
        return ret;
 }
 
+/*
+ * Interface allowing applications to close arbitrary streams.
+ * We check if it is owned by lttng-ust, and return -1, errno=EBADF
+ * instead of closing it if it is the case.
+ */
+int lttng_ust_safe_fclose_stream(FILE *stream, int (*fclose_cb)(FILE *stream))
+{
+       int ret = 0, fd;
+
+       lttng_ust_fixup_fd_tracker_tls();
+
+       /*
+        * If called from lttng-ust, we directly call fclose without
+        * validating whether the FD is part of the tracked set.
+        */
+       if (URCU_TLS(thread_fd_tracking))
+               return fclose_cb(stream);
+
+       fd = fileno(stream);
+
+       lttng_ust_lock_fd_tracker();
+       if (IS_FD_VALID(fd) && IS_FD_SET(fd, lttng_fd_set)) {
+               ret = -1;
+               errno = EBADF;
+       } else {
+               ret = fclose_cb(stream);
+       }
+       lttng_ust_unlock_fd_tracker();
+
+       return ret;
+}
+
 #ifdef __OpenBSD__
 static void set_close_success(int *p)
 {
index 6a095db60803e1cd45f50dce805faaba4d915716..863f0618adefd605ede54dbf1b2cb4981c7338f4 100644 (file)
@@ -31,6 +31,7 @@
 volatile enum ust_loglevel ust_loglevel;
 
 static int (*__lttng_ust_fd_plibc_close)(int fd);
+static int (*__lttng_ust_fd_plibc_fclose)(FILE *stream);
 
 static
 int _lttng_ust_fd_libc_close(int fd)
@@ -45,11 +46,35 @@ int _lttng_ust_fd_libc_close(int fd)
        return lttng_ust_safe_close_fd(fd, __lttng_ust_fd_plibc_close);
 }
 
+static
+int _lttng_ust_fd_libc_fclose(FILE *stream)
+{
+       if (!__lttng_ust_fd_plibc_fclose) {
+               __lttng_ust_fd_plibc_fclose = dlsym(RTLD_NEXT, "fclose");
+               if (!__lttng_ust_fd_plibc_fclose) {
+                       fprintf(stderr, "%s\n", dlerror());
+                       return -1;
+               }
+       }
+       return lttng_ust_safe_fclose_stream(stream,
+                       __lttng_ust_fd_plibc_fclose);
+}
+
 int close(int fd)
 {
        return _lttng_ust_fd_libc_close(fd);
 }
 
+/*
+ * Note: fcloseall() is not an issue because it fcloses only the
+ * streams it knows about, which differs from the problems caused by
+ * gnulib close_stdout(), which does an explicit fclose(stdout).
+ */
+int fclose(FILE *stream)
+{
+       return _lttng_ust_fd_libc_fclose(stream);
+}
+
 #if defined(__sun__) || defined(__FreeBSD__)
 /* Solaris and FreeBSD. */
 void closefrom(int lowfd)
This page took 0.026391 seconds and 4 git commands to generate.