Imported Upstream version 4.5.14
[platform/upstream/findutils.git] / lib / fdleak.c
1 /* fdleak.c -- detect file descriptor leaks
2    Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* config.h must be included first. */
18 #include <config.h>
19
20 /* system headers. */
21 #include <assert.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <poll.h>
25 #include <stdarg.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #if defined HAVE_SYS_RESOURCE_H
30 # include <sys/resource.h>
31 #endif
32 #include <unistd.h>
33
34 /* gnulib headers. */
35 #include "cloexec.h"
36 #include "dirent-safer.h"
37 #include "error.h"
38 #include "fcntl--.h"
39 #include "gettext.h"
40
41 /* find headers. */
42 #include "extendbuf.h"
43 #include "fdleak.h"
44 #include "safe-atoi.h"
45
46 #if ENABLE_NLS
47 # include <libintl.h>
48 # define _(Text) gettext (Text)
49 #else
50 # define _(Text) Text
51 #endif
52 #ifdef gettext_noop
53 # define N_(String) gettext_noop (String)
54 #else
55 /* See locate.c for explanation as to why not use (String) */
56 # define N_(String) String
57 #endif
58
59 /* In order to detect FD leaks, we take a snapshot of the open
60  * file descriptors which are not FD_CLOEXEC when the program starts.
61  * When the program exits, we discover if there are any new
62  * file descriptors which aren't FD_CLOEXEC.
63  */
64 static int *non_cloexec_fds;
65 static size_t num_cloexec_fds;
66
67
68 /* Determine the value of the largest open fd, on systems that
69  * offer /proc/self/fd. */
70 static int
71 get_proc_max_fd (void)
72 {
73   const char *path = "/proc/self/fd";
74   int maxfd = -1;
75   /* We don't use readdir_r, because we cannot trust pathconf
76    * to tell us the maximum possible length of a path in
77    * a given directory (the manpage for readdir_r claims this
78    * is the approved method, but the manpage for pathconf indicates
79    * that _PC_NAME_MAX is not an upper limit). */
80   DIR *dir = opendir_safer (path);
81   if (dir)
82     {
83       int good = 0;
84       struct dirent *dent;
85
86       while ((dent=readdir (dir)) != NULL)
87         {
88           if (dent->d_name[0] != '.'
89               || (dent->d_name[0] != 0
90                   && dent->d_name[1] != 0 && dent->d_name[1] != '.'))
91             {
92               const int fd = safe_atoi (dent->d_name, literal_quoting_style);
93               if (fd > maxfd)
94                 maxfd = fd;
95               good = 1;
96             }
97         }
98       closedir (dir);
99       if (good)
100         return maxfd;
101     }
102   return -1;
103 }
104
105
106
107 /* Estimate the value of the largest possible file descriptor */
108 static int
109 get_max_fd (void)
110 {
111   struct rlimit fd_limit;
112   long open_max;
113
114   open_max = get_proc_max_fd ();
115   if (open_max >= 0)
116     return open_max;
117
118   open_max = sysconf (_SC_OPEN_MAX);
119   if (open_max == -1)
120     open_max = _POSIX_OPEN_MAX; /* underestimate */
121
122   /* We assume if RLIMIT_NOFILE is defined, all the related macros are, too. */
123 #if defined HAVE_GETRUSAGE && defined RLIMIT_NOFILE
124   if (0 == getrlimit (RLIMIT_NOFILE, &fd_limit))
125     {
126       if (fd_limit.rlim_cur == RLIM_INFINITY)
127         return open_max;
128       else
129         return (int) fd_limit.rlim_cur;
130     }
131 #endif
132   /* cannot determine the limit's value */
133   return open_max;
134 }
135
136
137 static int
138 visit_open_fds (int fd_min, int fd_max,
139                 int (*callback)(int, void*), void *cb_context)
140 {
141   enum { MAX_POLL = 64 };
142   struct pollfd pf[MAX_POLL];
143   int rv = 0;
144
145   while (fd_min < fd_max)
146     {
147       int i;
148       int limit = fd_max - fd_min;
149       if (limit > MAX_POLL)
150         limit = MAX_POLL;
151
152       for (i=0; i<limit; i++)
153         {
154           pf[i].events = POLLIN|POLLOUT;
155           pf[i].revents = 0;
156           pf[i].fd = fd_min + i;
157         }
158       rv = poll (pf, limit, 0);
159       if (-1 == rv)
160         {
161           return -1;
162         }
163       else
164         {
165           int j;
166           for (j=0; j<limit; j++)
167             {
168               if (pf[j].revents != POLLNVAL)
169                 {
170                   if (0 != (rv = callback (pf[j].fd, cb_context)))
171                     return rv;
172                 }
173             }
174         }
175       fd_min += limit;
176     }
177   return 0;
178 }
179
180 static int
181 fd_is_cloexec (int fd)
182 {
183   const int flags = fcntl (fd, F_GETFD);
184   return flags & FD_CLOEXEC;
185 }
186
187
188 /* Faking closures in C is a bit of a pain.  */
189 struct remember_fd_context
190 {
191   int *buf;
192   size_t used;
193   size_t allocated;
194 };
195
196
197 /* Record FD is it's not FD_CLOEXEC. */
198 static int
199 remember_fd_if_non_cloexec (int fd, void *context)
200 {
201   if (fd_is_cloexec (fd))
202     {
203       return 0;
204     }
205   else
206     {
207       struct remember_fd_context * const p = context;
208       void *newbuf = extendbuf (p->buf,
209                                 sizeof (p->buf[0])*(p->used+1),
210                                 &(p->allocated));
211       if (newbuf)
212         {
213           p->buf = newbuf;
214           p->buf[p->used] = fd;
215           ++p->used;
216           return 0;
217         }
218       else
219         {
220           return -1;
221         }
222     }
223 }
224
225 void
226 remember_non_cloexec_fds (void)
227 {
228   int max_fd = get_max_fd ();
229   struct remember_fd_context cb_data;
230   cb_data.buf = NULL;
231   cb_data.used = cb_data.allocated = 0;
232
233   if (max_fd < INT_MAX)
234     ++max_fd;
235   visit_open_fds (0, max_fd, remember_fd_if_non_cloexec, &cb_data);
236
237   non_cloexec_fds = cb_data.buf;
238   num_cloexec_fds = cb_data.used;
239 }
240
241
242 struct fd_leak_context
243 {
244   const int *prev_buf;
245   size_t used;
246   size_t lookup_pos;
247   int leaked_fd;
248 };
249
250 /* FD is open and not close-on-exec.
251  * If it's not in the list of non-cloexec file descriptors we saw before, it's a leak.
252  */
253 static int
254 find_first_leak_callback (int fd, void *context)
255 {
256   if (!fd_is_cloexec (fd))
257     {
258       struct fd_leak_context *p = context;
259       while (p->lookup_pos < p->used)
260         {
261           if (p->prev_buf[p->lookup_pos] < fd)
262             {
263               ++p->lookup_pos;
264             }
265           else if (p->prev_buf[p->lookup_pos] == fd)
266             {
267               /* FD was open and still is, it's not a leak. */
268               return 0;
269             }
270           else
271             {
272               break;
273             }
274         }
275       /* We come here if p->prev_buf[p->lookup_pos] > fd, or
276          if we ran out of items in the lookup table.
277          Either way, this is a leak. */
278       p->leaked_fd = fd;
279       return -1;                /* No more callbacks needed. */
280     }
281   return 0;
282 }
283
284
285 static int
286 find_first_leaked_fd (const int* prev_non_cloexec_fds, size_t n)
287 {
288   struct fd_leak_context context;
289   int max_fd = get_max_fd ();
290
291   if (max_fd < INT_MAX)
292     ++max_fd;
293   context.prev_buf = prev_non_cloexec_fds;
294   context.used = n;
295   context.lookup_pos = 0;
296   context.leaked_fd = -1;
297   visit_open_fds (0, max_fd, find_first_leak_callback, &context);
298   return context.leaked_fd;
299 }
300
301 /* Determine if O_CLOEXEC actually works (Savannah bug #29435:
302    fd_is_cloexec () does not work on Fedora buildhosts).
303  */
304 static bool
305 o_cloexec_works (void)
306 {
307   bool result = false;
308   int fd = open ("/", O_RDONLY|O_CLOEXEC);
309   if (fd >= 0)
310     {
311       result = fd_is_cloexec (fd);
312       close (fd);
313     }
314   return result;
315 }
316
317
318 int
319 open_cloexec (const char *path, int flags, ...)
320 {
321   int fd;
322   mode_t mode = 0;
323   static bool cloexec_works = false;
324   static bool cloexec_status_known = false;
325
326   if (flags & O_CREAT)
327     {
328       /* this code is copied from gnulib's open-safer.c. */
329       va_list ap;
330       va_start (ap, flags);
331
332       /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4
333          creates crashing code when 'mode_t' is smaller than 'int'.  */
334       mode = va_arg (ap, PROMOTED_MODE_T);
335
336       va_end (ap);
337     }
338
339   /* Kernels usually ignore open flags they don't recognise, so it
340    * is possible this program was built against a library which
341    * defines O_CLOEXEC, but is running on a kernel that (silently)
342    * does not recognise it.   We figure this out by just trying it,
343    * once.
344    */
345   if (!cloexec_status_known)
346     {
347       cloexec_works = o_cloexec_works ();
348       cloexec_status_known = true;
349     }
350   fd = open (path, flags|O_CLOEXEC, mode);
351   if ((fd >= 0) && !(O_CLOEXEC && cloexec_works))
352     {
353       set_cloexec_flag (fd, true);
354     }
355   return fd;
356 }
357
358 void
359 forget_non_cloexec_fds (void)
360 {
361   free (non_cloexec_fds);
362   non_cloexec_fds = NULL;
363   num_cloexec_fds = 0;
364 }
365
366
367 void
368 complain_about_leaky_fds (void)
369 {
370   int no_leaks = 1;
371   const int leaking_fd = find_first_leaked_fd (non_cloexec_fds, num_cloexec_fds);
372
373   if (leaking_fd >= 0)
374     {
375       no_leaks = 0;
376       error (0, 0,
377              _("File descriptor %d will leak; please report this as a bug, "
378                "remembering to include a detailed description of the simplest "
379                "way to reproduce this problem."),
380              leaking_fd);
381     }
382   assert (no_leaks);
383 }