ust-fd: Add close_range declaration
[lttng-ust.git] / src / lib / lttng-ust-fd / lttng-ust-fd.c
... / ...
CommitLineData
1/*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 */
6
7#define _LGPL_SOURCE
8#include <limits.h>
9#include <stdio.h>
10#include <sys/types.h>
11#include <unistd.h>
12#include <dlfcn.h>
13#include <errno.h>
14
15#include <lttng/ust-common.h>
16
17#include "common/macros.h"
18#include "common/ust-fd.h"
19
20#define LTTNG_UST_DLSYM_FAILED_PTR 0x1
21
22static int (*__lttng_ust_fd_plibc_close)(int fd) = NULL;
23static int (*__lttng_ust_fd_plibc_fclose)(FILE *stream) = NULL;
24static int (*__lttng_ust_fd_plibc_close_range)(unsigned int first,
25 unsigned int last, int flags) = NULL;
26
27/*
28 * Use dlsym to find the original libc close() symbol and store it in
29 * __lttng_ust_fd_plibc_close.
30 */
31static
32void *_lttng_ust_fd_init_plibc_close(void)
33{
34 if (__lttng_ust_fd_plibc_close == NULL) {
35 __lttng_ust_fd_plibc_close = dlsym(RTLD_NEXT, "close");
36
37 if (__lttng_ust_fd_plibc_close == NULL) {
38 __lttng_ust_fd_plibc_close = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
39 fprintf(stderr, "%s\n", dlerror());
40 }
41 }
42
43 return __lttng_ust_fd_plibc_close;
44}
45
46/*
47 * Use dlsym to find the original libc fclose() symbol and store it in
48 * __lttng_ust_fd_plibc_fclose.
49 */
50static
51void *_lttng_ust_fd_init_plibc_fclose(void)
52{
53 if (__lttng_ust_fd_plibc_fclose == NULL) {
54 __lttng_ust_fd_plibc_fclose = dlsym(RTLD_NEXT, "fclose");
55
56 if (__lttng_ust_fd_plibc_fclose == NULL) {
57 __lttng_ust_fd_plibc_fclose = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
58 fprintf(stderr, "%s\n", dlerror());
59 }
60 }
61
62 return __lttng_ust_fd_plibc_fclose;
63}
64
65/*
66 * Use dlsym to find the original libc close_range() symbol and store it
67 * in __lttng_ust_fd_plibc_close_range. The close_range symbol only
68 * appears in glibc 2.34, so it is considered optional.
69 */
70static
71void *_lttng_ust_fd_init_plibc_close_range(void)
72{
73 if (__lttng_ust_fd_plibc_close_range == NULL) {
74 __lttng_ust_fd_plibc_close_range = dlsym(RTLD_NEXT, "close_range");
75
76 if (__lttng_ust_fd_plibc_close_range == NULL)
77 __lttng_ust_fd_plibc_close_range = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
78 }
79
80 return __lttng_ust_fd_plibc_close_range;
81}
82
83static
84void _lttng_ust_fd_ctor(void)
85 __attribute__((constructor));
86static
87void _lttng_ust_fd_ctor(void)
88{
89 lttng_ust_common_ctor();
90
91 /*
92 * Initialize the function pointers to the original libc symbols in the
93 * constructor since close() has to stay async-signal-safe and as such,
94 * we can't call dlsym() in the override functions.
95 */
96 (void) _lttng_ust_fd_init_plibc_close();
97 (void) _lttng_ust_fd_init_plibc_fclose();
98 (void) _lttng_ust_fd_init_plibc_close_range();
99}
100
101/*
102 * Override the libc close() symbol with our own, allowing applications to
103 * close arbitrary file descriptors. If the fd is owned by lttng-ust, return
104 * -1, errno=EBADF instead of closing it.
105 *
106 * If dlsym failed to find the original libc close() symbol, return -1,
107 * errno=ENOSYS.
108 *
109 * There is a short window before the library constructor has executed where
110 * this wrapper could call dlsym() and thus not be async-signal-safe.
111 */
112int close(int fd)
113{
114 /*
115 * We can't retry dlsym here since close is async-signal-safe.
116 */
117 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
118 errno = ENOSYS;
119 return -1;
120 }
121
122 return lttng_ust_safe_close_fd(fd, __lttng_ust_fd_plibc_close);
123}
124
125/*
126 * Override the libc fclose() symbol with our own, allowing applications to
127 * close arbitrary streams. If the fd is owned by lttng-ust, return -1,
128 * errno=EBADF instead of closing it.
129 *
130 * If dlsym failed to find the original libc close() symbol, return -1,
131 * errno=ENOSYS.
132 *
133 * There is a short window before the library constructor has executed where
134 * this wrapper could call dlsym() and thus not be async-signal-safe.
135 *
136 * Note: fcloseall() is not an issue because it closes only the streams it
137 * knows about, which differs from the problems caused by gnulib
138 * close_stdout(), which does an explicit fclose(stdout).
139 */
140int fclose(FILE *stream)
141{
142 if (_lttng_ust_fd_init_plibc_fclose() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
143 errno = ENOSYS;
144 return -1;
145 }
146
147 return lttng_ust_safe_fclose_stream(stream,
148 __lttng_ust_fd_plibc_fclose);
149}
150
151/* Old libc headers don't contain a close_range() declaration. */
152int close_range(unsigned int first, unsigned int last, int flags);
153
154/*
155 * Override the libc close_range() symbol with our own, allowing
156 * applications to close arbitrary file descriptors. If the fd is owned
157 * by lttng-ust, return -1, errno=EBADF instead of closing it.
158 *
159 * If dlsym failed to find the original libc close_range() symbol,
160 * return -1, errno=ENOSYS.
161 *
162 * There is a short window before the library constructor has executed where
163 * this wrapper could call dlsym() and thus not be async-signal-safe.
164 */
165int close_range(unsigned int first, unsigned int last, int flags)
166{
167 /*
168 * We can't retry dlsym here since close is async-signal-safe.
169 */
170 if (_lttng_ust_fd_init_plibc_close_range() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
171 errno = ENOSYS;
172 return -1;
173 }
174
175 return lttng_ust_safe_close_range_fd(first, last, flags, __lttng_ust_fd_plibc_close_range);
176}
177
178#if defined(__sun__) || defined(__FreeBSD__)
179/* Solaris and FreeBSD. */
180void closefrom(int lowfd)
181{
182 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
183 return;
184 }
185
186 (void) lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
187}
188#elif defined(__NetBSD__) || defined(__OpenBSD__)
189/* NetBSD and OpenBSD. */
190int closefrom(int lowfd)
191{
192 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
193 errno = ENOSYS;
194 return -1;
195 }
196
197 return lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
198}
199#else
200/* As far as we know, this OS does not implement closefrom. */
201#endif
This page took 0.025626 seconds and 5 git commands to generate.