Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright 2000-2022 Red Hat, Inc.
3 : : * Copyright 2006-2007 Matthias Clasen
4 : : * Copyright 2006 Padraig O'Briain
5 : : * Copyright 2007 Lennart Poettering
6 : : * Copyright 2018-2022 Endless OS Foundation, LLC
7 : : * Copyright 2018 Peter Wu
8 : : * Copyright 2019 Ting-Wei Lan
9 : : * Copyright 2019 Sebastian Schwarz
10 : : * Copyright 2020 Matt Rose
11 : : * Copyright 2021 Casper Dik
12 : : * Copyright 2022 Alexander Richardson
13 : : * Copyright 2022 Ray Strode
14 : : * Copyright 2022 Thomas Haller
15 : : * Copyright 2023-2024 Collabora Ltd.
16 : : * Copyright 2023 Sebastian Wilhelmi
17 : : * Copyright 2023 CaiJingLong
18 : : *
19 : : * glib-unix.c: UNIX specific API wrappers and convenience functions
20 : : *
21 : : * SPDX-License-Identifier: LGPL-2.1-or-later
22 : : *
23 : : * This library is free software; you can redistribute it and/or
24 : : * modify it under the terms of the GNU Lesser General Public
25 : : * License as published by the Free Software Foundation; either
26 : : * version 2.1 of the License, or (at your option) any later version.
27 : : *
28 : : * This library is distributed in the hope that it will be useful,
29 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 : : * Lesser General Public License for more details.
32 : : *
33 : : * You should have received a copy of the GNU Lesser General Public
34 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
35 : : *
36 : : * Authors: Colin Walters <walters@verbum.org>
37 : : */
38 : :
39 : : #include "config.h"
40 : :
41 : : #include "glib-private.h"
42 : : #include "glib-unix.h"
43 : : #include "glib-unixprivate.h"
44 : : #include "gmain-internal.h"
45 : :
46 : : #include <dirent.h>
47 : : #include <errno.h>
48 : : #include <fcntl.h>
49 : : #include <stdlib.h> /* for fdwalk */
50 : : #include <string.h>
51 : : #include <sys/types.h>
52 : : #include <pwd.h>
53 : : #include <unistd.h>
54 : :
55 : : #if defined(__linux__) || defined(__DragonFly__)
56 : : #include <sys/syscall.h> /* for syscall and SYS_getdents64 */
57 : : #endif
58 : :
59 : : #ifdef HAVE_SYS_RESOURCE_H
60 : : #include <sys/resource.h>
61 : : #endif /* HAVE_SYS_RESOURCE_H */
62 : :
63 : : #if defined(__APPLE__) && defined(HAVE_LIBPROC_H)
64 : : #include <libproc.h>
65 : : #include <sys/proc_info.h>
66 : : #endif
67 : :
68 : : G_STATIC_ASSERT (sizeof (ssize_t) == GLIB_SIZEOF_SSIZE_T);
69 : : G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (ssize_t));
70 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (ssize_t) == 1);
71 : :
72 : : G_STATIC_ASSERT (sizeof (GPid) == sizeof (pid_t));
73 : : G_STATIC_ASSERT (G_ALIGNOF (GPid) == G_ALIGNOF (pid_t));
74 : : /* It's platform-dependent whether pid_t is signed, so no assertion */
75 : :
76 : : /* If this assertion fails, then the ABI of g_unix_open_pipe() would be
77 : : * ambiguous on this platform.
78 : : * On Linux, usually O_NONBLOCK == 04000 and FD_CLOEXEC == 1, but the same
79 : : * might not be true everywhere. */
80 : : G_STATIC_ASSERT (O_NONBLOCK != FD_CLOEXEC);
81 : :
82 : 7 : G_DEFINE_QUARK (g-unix-error-quark, g_unix_error)
83 : :
84 : : static gboolean
85 : 3 : g_unix_set_error_from_errno (GError **error,
86 : : gint saved_errno)
87 : : {
88 : 3 : g_set_error_literal (error,
89 : : G_UNIX_ERROR,
90 : : 0,
91 : : g_strerror (saved_errno));
92 : 3 : errno = saved_errno;
93 : 3 : return FALSE;
94 : : }
95 : :
96 : : /**
97 : : * g_unix_open_pipe:
98 : : * @fds: (array fixed-size=2): Array of two integers
99 : : * @flags: Bitfield of file descriptor flags, as for fcntl()
100 : : * @error: a #GError
101 : : *
102 : : * Similar to the UNIX pipe() call, but on modern systems like Linux
103 : : * uses the pipe2() system call, which atomically creates a pipe with
104 : : * the configured flags.
105 : : *
106 : : * As of GLib 2.78, the supported flags are `O_CLOEXEC`/`FD_CLOEXEC` (see below)
107 : : * and `O_NONBLOCK`. Prior to GLib 2.78, only `FD_CLOEXEC` was supported — if
108 : : * you wanted to configure `O_NONBLOCK` then that had to be done separately with
109 : : * `fcntl()`.
110 : : *
111 : : * Since GLib 2.80, the constants %G_UNIX_PIPE_END_READ and
112 : : * %G_UNIX_PIPE_END_WRITE can be used as mnemonic indexes in @fds.
113 : : *
114 : : * It is a programmer error to call this function with unsupported flags, and a
115 : : * critical warning will be raised.
116 : : *
117 : : * As of GLib 2.78, it is preferred to pass `O_CLOEXEC` in, rather than
118 : : * `FD_CLOEXEC`, as that matches the underlying `pipe()` API more closely. Prior
119 : : * to 2.78, only `FD_CLOEXEC` was supported. Support for `FD_CLOEXEC` may be
120 : : * deprecated and removed in future.
121 : : *
122 : : * Returns: %TRUE on success, %FALSE if not (and errno will be set).
123 : : *
124 : : * Since: 2.30
125 : : */
126 : : gboolean
127 : 2870 : g_unix_open_pipe (int *fds,
128 : : int flags,
129 : : GError **error)
130 : : {
131 : : /* We only support O_CLOEXEC/FD_CLOEXEC and O_NONBLOCK */
132 : 2870 : g_return_val_if_fail ((flags & (O_CLOEXEC | FD_CLOEXEC | O_NONBLOCK)) == flags, FALSE);
133 : :
134 : : #if O_CLOEXEC != FD_CLOEXEC && !defined(G_DISABLE_CHECKS)
135 : 2870 : if (flags & FD_CLOEXEC)
136 : 1 : g_debug ("g_unix_open_pipe() called with FD_CLOEXEC; please migrate to using O_CLOEXEC instead");
137 : : #endif
138 : :
139 : 2870 : if (!g_unix_open_pipe_internal (fds,
140 : 2870 : (flags & (O_CLOEXEC | FD_CLOEXEC)) != 0,
141 : 2870 : (flags & O_NONBLOCK) != 0))
142 : 0 : return g_unix_set_error_from_errno (error, errno);
143 : :
144 : 2870 : return TRUE;
145 : : }
146 : :
147 : : /**
148 : : * g_unix_set_fd_nonblocking:
149 : : * @fd: A file descriptor
150 : : * @nonblock: If %TRUE, set the descriptor to be non-blocking
151 : : * @error: a #GError
152 : : *
153 : : * Control the non-blocking state of the given file descriptor,
154 : : * according to @nonblock. On most systems this uses %O_NONBLOCK, but
155 : : * on some older ones may use %O_NDELAY.
156 : : *
157 : : * Returns: %TRUE if successful
158 : : *
159 : : * Since: 2.30
160 : : */
161 : : gboolean
162 : 499 : g_unix_set_fd_nonblocking (gint fd,
163 : : gboolean nonblock,
164 : : GError **error)
165 : : {
166 : : #ifdef F_GETFL
167 : : glong fcntl_flags;
168 : 499 : fcntl_flags = fcntl (fd, F_GETFL);
169 : :
170 : 499 : if (fcntl_flags == -1)
171 : 1 : return g_unix_set_error_from_errno (error, errno);
172 : :
173 : 498 : if (nonblock)
174 : 497 : fcntl_flags |= O_NONBLOCK;
175 : : else
176 : 1 : fcntl_flags &= ~O_NONBLOCK;
177 : :
178 : 498 : if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
179 : 0 : return g_unix_set_error_from_errno (error, errno);
180 : 498 : return TRUE;
181 : : #else
182 : : return g_unix_set_error_from_errno (error, EINVAL);
183 : : #endif
184 : : }
185 : :
186 : : /**
187 : : * g_unix_signal_source_new:
188 : : * @signum: A signal number
189 : : *
190 : : * Create a #GSource that will be dispatched upon delivery of the UNIX
191 : : * signal @signum. In GLib versions before 2.36, only `SIGHUP`, `SIGINT`,
192 : : * `SIGTERM` can be monitored. In GLib 2.36, `SIGUSR1` and `SIGUSR2`
193 : : * were added. In GLib 2.54, `SIGWINCH` was added.
194 : : *
195 : : * Note that unlike the UNIX default, all sources which have created a
196 : : * watch will be dispatched, regardless of which underlying thread
197 : : * invoked g_unix_signal_source_new().
198 : : *
199 : : * For example, an effective use of this function is to handle `SIGTERM`
200 : : * cleanly; flushing any outstanding files, and then calling
201 : : * g_main_loop_quit(). It is not safe to do any of this from a regular
202 : : * UNIX signal handler; such a handler may be invoked while malloc() or
203 : : * another library function is running, causing reentrancy issues if the
204 : : * handler attempts to use those functions. None of the GLib/GObject
205 : : * API is safe against this kind of reentrancy.
206 : : *
207 : : * The interaction of this source when combined with native UNIX
208 : : * functions like sigprocmask() is not defined.
209 : : *
210 : : * The source will not initially be associated with any #GMainContext
211 : : * and must be added to one with g_source_attach() before it will be
212 : : * executed.
213 : : *
214 : : * Returns: A newly created #GSource
215 : : *
216 : : * Since: 2.30
217 : : */
218 : : GSource *
219 : 32 : g_unix_signal_source_new (int signum)
220 : : {
221 : 32 : g_return_val_if_fail (signum == SIGHUP || signum == SIGINT || signum == SIGTERM ||
222 : : signum == SIGUSR1 || signum == SIGUSR2 || signum == SIGWINCH,
223 : : NULL);
224 : :
225 : 32 : return _g_main_create_unix_signal_watch (signum);
226 : : }
227 : :
228 : : /**
229 : : * g_unix_signal_add_full: (rename-to g_unix_signal_add)
230 : : * @priority: the priority of the signal source. Typically this will be in
231 : : * the range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
232 : : * @signum: Signal number
233 : : * @handler: Callback
234 : : * @user_data: Data for @handler
235 : : * @notify: #GDestroyNotify for @handler
236 : : *
237 : : * A convenience function for g_unix_signal_source_new(), which
238 : : * attaches to the default #GMainContext. You can remove the watch
239 : : * using g_source_remove().
240 : : *
241 : : * Returns: An ID (greater than 0) for the event source
242 : : *
243 : : * Since: 2.30
244 : : */
245 : : guint
246 : 29 : g_unix_signal_add_full (int priority,
247 : : int signum,
248 : : GSourceFunc handler,
249 : : gpointer user_data,
250 : : GDestroyNotify notify)
251 : : {
252 : : guint id;
253 : : GSource *source;
254 : :
255 : 29 : source = g_unix_signal_source_new (signum);
256 : :
257 : 29 : if (priority != G_PRIORITY_DEFAULT)
258 : 0 : g_source_set_priority (source, priority);
259 : :
260 : 29 : g_source_set_callback (source, handler, user_data, notify);
261 : 29 : id = g_source_attach (source, NULL);
262 : 29 : g_source_unref (source);
263 : :
264 : 29 : return id;
265 : : }
266 : :
267 : : /**
268 : : * g_unix_signal_add:
269 : : * @signum: Signal number
270 : : * @handler: Callback
271 : : * @user_data: Data for @handler
272 : : *
273 : : * A convenience function for g_unix_signal_source_new(), which
274 : : * attaches to the default #GMainContext. You can remove the watch
275 : : * using g_source_remove().
276 : : *
277 : : * Returns: An ID (greater than 0) for the event source
278 : : *
279 : : * Since: 2.30
280 : : */
281 : : guint
282 : 29 : g_unix_signal_add (int signum,
283 : : GSourceFunc handler,
284 : : gpointer user_data)
285 : : {
286 : 29 : return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL);
287 : : }
288 : :
289 : : typedef struct
290 : : {
291 : : GSource source;
292 : :
293 : : gint fd;
294 : : gpointer tag;
295 : : } GUnixFDSource;
296 : :
297 : : static gboolean
298 : 262659 : g_unix_fd_source_dispatch (GSource *source,
299 : : GSourceFunc callback,
300 : : gpointer user_data)
301 : : {
302 : 262659 : GUnixFDSource *fd_source = (GUnixFDSource *) source;
303 : 262659 : GUnixFDSourceFunc func = (GUnixFDSourceFunc) callback;
304 : :
305 : 262659 : if (!callback)
306 : : {
307 : 1 : g_warning ("GUnixFDSource dispatched without callback. "
308 : : "You must call g_source_set_callback().");
309 : 1 : return FALSE;
310 : : }
311 : :
312 : 262658 : return (* func) (fd_source->fd, g_source_query_unix_fd (source, fd_source->tag), user_data);
313 : : }
314 : :
315 : : GSourceFuncs g_unix_fd_source_funcs = {
316 : : NULL, NULL, g_unix_fd_source_dispatch, NULL, NULL, NULL
317 : : };
318 : :
319 : : /**
320 : : * g_unix_fd_source_new:
321 : : * @fd: a file descriptor
322 : : * @condition: I/O conditions to watch for on @fd
323 : : *
324 : : * Creates a #GSource to watch for a particular I/O condition on a file
325 : : * descriptor.
326 : : *
327 : : * The source will never close the @fd — you must do it yourself.
328 : : *
329 : : * Any callback attached to the returned #GSource must have type
330 : : * #GUnixFDSourceFunc.
331 : : *
332 : : * Returns: the newly created #GSource
333 : : *
334 : : * Since: 2.36
335 : : **/
336 : : GSource *
337 : 628 : g_unix_fd_source_new (gint fd,
338 : : GIOCondition condition)
339 : : {
340 : : GUnixFDSource *fd_source;
341 : : GSource *source;
342 : :
343 : 628 : source = g_source_new (&g_unix_fd_source_funcs, sizeof (GUnixFDSource));
344 : 628 : fd_source = (GUnixFDSource *) source;
345 : :
346 : 628 : fd_source->fd = fd;
347 : 628 : fd_source->tag = g_source_add_unix_fd (source, fd, condition);
348 : :
349 : 628 : return source;
350 : : }
351 : :
352 : : /**
353 : : * g_unix_fd_add_full:
354 : : * @priority: the priority of the source
355 : : * @fd: a file descriptor
356 : : * @condition: IO conditions to watch for on @fd
357 : : * @function: a #GUnixFDSourceFunc
358 : : * @user_data: data to pass to @function
359 : : * @notify: function to call when the idle is removed, or %NULL
360 : : *
361 : : * Sets a function to be called when the IO condition, as specified by
362 : : * @condition becomes true for @fd.
363 : : *
364 : : * This is the same as g_unix_fd_add(), except that it allows you to
365 : : * specify a non-default priority and a provide a #GDestroyNotify for
366 : : * @user_data.
367 : : *
368 : : * Returns: the ID (greater than 0) of the event source
369 : : *
370 : : * Since: 2.36
371 : : **/
372 : : guint
373 : 2 : g_unix_fd_add_full (gint priority,
374 : : gint fd,
375 : : GIOCondition condition,
376 : : GUnixFDSourceFunc function,
377 : : gpointer user_data,
378 : : GDestroyNotify notify)
379 : : {
380 : : GSource *source;
381 : : guint id;
382 : :
383 : 2 : g_return_val_if_fail (function != NULL, 0);
384 : :
385 : 2 : source = g_unix_fd_source_new (fd, condition);
386 : :
387 : 2 : if (priority != G_PRIORITY_DEFAULT)
388 : 1 : g_source_set_priority (source, priority);
389 : :
390 : 2 : g_source_set_callback (source, (GSourceFunc) function, user_data, notify);
391 : 2 : id = g_source_attach (source, NULL);
392 : 2 : g_source_unref (source);
393 : :
394 : 2 : return id;
395 : : }
396 : :
397 : : /**
398 : : * g_unix_fd_add:
399 : : * @fd: a file descriptor
400 : : * @condition: IO conditions to watch for on @fd
401 : : * @function: a #GUnixFDSourceFunc
402 : : * @user_data: data to pass to @function
403 : : *
404 : : * Sets a function to be called when the IO condition, as specified by
405 : : * @condition becomes true for @fd.
406 : : *
407 : : * @function will be called when the specified IO condition becomes
408 : : * %TRUE. The function is expected to clear whatever event caused the
409 : : * IO condition to become true and return %TRUE in order to be notified
410 : : * when it happens again. If @function returns %FALSE then the watch
411 : : * will be cancelled.
412 : : *
413 : : * The return value of this function can be passed to g_source_remove()
414 : : * to cancel the watch at any time that it exists.
415 : : *
416 : : * The source will never close the fd -- you must do it yourself.
417 : : *
418 : : * Returns: the ID (greater than 0) of the event source
419 : : *
420 : : * Since: 2.36
421 : : **/
422 : : guint
423 : 1 : g_unix_fd_add (gint fd,
424 : : GIOCondition condition,
425 : : GUnixFDSourceFunc function,
426 : : gpointer user_data)
427 : : {
428 : 1 : return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL);
429 : : }
430 : :
431 : : /**
432 : : * g_unix_get_passwd_entry:
433 : : * @user_name: the username to get the passwd file entry for
434 : : * @error: return location for a #GError, or %NULL
435 : : *
436 : : * Get the `passwd` file entry for the given @user_name using `getpwnam_r()`.
437 : : * This can fail if the given @user_name doesn’t exist.
438 : : *
439 : : * The returned `struct passwd` has been allocated using g_malloc() and should
440 : : * be freed using g_free(). The strings referenced by the returned struct are
441 : : * included in the same allocation, so are valid until the `struct passwd` is
442 : : * freed.
443 : : *
444 : : * This function is safe to call from multiple threads concurrently.
445 : : *
446 : : * You will need to include `pwd.h` to get the definition of `struct passwd`.
447 : : *
448 : : * Returns: (transfer full): passwd entry, or %NULL on error; free the returned
449 : : * value with g_free()
450 : : * Since: 2.64
451 : : */
452 : : struct passwd *
453 : 3 : g_unix_get_passwd_entry (const gchar *user_name,
454 : : GError **error)
455 : : {
456 : : struct passwd *passwd_file_entry;
457 : : struct
458 : : {
459 : : struct passwd pwd;
460 : : char string_buffer[];
461 : 3 : } *buffer = NULL;
462 : 3 : gsize string_buffer_size = 0;
463 : 3 : GError *local_error = NULL;
464 : :
465 : 3 : g_return_val_if_fail (user_name != NULL, NULL);
466 : 3 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
467 : :
468 : : #ifdef _SC_GETPW_R_SIZE_MAX
469 : : {
470 : : /* Get the recommended buffer size */
471 : 3 : glong string_buffer_size_long = sysconf (_SC_GETPW_R_SIZE_MAX);
472 : 3 : if (string_buffer_size_long > 0)
473 : 3 : string_buffer_size = string_buffer_size_long;
474 : : }
475 : : #endif /* _SC_GETPW_R_SIZE_MAX */
476 : :
477 : : /* Default starting size. */
478 : 3 : if (string_buffer_size == 0)
479 : 0 : string_buffer_size = 64;
480 : :
481 : : do
482 : : {
483 : : int retval;
484 : :
485 : 3 : g_free (buffer);
486 : : /* Allocate space for the `struct passwd`, and then a buffer for all its
487 : : * strings (whose size is @string_buffer_size, which increases in this
488 : : * loop until it’s big enough). Add 6 extra bytes to work around a bug in
489 : : * macOS < 10.3. See #156446.
490 : : */
491 : 3 : buffer = g_malloc0 (sizeof (*buffer) + string_buffer_size + 6);
492 : :
493 : 3 : retval = getpwnam_r (user_name, &buffer->pwd, buffer->string_buffer,
494 : : string_buffer_size, &passwd_file_entry);
495 : :
496 : : /* Bail out if: the lookup was successful, or if the user id can't be
497 : : * found (should be pretty rare case actually), or if the buffer should be
498 : : * big enough and yet lookups are still not successful.
499 : : */
500 : 3 : if (passwd_file_entry != NULL)
501 : : {
502 : : /* Success. */
503 : 1 : break;
504 : : }
505 : 2 : else if (retval == 0 ||
506 : 0 : retval == ENOENT || retval == ESRCH ||
507 : 0 : retval == EBADF || retval == EPERM)
508 : : {
509 : : /* Username not found. */
510 : 2 : g_unix_set_error_from_errno (&local_error, retval);
511 : 2 : break;
512 : : }
513 : 0 : else if (retval == ERANGE)
514 : : {
515 : : /* Can’t allocate enough string buffer space. */
516 : 0 : if (string_buffer_size > 32 * 1024)
517 : : {
518 : 0 : g_unix_set_error_from_errno (&local_error, retval);
519 : 0 : break;
520 : : }
521 : :
522 : 0 : string_buffer_size *= 2;
523 : 0 : continue;
524 : : }
525 : : else
526 : : {
527 : 0 : g_unix_set_error_from_errno (&local_error, retval);
528 : 0 : break;
529 : : }
530 : : }
531 : 0 : while (passwd_file_entry == NULL);
532 : :
533 : 3 : g_assert (passwd_file_entry == NULL ||
534 : : (gpointer) passwd_file_entry == (gpointer) buffer);
535 : :
536 : : /* Success or error. */
537 : 3 : if (local_error != NULL)
538 : : {
539 : 2 : g_clear_pointer (&buffer, g_free);
540 : 2 : g_propagate_error (error, g_steal_pointer (&local_error));
541 : : }
542 : :
543 : 3 : return (struct passwd *) g_steal_pointer (&buffer);
544 : : }
545 : :
546 : : /* This function is called between fork() and exec() and hence must be
547 : : * async-signal-safe (see signal-safety(7)). */
548 : : static int
549 : 0 : set_cloexec (void *data, gint fd)
550 : : {
551 : 0 : if (fd >= GPOINTER_TO_INT (data))
552 : 0 : fcntl (fd, F_SETFD, FD_CLOEXEC);
553 : :
554 : 0 : return 0;
555 : : }
556 : :
557 : : /* fdwalk()-compatible callback to close a fd for non-compliant
558 : : * implementations of fdwalk() that potentially pass already
559 : : * closed fds.
560 : : *
561 : : * It is not an error to pass an invalid fd to this function.
562 : : *
563 : : * This function is called between fork() and exec() and hence must be
564 : : * async-signal-safe (see signal-safety(7)).
565 : : */
566 : : G_GNUC_UNUSED static int
567 : 0 : close_func_with_invalid_fds (void *data, int fd)
568 : : {
569 : : /* We use close and not g_close here because on some platforms, we
570 : : * don't know how to close only valid, open file descriptors, so we
571 : : * have to pass bad fds to close too. g_close warns if given a bad
572 : : * fd.
573 : : *
574 : : * This function returns no error, because there is nothing that the caller
575 : : * could do with that information. That is even the case for EINTR. See
576 : : * g_close() about the specialty of EINTR and why that is correct.
577 : : * If g_close() ever gets extended to handle EINTR specially, then this place
578 : : * should get updated to do the same handling.
579 : : */
580 : 0 : if (fd >= GPOINTER_TO_INT (data))
581 : 0 : close (fd);
582 : :
583 : 0 : return 0;
584 : : }
585 : :
586 : : #ifdef __linux__
587 : : struct linux_dirent64
588 : : {
589 : : guint64 d_ino; /* 64-bit inode number */
590 : : guint64 d_off; /* 64-bit offset to next structure */
591 : : unsigned short d_reclen; /* Size of this dirent */
592 : : unsigned char d_type; /* File type */
593 : : char d_name[]; /* Filename (null-terminated) */
594 : : };
595 : :
596 : : /* This function is called between fork() and exec() and hence must be
597 : : * async-signal-safe (see signal-safety(7)). */
598 : : static gint
599 : 0 : filename_to_fd (const char *p)
600 : : {
601 : : char c;
602 : 0 : int fd = 0;
603 : 0 : const int cutoff = G_MAXINT / 10;
604 : 0 : const int cutlim = G_MAXINT % 10;
605 : :
606 : 0 : if (*p == '\0')
607 : 0 : return -1;
608 : :
609 : 0 : while ((c = *p++) != '\0')
610 : : {
611 : 0 : if (c < '0' || c > '9')
612 : 0 : return -1;
613 : 0 : c -= '0';
614 : :
615 : : /* Check for overflow. */
616 : 0 : if (fd > cutoff || (fd == cutoff && c > cutlim))
617 : 0 : return -1;
618 : :
619 : 0 : fd = fd * 10 + c;
620 : : }
621 : :
622 : 0 : return fd;
623 : : }
624 : : #endif
625 : :
626 : : static int safe_fdwalk_with_invalid_fds (int (*cb)(void *data, int fd), void *data);
627 : :
628 : : /* This function is called between fork() and exec() and hence must be
629 : : * async-signal-safe (see signal-safety(7)). */
630 : : static int
631 : 0 : safe_fdwalk (int (*cb)(void *data, int fd), void *data)
632 : : {
633 : : #if 0
634 : : /* Use fdwalk function provided by the system if it is known to be
635 : : * async-signal safe.
636 : : *
637 : : * Currently there are no operating systems known to provide a safe
638 : : * implementation, so this section is not used for now.
639 : : */
640 : : return fdwalk (cb, data);
641 : : #else
642 : : /* Fallback implementation of fdwalk. It should be async-signal safe, but it
643 : : * may fail on non-Linux operating systems. See safe_fdwalk_with_invalid_fds
644 : : * for a slower alternative.
645 : : */
646 : :
647 : : #ifdef __linux__
648 : : gint fd;
649 : 0 : gint res = 0;
650 : :
651 : : /* Avoid use of opendir/closedir since these are not async-signal-safe. */
652 : 0 : int dir_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY);
653 : 0 : if (dir_fd >= 0)
654 : : {
655 : : /* buf needs to be aligned correctly to receive linux_dirent64.
656 : : * C11 has _Alignof for this purpose, but for now a
657 : : * union serves the same purpose. */
658 : : union
659 : : {
660 : : char buf[4096];
661 : : struct linux_dirent64 alignment;
662 : : } u;
663 : : int pos, nread;
664 : : struct linux_dirent64 *de;
665 : :
666 : 0 : while ((nread = syscall (SYS_getdents64, dir_fd, u.buf, sizeof (u.buf))) > 0)
667 : : {
668 : 0 : for (pos = 0; pos < nread; pos += de->d_reclen)
669 : : {
670 : 0 : de = (struct linux_dirent64 *) (u.buf + pos);
671 : :
672 : 0 : fd = filename_to_fd (de->d_name);
673 : 0 : if (fd < 0 || fd == dir_fd)
674 : 0 : continue;
675 : :
676 : 0 : if ((res = cb (data, fd)) != 0)
677 : 0 : break;
678 : : }
679 : : }
680 : :
681 : 0 : g_close (dir_fd, NULL);
682 : 0 : return res;
683 : : }
684 : :
685 : : /* If /proc is not mounted or not accessible we fail here and rely on
686 : : * safe_fdwalk_with_invalid_fds to fall back to the old
687 : : * rlimit trick. */
688 : :
689 : : #endif
690 : :
691 : : #if defined(__sun__) && defined(F_PREVFD) && defined(F_NEXTFD)
692 : : /*
693 : : * Solaris 11.4 has a signal-safe way which allows
694 : : * us to find all file descriptors in a process.
695 : : *
696 : : * fcntl(fd, F_NEXTFD, maxfd)
697 : : * - returns the first allocated file descriptor <= maxfd > fd.
698 : : *
699 : : * fcntl(fd, F_PREVFD)
700 : : * - return highest allocated file descriptor < fd.
701 : : */
702 : : gint open_max;
703 : : gint fd;
704 : : gint res = 0;
705 : :
706 : : open_max = fcntl (INT_MAX, F_PREVFD); /* find the maximum fd */
707 : : if (open_max < 0) /* No open files */
708 : : return 0;
709 : :
710 : : for (fd = -1; (fd = fcntl (fd, F_NEXTFD, open_max)) != -1; )
711 : : if ((res = cb (data, fd)) != 0 || fd == open_max)
712 : : break;
713 : :
714 : : return res;
715 : : #endif
716 : :
717 : 0 : return safe_fdwalk_with_invalid_fds (cb, data);
718 : : #endif
719 : : }
720 : :
721 : : /* This function is called between fork() and exec() and hence must be
722 : : * async-signal-safe (see signal-safety(7)). */
723 : : static int
724 : 0 : safe_fdwalk_with_invalid_fds (int (*cb)(void *data, int fd), void *data)
725 : : {
726 : : /* Fallback implementation of fdwalk. It should be async-signal safe, but it
727 : : * may be slow, especially on systems allowing very high number of open file
728 : : * descriptors.
729 : : */
730 : 0 : gint open_max = -1;
731 : : gint fd;
732 : 0 : gint res = 0;
733 : :
734 : : #if 0 && defined(HAVE_SYS_RESOURCE_H)
735 : : struct rlimit rl;
736 : :
737 : : /* Use getrlimit() function provided by the system if it is known to be
738 : : * async-signal safe.
739 : : *
740 : : * Currently there are no operating systems known to provide a safe
741 : : * implementation, so this section is not used for now.
742 : : */
743 : : if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
744 : : open_max = rl.rlim_max;
745 : : #endif
746 : : #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
747 : : /* Use sysconf() function provided by the system if it is known to be
748 : : * async-signal safe.
749 : : *
750 : : * FreeBSD: sysconf() is included in the list of async-signal safe functions
751 : : * found in https://man.freebsd.org/sigaction(2).
752 : : *
753 : : * OpenBSD: sysconf() is included in the list of async-signal safe functions
754 : : * found in https://man.openbsd.org/sigaction.2.
755 : : *
756 : : * Apple: sysconf() is included in the list of async-signal safe functions
757 : : * found in https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man2/sigaction.2
758 : : */
759 : : if (open_max < 0)
760 : : open_max = sysconf (_SC_OPEN_MAX);
761 : : #endif
762 : : /* Hardcoded fallback: the default process hard limit in Linux as of 2020 */
763 : 0 : if (open_max < 0)
764 : 0 : open_max = 4096;
765 : :
766 : : #if defined(__APPLE__) && defined(HAVE_LIBPROC_H)
767 : : /* proc_pidinfo isn't documented as async-signal-safe but looking at the implementation
768 : : * in the darwin tree here:
769 : : *
770 : : * https://opensource.apple.com/source/Libc/Libc-498/darwin/libproc.c.auto.html
771 : : *
772 : : * It's just a thin wrapper around a syscall, so it's probably okay.
773 : : */
774 : : {
775 : : char buffer[4096 * PROC_PIDLISTFD_SIZE];
776 : : ssize_t buffer_size;
777 : :
778 : : buffer_size = proc_pidinfo (getpid (), PROC_PIDLISTFDS, 0, buffer, sizeof (buffer));
779 : :
780 : : if (buffer_size > 0 &&
781 : : sizeof (buffer) >= (size_t) buffer_size &&
782 : : (buffer_size % PROC_PIDLISTFD_SIZE) == 0)
783 : : {
784 : : const struct proc_fdinfo *fd_info = (const struct proc_fdinfo *) buffer;
785 : : size_t number_of_fds = (size_t) buffer_size / PROC_PIDLISTFD_SIZE;
786 : :
787 : : for (size_t i = 0; i < number_of_fds; i++)
788 : : if ((res = cb (data, fd_info[i].proc_fd)) != 0)
789 : : break;
790 : :
791 : : return res;
792 : : }
793 : : }
794 : : #endif
795 : :
796 : 0 : for (fd = 0; fd < open_max; fd++)
797 : 0 : if ((res = cb (data, fd)) != 0)
798 : 0 : break;
799 : :
800 : 0 : return res;
801 : : }
802 : :
803 : : /**
804 : : * g_fdwalk_set_cloexec:
805 : : * @lowfd: Minimum fd to act on, which must be non-negative
806 : : *
807 : : * Mark every file descriptor equal to or greater than @lowfd to be closed
808 : : * at the next `execve()` or similar, as if via the `FD_CLOEXEC` flag.
809 : : *
810 : : * Typically @lowfd will be 3, to leave standard input, standard output
811 : : * and standard error open after exec.
812 : : *
813 : : * This is the same as Linux `close_range (lowfd, ~0U, CLOSE_RANGE_CLOEXEC)`,
814 : : * but portable to other OSs and to older versions of Linux.
815 : : *
816 : : * This function is async-signal safe, making it safe to call from a
817 : : * signal handler or a [callback@GLib.SpawnChildSetupFunc], as long as @lowfd is
818 : : * non-negative.
819 : : * See [`signal(7)`](man:signal(7)) and
820 : : * [`signal-safety(7)`](man:signal-safety(7)) for more details.
821 : : *
822 : : * Returns: 0 on success, -1 with errno set on error
823 : : * Since: 2.80
824 : : */
825 : : int
826 : 9 : g_fdwalk_set_cloexec (int lowfd)
827 : : {
828 : : int ret;
829 : :
830 : 9 : g_return_val_if_fail (lowfd >= 0, (errno = EINVAL, -1));
831 : :
832 : : #if defined(HAVE_CLOSE_RANGE) && defined(CLOSE_RANGE_CLOEXEC)
833 : : /* close_range() is available in Linux since kernel 5.9, and on FreeBSD at
834 : : * around the same time. It was designed for use in async-signal-safe
835 : : * situations: https://bugs.python.org/issue38061
836 : : *
837 : : * The `CLOSE_RANGE_CLOEXEC` flag was added in Linux 5.11, and is not yet
838 : : * present in FreeBSD.
839 : : *
840 : : * Handle ENOSYS in case it’s supported in libc but not the kernel; if so,
841 : : * fall back to safe_fdwalk(). Handle EINVAL in case `CLOSE_RANGE_CLOEXEC`
842 : : * is not supported. */
843 : 8 : ret = close_range (lowfd, G_MAXUINT, CLOSE_RANGE_CLOEXEC);
844 : 8 : if (ret == 0 || !(errno == ENOSYS || errno == EINVAL))
845 : 8 : return ret;
846 : : #endif /* HAVE_CLOSE_RANGE */
847 : :
848 : 0 : ret = safe_fdwalk (set_cloexec, GINT_TO_POINTER (lowfd));
849 : :
850 : 0 : return ret;
851 : : }
852 : :
853 : : /**
854 : : * g_closefrom:
855 : : * @lowfd: Minimum fd to close, which must be non-negative
856 : : *
857 : : * Close every file descriptor equal to or greater than @lowfd.
858 : : *
859 : : * Typically @lowfd will be 3, to leave standard input, standard output
860 : : * and standard error open.
861 : : *
862 : : * This is the same as Linux `close_range (lowfd, ~0U, 0)`,
863 : : * but portable to other OSs and to older versions of Linux.
864 : : * Equivalently, it is the same as BSD `closefrom (lowfd)`, but portable,
865 : : * and async-signal-safe on all OSs.
866 : : *
867 : : * This function is async-signal safe, making it safe to call from a
868 : : * signal handler or a [callback@GLib.SpawnChildSetupFunc], as long as @lowfd is
869 : : * non-negative.
870 : : * See [`signal(7)`](man:signal(7)) and
871 : : * [`signal-safety(7)`](man:signal-safety(7)) for more details.
872 : : *
873 : : * Returns: 0 on success, -1 with errno set on error
874 : : * Since: 2.80
875 : : */
876 : : int
877 : 958 : g_closefrom (int lowfd)
878 : : {
879 : : int ret;
880 : :
881 : 958 : g_return_val_if_fail (lowfd >= 0, (errno = EINVAL, -1));
882 : :
883 : : #if defined(HAVE_CLOSE_RANGE)
884 : : /* close_range() is available in Linux since kernel 5.9, and on FreeBSD at
885 : : * around the same time. It was designed for use in async-signal-safe
886 : : * situations: https://bugs.python.org/issue38061
887 : : *
888 : : * Handle ENOSYS in case it’s supported in libc but not the kernel; if so,
889 : : * fall back to safe_fdwalk(). */
890 : 957 : ret = close_range (lowfd, G_MAXUINT, 0);
891 : 957 : if (ret == 0 || errno != ENOSYS)
892 : 957 : return ret;
893 : : #endif /* HAVE_CLOSE_RANGE */
894 : :
895 : : #if defined(__FreeBSD__) || defined(__OpenBSD__) || \
896 : : (defined(__sun__) && defined(F_CLOSEFROM))
897 : : /* Use closefrom function provided by the system if it is known to be
898 : : * async-signal safe.
899 : : *
900 : : * FreeBSD: closefrom is included in the list of async-signal safe functions
901 : : * found in https://man.freebsd.org/sigaction(2).
902 : : *
903 : : * OpenBSD: closefrom is not included in the list, but a direct system call
904 : : * should be safe to use.
905 : : *
906 : : * In Solaris as of 11.3 SRU 31, closefrom() is also a direct system call.
907 : : * On such systems, F_CLOSEFROM is defined.
908 : : */
909 : : (void) closefrom (lowfd);
910 : : return 0;
911 : : #elif defined(__DragonFly__)
912 : : /* It is unclear whether closefrom function included in DragonFlyBSD libc_r
913 : : * is safe to use because it calls a lot of library functions. It is also
914 : : * unclear whether libc_r itself is still being used. Therefore, we do a
915 : : * direct system call here ourselves to avoid possible issues.
916 : : */
917 : : (void) syscall (SYS_closefrom, lowfd);
918 : : return 0;
919 : : #elif defined(F_CLOSEM)
920 : : /* NetBSD and AIX have a special fcntl command which does the same thing as
921 : : * closefrom. NetBSD also includes closefrom function, which seems to be a
922 : : * simple wrapper of the fcntl command.
923 : : */
924 : : return fcntl (lowfd, F_CLOSEM);
925 : : #else
926 : 0 : ret = safe_fdwalk (close_func_with_invalid_fds, GINT_TO_POINTER (lowfd));
927 : :
928 : 0 : return ret;
929 : : #endif
930 : : }
|